shipbob-node-sdk 0.0.2 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -3,7 +3,7 @@ First of all there are no official SDKs for ShipBob. I'm just dropping this her
3
3
 
4
4
  These is just a starting point for anybody looking to integrate ShipBob into a Node.js application.
5
5
 
6
- You could make it run in the browser by replacing `https` with `fetch` or `axios`. I could have used fetch as well, but in case somebody is on Node < v18 (and it wasn't stable till v21 anyway).
6
+ It uses the built-in node.js fetch.
7
7
 
8
8
  This is not an official or supported library. If you extend or have any issues kindly open a PR. Not really sure anybody will ever need this as most common platforms probably have built-in support.
9
9
 
@@ -52,10 +52,17 @@ SHIPBOB_API_TOKEN=<redacted>
52
52
  - [x] Get logs for one Shipment by Shipment Id
53
53
  - [?] Get shipping methods (hard-code shipping methods?)
54
54
 
55
- ## Products
56
- - [✓] Get multiple products: api.getProducts(...)
57
- - [✓] Add a single product to the store: api.addProduct(...)
58
- - [ ] Modify a single product (we will need this to add multiple barcodes)
55
+ ## Products 1.0
56
+ - [✓] Get multiple products: api.getProducts1_0(...)
57
+ - [✓] Add a single product to the store: api.createProduct1_0(...)
58
+ - [x] Modify a single product (using 2.0 for additional properties)
59
+ - [x] Add multiple products to the store
60
+
61
+ ## Products 2.0
62
+ These are not documented on the site yet.
63
+ - [✓] Get multiple products: api.getProducts2_0(...)
64
+ - [✓] Add a single product to the store: api.createProduct2_0(...)
65
+ - [✓] Modify a single product: api.updateProducts2_0(..,)
59
66
  - [x] Add multiple products to the store
60
67
 
61
68
  ## Inventory
package/dist/index.d.ts CHANGED
@@ -72,10 +72,218 @@ export type AddProductResponse = {
72
72
  id: number;
73
73
  reference_id: string;
74
74
  };
75
- export type GetProductResult = {
75
+ /**
76
+ * This is missing practically all fields of actual result.
77
+ */
78
+ export type GetProduct1_0Result = {
76
79
  id: number;
77
80
  reference_id: string;
78
81
  };
82
+ export type ActionName = 'Dispose' | 'Restock' | 'Quarantine';
83
+ export type ProductType = 'Regular' | 'Bundle';
84
+ /**
85
+ * This is just some guessing based on a response
86
+ */
87
+ export type GetProduct2_0Result = {
88
+ /**
89
+ * Product Id
90
+ */
91
+ id: number;
92
+ /**
93
+ * Product Name
94
+ */
95
+ name: string;
96
+ type: ProductType;
97
+ category: Nullable<unknown>;
98
+ sub_category: Nullable<unknown>;
99
+ user_id: number;
100
+ created_on: string;
101
+ updated_on: string;
102
+ /**
103
+ * null | ?
104
+ */
105
+ taxonomy: null;
106
+ variants: {
107
+ /**
108
+ * The expected barcode to be found on the item and checked during the pick process
109
+ */
110
+ barcode: string;
111
+ barcode_sticker_url: Nullable<string>;
112
+ channel_metadata: unknown[];
113
+ reviews_pending: unknown[];
114
+ associated_bundles: unknown[];
115
+ bundle_definition: unknown[];
116
+ created_on: string;
117
+ customs: {
118
+ /**
119
+ * The customs code (6 digit)
120
+ */
121
+ hs_tariff_code: string;
122
+ /**
123
+ * 2 character country code
124
+ */
125
+ country_code_of_origin: string;
126
+ /**
127
+ * Value of object for customs (in USD)
128
+ */
129
+ value: Nullable<string>;
130
+ currency: 'USD';
131
+ /**
132
+ * Description of product for customs purposes
133
+ */
134
+ description: string;
135
+ is321_eligible: boolean;
136
+ };
137
+ dimension: {
138
+ length: number;
139
+ width: number;
140
+ height: number;
141
+ /**
142
+ * "inch"
143
+ */
144
+ unit: string;
145
+ is_locked: boolean;
146
+ /**
147
+ * ie: "UserEntry"
148
+ */
149
+ source: string;
150
+ };
151
+ fulfillment_settings: {
152
+ /**
153
+ * If the product requires a prop65 label in the box
154
+ */
155
+ requires_prop65: false;
156
+ serial_scan: {
157
+ /**
158
+ * Indicates if a Serial Scan is required during the pack process.
159
+ * Note: Serial scan requires either a prefix or a suffix to be defined
160
+ */
161
+ is_enabled: false;
162
+ /**
163
+ * The prefix expected on the serial number
164
+ */
165
+ prefix: string;
166
+ /**
167
+ * The suffix expected on the serial number
168
+ */
169
+ suffix: string;
170
+ /**
171
+ * The exact number of characters expected in the serial number
172
+ */
173
+ exact_character_length: Nullable<number>;
174
+ };
175
+ /**
176
+ * If the product needs to classified as a hazmat product with the shipping carrier
177
+ */
178
+ dangerous_goods: false;
179
+ /**
180
+ * URL of the Safety Data Sheet for this product.
181
+ * Note: should be populated by ShipBob system via the UI, should not reference a URL outside of the ShipBob domain
182
+ */
183
+ msds_url: string;
184
+ /**
185
+ * If the product should be picked as an entire case
186
+ */
187
+ is_case_pick: boolean;
188
+ /**
189
+ * Is Bound Printed Matter, must be set by the ShipBob internal team
190
+ */
191
+ is_bpm_parcel: boolean;
192
+ };
193
+ /**
194
+ * Global Trade Item Number
195
+ */
196
+ gtin: string;
197
+ /**
198
+ * Variant Id (used to alter product lot, packaging, etc.)
199
+ */
200
+ id: number;
201
+ inventory: {
202
+ inventory_id: number;
203
+ on_hand_qty: number;
204
+ };
205
+ is_digital: boolean;
206
+ lot_information: {
207
+ /**
208
+ * If the product should use lot date based picking
209
+ */
210
+ is_lot: boolean;
211
+ minimum_shelf_life_days: Nullable<number>;
212
+ };
213
+ /**
214
+ * Name of the Variant (should match the Product name if a non-varying product)
215
+ */
216
+ name: string;
217
+ /**
218
+ * PDf has wrong field: The specific material to package the product in (box, poly mailer, bubble mailer, etc_
219
+ */
220
+ packaging_material_type: {
221
+ id: number;
222
+ /**
223
+ * Not sure what else can be here
224
+ */
225
+ name: 'Box';
226
+ };
227
+ /**
228
+ * PDF has wrong field. int The id of the packaging_requirement (No requirement, fragile, ship in own container, etc)
229
+ */
230
+ packaging_requirement: {
231
+ id: number;
232
+ name: 'NoRequirements' | 'Fragile';
233
+ };
234
+ return_preferences: {
235
+ /**
236
+ * Restock (1) Quarantine (2) Dispose (3)
237
+ */
238
+ primary_action: Nullable<{
239
+ id: number;
240
+ name: ActionName;
241
+ }>;
242
+ /**
243
+ * Restock (1) Quarantine (2) Dispose (3)
244
+ */
245
+ backup_action: Nullable<{
246
+ id: number;
247
+ name: ActionName;
248
+ }>;
249
+ /**
250
+ * Instructions for inspecting returns
251
+ */
252
+ instructions: Nullable<string>;
253
+ return_to_sender_primary_action: Nullable<{
254
+ id: number;
255
+ name: ActionName;
256
+ }>;
257
+ return_to_sender_backup_action: Nullable<{
258
+ id: number;
259
+ name: ActionName;
260
+ }>;
261
+ };
262
+ /**
263
+ * The SKU of the product. This is a required field and must be unique.
264
+ */
265
+ sku: string;
266
+ /**
267
+ * PDF is incorrect - it describes in int. Active (1) or Inactive (2)
268
+ */
269
+ status: 'Active' | 'Inactive';
270
+ /**
271
+ * Universal Product Code
272
+ */
273
+ upc: string;
274
+ is_image_uploaded: false;
275
+ updated_on: string;
276
+ weight: {
277
+ weight: number;
278
+ /**
279
+ * ie: "oz"
280
+ */
281
+ unit: string;
282
+ };
283
+ additional_hazmat_attributes: Nullable<unknown>;
284
+ merge_children: [];
285
+ }[];
286
+ };
79
287
  export type OrderType = 'DTC' | 'DropShip' | 'B2B' | 'Transportation';
80
288
  export type AnyProduct = ({
81
289
  /**
@@ -627,6 +835,103 @@ export type WarehouseReceivingOrderBoxesResponse = {
627
835
  lot_date: Nullable<string>;
628
836
  }[];
629
837
  }[];
838
+ export declare enum PackagingRequirement {
839
+ 'No Requirements' = 1,
840
+ Fragile = 2,
841
+ 'Is Foldable' = 3,
842
+ 'Is Media (Media mail)' = 4,
843
+ 'Is Book' = 5,
844
+ 'Is Poster' = 6,
845
+ 'Is Apparel' = 7,
846
+ 'Is Packaging Material (for custom boxes, marketing inserts, etc)' = 8,
847
+ 'Ship In Own Container' = 9
848
+ }
849
+ export declare enum PackagingMaterial {
850
+ 'Box' = 1,
851
+ 'Bubble Mailer' = 2,
852
+ 'Poly Mailer' = 3,
853
+ 'Poster Tube' = 5,
854
+ 'Custom Box' = 6,
855
+ 'Bookfold' = 7,
856
+ 'Ship In Own Container' = 8,
857
+ 'Custom Bubble Mailer' = 9,
858
+ 'Custom Poly Mailer' = 10
859
+ }
860
+ /**
861
+ * Restock (1)
862
+ * Quarantine (2)
863
+ * Dispose (3)
864
+ */
865
+ export declare enum ReturnAction {
866
+ /**
867
+ * Restock (1)
868
+ */
869
+ Restock = 1,
870
+ /**
871
+ * Quarantine (2)
872
+ */
873
+ Quarantine = 2,
874
+ /**
875
+ * Dispose (3)
876
+ */
877
+ Dispose = 3
878
+ }
879
+ export type ProductVariantRequest = {
880
+ /**
881
+ * Required for updates
882
+ */
883
+ id?: number;
884
+ name?: string;
885
+ sku?: string;
886
+ /**
887
+ * will serialize as a number
888
+ */
889
+ packaging_requirement_id?: PackagingRequirement;
890
+ /**
891
+ * will serialize as a number
892
+ */
893
+ packaging_material_type_id?: PackagingMaterial;
894
+ barcode?: string;
895
+ upc?: string;
896
+ gtin?: string;
897
+ customs?: {
898
+ /**
899
+ * 2 character country code
900
+ */
901
+ country_code_of_origin: 'US';
902
+ /**
903
+ * The customs code (6 digit)
904
+ * ie: “6103.22”
905
+ */
906
+ hs_tariff_code: string;
907
+ /**
908
+ * Value of object for customs (in USD)
909
+ * ie: “15”
910
+ */
911
+ value: string;
912
+ /**
913
+ * Description of product for customs purposes
914
+ */
915
+ description: string;
916
+ };
917
+ /**
918
+ * Not sure if these can be partially supplied.
919
+ */
920
+ return_preferences?: {
921
+ primary_action_id: Nullable<ReturnAction>;
922
+ backup_action_id: null;
923
+ instructions: Nullable<string>;
924
+ return_to_sender_primary_action_id: Nullable<ReturnAction>;
925
+ return_to_sender_backup_action_id: Nullable<ReturnAction>;
926
+ };
927
+ lot_information: {
928
+ /**
929
+ * If the product should use lot date based picking
930
+ */
931
+ is_lot: boolean;
932
+ minimum_shelf_life_days: Nullable<number>;
933
+ };
934
+ };
630
935
  /**
631
936
  * Create API with PAT (personal access token) - defaults to sandbox endpoints and "SMA" channel.
632
937
  *
@@ -640,8 +945,8 @@ export type WarehouseReceivingOrderBoxesResponse = {
640
945
  * @returns
641
946
  */
642
947
  export declare const createShipBobApi: (personalAccessToken: string | undefined, apiBaseUrl?: string, channelApplicationName?: string) => Promise<{
643
- getProductById: (productId: number) => Promise<DataResponse<GetProductResult>>;
644
- getProducts: (query: Partial<{
948
+ getProductById: (productId: number) => Promise<DataResponse<GetProduct1_0Result>>;
949
+ getProducts1_0: (query: Partial<{
645
950
  ReferenceIds: string;
646
951
  Page: number;
647
952
  Limit: number;
@@ -649,13 +954,85 @@ export declare const createShipBobApi: (personalAccessToken: string | undefined,
649
954
  Search: string;
650
955
  ActiveStatus: "Any" | "Active" | "Inactive";
651
956
  BundleStatus: "Any" | "Bundle" | "NotBundle";
652
- }>) => Promise<DataResponse<GetProductResult[]>>;
653
- addProduct: (product: {
957
+ }>) => Promise<DataResponse<GetProduct1_0Result[]>>;
958
+ /**
959
+ * NOTE: we can probably pass more than "variants" prop. We could on the /1.0/product endpoint
960
+ * NOTE: This PATCH functionality will be available in the next version available in ShipBob next large release January 2025, it may require extra scope.
961
+ */
962
+ updateProducts2_0: (productId: number, variants: ProductVariantRequest[]) => Promise<DataResponse<AddProductResponse>>;
963
+ /**
964
+ * Not supported here, but:
965
+ * Some search filters allow for operators (equals, not equals, starts with, ends with, contains, etc) to get more exact values. When filtering with an operator, the query string will look like the below:
966
+ * Example: /product?{filter}={operator}:{value}
967
+ * Example: /product?sku=any:shirt-a,shirt-b,shirt-c Find products that match any of these SKUs
968
+ * Example: /product?onHandQuantity=gt:0 Find products where OnHandQty greater than 0
969
+ */
970
+ getProducts2_0: (query: Partial<{
971
+ Page: number;
972
+ Limit: number;
973
+ /**
974
+ * Regular product (1) or Bundle (2)
975
+ */
976
+ productTypeId: 1 | 2;
977
+ /**
978
+ * Active (1) or Inactive (2)
979
+ */
980
+ variantStatus: 1 | 2;
981
+ /**
982
+ * True -> at least one variant is digital
983
+ * False -> at least one variant is not-digital
984
+ */
985
+ hasDigitalVariants: boolean;
986
+ /**
987
+ * Search by one or more Product Ids (comma separated) to return multiple products
988
+ */
989
+ Ids: string;
990
+ /**
991
+ * Search by one or more Variant Ids (comma separated) to return multiple products
992
+ */
993
+ VariantIds: string;
994
+ /**
995
+ * Search by product barcode
996
+ */
997
+ barcode: string;
998
+ /**
999
+ * Search by an exact sku
1000
+ */
1001
+ sku: string;
1002
+ /**
1003
+ * Search for products that vary or non-varying products
1004
+ */
1005
+ hasVariants: boolean;
1006
+ /**
1007
+ * Search by one or more InventoryIds (comma separated) to return multiple barcodes
1008
+ */
1009
+ InventoryId: string;
1010
+ /**
1011
+ * Search by Variant Name.
1012
+ * NOTE: Query parameters should be URL encoded such as "Green%20Shirt"
1013
+ */
1014
+ Name: string;
1015
+ /**
1016
+ * Search by matching Taxonomy (category) of the product (comma separated)
1017
+ */
1018
+ TaxonomyIds: string;
1019
+ }>) => Promise<DataResponse<GetProduct2_0Result[]>>;
1020
+ createProduct1_0: (product: {
654
1021
  reference_id: string;
655
1022
  sku: string;
656
1023
  name: string;
657
1024
  barcode: string;
658
1025
  }) => Promise<DataResponse<AddProductResponse>>;
1026
+ /**
1027
+ * The request part for variant is not accurate. This is just for testing - there are no official docs.
1028
+ */
1029
+ createProduct2_0: (product: {
1030
+ reference_id: string;
1031
+ sku: string;
1032
+ type_id: number;
1033
+ name: string;
1034
+ variants: ProductVariantRequest[];
1035
+ }) => Promise<DataResponse<AddProductResponse>>;
659
1036
  placeOrder: (order: PlaceOrderRequest) => Promise<DataResponse<PlaceOrderResponse>>;
660
1037
  /**
661
1038
  * Cancel single Order by Order Id
@@ -669,10 +1046,13 @@ export declare const createShipBobApi: (personalAccessToken: string | undefined,
669
1046
  createWarehouseReceivingOrder: (request: WarehouseReceivingOrderRequest) => Promise<DataResponse<WarehouseReceivingOrderResponse>>;
670
1047
  getWarehouseReceivingOrder: (orderId: number) => Promise<DataResponse<WarehouseReceivingOrderResponse>>;
671
1048
  getWarehouseReceivingOrderBoxes: (orderId: number) => Promise<DataResponse<WarehouseReceivingOrderBoxesResponse>>;
1049
+ /**
1050
+ * NOTE: should verify that response matches 1.0 product endpoint
1051
+ */
672
1052
  getReceivingExtended: (query: Partial<{
673
1053
  Statuses: string;
674
1054
  ExternalSync: boolean;
675
- }>) => Promise<DataResponse<GetProductResult[]>>;
1055
+ }>) => Promise<DataResponse<GetProduct1_0Result[]>>;
676
1056
  /**
677
1057
  * This must be for setting/clearing if it has been synced externally.
678
1058
  *
@@ -681,6 +1061,9 @@ export declare const createShipBobApi: (personalAccessToken: string | undefined,
681
1061
  * NOTE: this is tagged experimental, so might change or be dropped
682
1062
  */
683
1063
  experimentalReceivingSetExternalSync: (ids: number[], isExternalSync: boolean) => Promise<DataResponse<SetExternalSyncResponse>>;
1064
+ /**
1065
+ * NOTE: should verify the response type matches the product 1.0 endpoint
1066
+ */
684
1067
  listInventory: (query: Partial<{
685
1068
  /**
686
1069
  * Page of inventory items to get
@@ -712,7 +1095,7 @@ export declare const createShipBobApi: (personalAccessToken: string | undefined,
712
1095
  * LocationType is valid for hub, spoke, or lts. LocationType will default to all locations.
713
1096
  */
714
1097
  LocationType: string;
715
- }>) => Promise<DataResponse<GetProductResult[]>>;
1098
+ }>) => Promise<DataResponse<GetProduct1_0Result[]>>;
716
1099
  /**
717
1100
  * Only for sandbox: https://developer.shipbob.com/sandbox-simulations/
718
1101
  *