freight-club 0.0.1
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/CHANGELOG.md +5 -0
- package/LICENSE +21 -0
- package/README.md +278 -0
- package/index.js +346 -0
- package/package.json +36 -0
package/CHANGELOG.md
ADDED
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Stores.com
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
# freight-club
|
|
2
|
+
|
|
3
|
+
[](https://github.com/stores-com/freight-club/actions?query=workflow%3ATest+branch%3Amain)
|
|
4
|
+
[](https://coveralls.io/github/stores-com/freight-club?branch=main)
|
|
5
|
+
[](https://www.npmjs.com/package/freight-club)
|
|
6
|
+
[](LICENSE)
|
|
7
|
+
|
|
8
|
+
The Freight Club API is an interface that allows you to set up an integrated experience between your daily operations and our application. APIs give you the ability to manage all your Parcel or LTL shipments with capabilities that include rating shipments, creating Bills of Lading or parcel labels, booking shipments with carriers and getting tracking information from those bookings.
|
|
9
|
+
|
|
10
|
+
https://api.freightclub.com/ApiDoc/index
|
|
11
|
+
|
|
12
|
+
## Requirements
|
|
13
|
+
|
|
14
|
+
Node.js 18 or later. This package uses the built-in `fetch` and has no HTTP dependency.
|
|
15
|
+
|
|
16
|
+
## Usage
|
|
17
|
+
|
|
18
|
+
```javascript
|
|
19
|
+
const FreightClub = require('freight-club');
|
|
20
|
+
|
|
21
|
+
const freightClub = new FreightClub({
|
|
22
|
+
api_token: 'your_api_token'
|
|
23
|
+
});
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
| Option | Default | Description |
|
|
27
|
+
| --- | --- | --- |
|
|
28
|
+
| `api_token` | | Freight Club API token, without the `Bearer ` prefix. Request one under Manage API Tokens in the Freight Club application, or use the testing token from the API documentation. |
|
|
29
|
+
| `timeout` | `60000` | Milliseconds to wait before aborting a request. Rating fans out to Freight Club's carrier network and waits up to 40 seconds (the `maxTime` default) for the slowest carrier. |
|
|
30
|
+
| `url` | `https://api.freightclub.com` | API endpoint. |
|
|
31
|
+
|
|
32
|
+
Every method that makes a request also accepts a `timeout` option, which overrides the constructor value for that call only.
|
|
33
|
+
|
|
34
|
+
```javascript
|
|
35
|
+
const response = await freightClub.getRates(request, { timeout: 45000 });
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Errors
|
|
39
|
+
|
|
40
|
+
A response other than 200 produces an [HttpError](https://www.npmjs.com/package/@stores.com/http-error), thrown from the promise.
|
|
41
|
+
|
|
42
|
+
```javascript
|
|
43
|
+
try {
|
|
44
|
+
await freightClub.bookShipment(request);
|
|
45
|
+
} catch (err) {
|
|
46
|
+
console.log(err.message); // '400 Bad Request'
|
|
47
|
+
console.log(err.cause.status); // 400
|
|
48
|
+
console.log(err.json); // the parsed response body
|
|
49
|
+
console.log(err.text); // the raw response body
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
A request that never reaches Freight Club — an unparseable `url`, a network failure, or a timeout — produces the error `fetch` itself raised, with no `cause.status`.
|
|
54
|
+
|
|
55
|
+
### freightClub.bookShipment(request, [options])
|
|
56
|
+
|
|
57
|
+
Supplying the quote number returned by GetRate and GetRates, this method books a shipment at that specific quoted rate with the chosen carrier. Carriers require a contact `Email` at booking (Error Code 13010), even though Freight Club's API documentation marks it optional.
|
|
58
|
+
|
|
59
|
+
**Example**
|
|
60
|
+
|
|
61
|
+
```javascript
|
|
62
|
+
const response = await freightClub.bookShipment({
|
|
63
|
+
OrderReferenceID: 'SALEID1660782849',
|
|
64
|
+
PickupDate: '2022-08-18',
|
|
65
|
+
Quote: '1151240419',
|
|
66
|
+
DropOffLocation: {
|
|
67
|
+
Address: {
|
|
68
|
+
Address1: '5678 Destination Street',
|
|
69
|
+
City: 'Action',
|
|
70
|
+
Country: 'US',
|
|
71
|
+
LocationType: 'Residential',
|
|
72
|
+
ProvinceState: 'MT',
|
|
73
|
+
ZipCode: '59002'
|
|
74
|
+
},
|
|
75
|
+
Contact: {
|
|
76
|
+
Email: 'recipient@example.com',
|
|
77
|
+
Firstname: 'Recipient',
|
|
78
|
+
Lastname: 'Person',
|
|
79
|
+
PhoneNumber: '5555555556'
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
PickupLocation: {
|
|
83
|
+
Address: {
|
|
84
|
+
Address1: '1234 Source Street',
|
|
85
|
+
City: 'Seattle',
|
|
86
|
+
Country: 'US',
|
|
87
|
+
LocationType: 'Commercial',
|
|
88
|
+
ProvinceState: 'WA',
|
|
89
|
+
ZipCode: '98101'
|
|
90
|
+
},
|
|
91
|
+
Contact: {
|
|
92
|
+
Email: 'sender@example.com',
|
|
93
|
+
Firstname: 'Sender',
|
|
94
|
+
Lastname: 'Person',
|
|
95
|
+
PhoneNumber: '5555555558'
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
ShipmentInformation: {
|
|
99
|
+
Boxes: [
|
|
100
|
+
{
|
|
101
|
+
Category: 'CasedGoodsFurniture',
|
|
102
|
+
DeclaredValue: {
|
|
103
|
+
Unit: 'USD',
|
|
104
|
+
Value: 500
|
|
105
|
+
},
|
|
106
|
+
Description: 'Pack of 4',
|
|
107
|
+
Dimension: {
|
|
108
|
+
Height: 10,
|
|
109
|
+
Length: 10,
|
|
110
|
+
Unit: 'Inch',
|
|
111
|
+
Width: 10
|
|
112
|
+
},
|
|
113
|
+
Quantity: 1,
|
|
114
|
+
Sku: 'SKU12345',
|
|
115
|
+
Weight: {
|
|
116
|
+
Unit: 'LB',
|
|
117
|
+
Value: 45
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
]
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
console.log(response.ConfirmationNumber); // 'FC59086014T860'
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### freightClub.cancelShipment(confirmationNumber, [options])
|
|
128
|
+
|
|
129
|
+
This method will cancel a shipment, provided it has not yet been picked up by a carrier.
|
|
130
|
+
|
|
131
|
+
**Example**
|
|
132
|
+
|
|
133
|
+
```javascript
|
|
134
|
+
const response = await freightClub.cancelShipment('FC59086014T860');
|
|
135
|
+
|
|
136
|
+
console.log(response.Message); // 'We have successfully processed your shipment cancellation'
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### freightClub.downloadBol(confirmationNumber, [options])
|
|
140
|
+
|
|
141
|
+
This method will download the Bill of Lading (BOL) document itself for LTL shipments based on the confirmation number generated after successful booking of an order. It resolves to a `Buffer` containing the document rather than a JSON envelope. Pass `shipmentlabelFormatType` (`Pdf` or `Zpl`) to choose the format.
|
|
142
|
+
|
|
143
|
+
**Example**
|
|
144
|
+
|
|
145
|
+
```javascript
|
|
146
|
+
const document = await freightClub.downloadBol('FC59086014T860', { shipmentlabelFormatType: 'Pdf' });
|
|
147
|
+
|
|
148
|
+
fs.writeFileSync('bol.pdf', document);
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### freightClub.exportOrders([query], [options])
|
|
152
|
+
|
|
153
|
+
This method will retrieve all the booked orders for the period you specify, up to a 30-day window. Freight Club's API documentation says an export without parameters returns the current day's orders, but the API actually requires `from` and `to` — and `to` is exclusive, so a single day is `{ from: '2022-08-14', to: '2022-08-15' }`.
|
|
154
|
+
|
|
155
|
+
**Example**
|
|
156
|
+
|
|
157
|
+
```javascript
|
|
158
|
+
const response = await freightClub.exportOrders({ from: '2022-08-14', to: '2022-08-20' });
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### freightClub.getBol(confirmationNumber, [options])
|
|
162
|
+
|
|
163
|
+
This method will return Bill of Lading (BOL) details for LTL shipments based on the confirmation number generated after successful booking of an order. Pass `contentBase64Needed: true` to also receive the document itself in the response's `ContentBase64` field.
|
|
164
|
+
|
|
165
|
+
**Example**
|
|
166
|
+
|
|
167
|
+
```javascript
|
|
168
|
+
const response = await freightClub.getBol('FC59086014T860', { contentBase64Needed: true });
|
|
169
|
+
|
|
170
|
+
console.log(response.BolURL);
|
|
171
|
+
console.log(response.TrackingNumber); // 'FCT1009624087737139200'
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### freightClub.getLabel(confirmationNumber, [options])
|
|
175
|
+
|
|
176
|
+
This method will return the shipping label based on the confirmation number generated after a successful booking.
|
|
177
|
+
|
|
178
|
+
**Example**
|
|
179
|
+
|
|
180
|
+
```javascript
|
|
181
|
+
const response = await freightClub.getLabel('FC59086014T860', { shipmentlabelFormatType: 'Zpl' });
|
|
182
|
+
|
|
183
|
+
console.log(response.LabelURL);
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### freightClub.getOrderStatus(query, [options])
|
|
187
|
+
|
|
188
|
+
This method will retrieve the current status of a specific order providing the essential details like important shipping dates and the current status. Query by `OrderID`, `OrderReferenceID`, `WayBill` or `TrackingNo`.
|
|
189
|
+
|
|
190
|
+
**Example**
|
|
191
|
+
|
|
192
|
+
```javascript
|
|
193
|
+
const response = await freightClub.getOrderStatus({ OrderID: '59086014' });
|
|
194
|
+
|
|
195
|
+
console.log(response[0].CurrentStatus); // 'Pending Pickup'
|
|
196
|
+
console.log(response[0].Dates.DeliveryEta); // '08-26-2022'
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
### freightClub.getRate(request, [options])
|
|
200
|
+
|
|
201
|
+
Use GetRate when you're only interested in a specific Service Level. This call is much quicker than the GetRates call and will provide all available rates for carriers that are open to your account for the Service Level you specified.
|
|
202
|
+
|
|
203
|
+
Pass `maxTime` (seconds, 1-40, default 40) to trade quote quantity for speed.
|
|
204
|
+
|
|
205
|
+
**Example**
|
|
206
|
+
|
|
207
|
+
```javascript
|
|
208
|
+
const response = await freightClub.getRate({
|
|
209
|
+
OrderReferenceID: 'SALEID1660782849',
|
|
210
|
+
PickupDate: '2022-08-18',
|
|
211
|
+
ServiceLevel: 'Threshold',
|
|
212
|
+
DropOffLocation: {
|
|
213
|
+
Address1: '5678 Destination Street',
|
|
214
|
+
City: 'Action',
|
|
215
|
+
Country: 'US',
|
|
216
|
+
LocationType: 'Residential',
|
|
217
|
+
ProvinceState: 'MT',
|
|
218
|
+
ZipCode: '59002'
|
|
219
|
+
},
|
|
220
|
+
PickupLocation: {
|
|
221
|
+
Address1: '1234 Source Street',
|
|
222
|
+
City: 'Seattle',
|
|
223
|
+
Country: 'US',
|
|
224
|
+
LocationType: 'Commercial',
|
|
225
|
+
ProvinceState: 'WA',
|
|
226
|
+
ZipCode: '98101'
|
|
227
|
+
},
|
|
228
|
+
TotalDeclaredValue: {
|
|
229
|
+
Unit: 'USD',
|
|
230
|
+
Value: 500
|
|
231
|
+
},
|
|
232
|
+
Accessorials: [],
|
|
233
|
+
Boxes: [
|
|
234
|
+
{
|
|
235
|
+
Category: 'CasedGoodsFurniture',
|
|
236
|
+
DeclaredValue: {
|
|
237
|
+
Unit: 'USD',
|
|
238
|
+
Value: 500
|
|
239
|
+
},
|
|
240
|
+
Description: 'Pack of 4',
|
|
241
|
+
Dimension: {
|
|
242
|
+
Height: 10,
|
|
243
|
+
Length: 10,
|
|
244
|
+
Unit: 'Inch',
|
|
245
|
+
Width: 10
|
|
246
|
+
},
|
|
247
|
+
FreightClass: '50',
|
|
248
|
+
Quantity: 1,
|
|
249
|
+
Sku: 'SKU12345',
|
|
250
|
+
Weight: {
|
|
251
|
+
Unit: 'LB',
|
|
252
|
+
Value: 45
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
]
|
|
256
|
+
}, { maxTime: 30 });
|
|
257
|
+
|
|
258
|
+
console.log(response.Quote); // the cheapest quote number
|
|
259
|
+
console.log(response.TotalNetCharge.Value); // its all-in cost
|
|
260
|
+
console.log(response.CompositeRateQuote); // every quote, including per-carrier NetCharge, ExtraServices and transit time
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### freightClub.getRates(request, [options])
|
|
264
|
+
|
|
265
|
+
This method will retrieve quotes for all Service Levels, valid for both LTL and Parcel depending on Carriers that are open to your account. The request shape matches `getRate` without the `ServiceLevel` field.
|
|
266
|
+
|
|
267
|
+
### freightClub.getShipmentTracking(query, [options])
|
|
268
|
+
|
|
269
|
+
This method will return a list of tracking information for specific shipments. Query by `trackingNo`, `wayBillNumber`, `shipmentId` or `CustomerNumber`.
|
|
270
|
+
|
|
271
|
+
**Example**
|
|
272
|
+
|
|
273
|
+
```javascript
|
|
274
|
+
const response = await freightClub.getShipmentTracking({ shipmentId: '59086014' });
|
|
275
|
+
|
|
276
|
+
console.log(response[0].TrackingCategory); // 'Pending Pickup'
|
|
277
|
+
console.log(response[0].Description); // 'WAITING FOR PICKUP'
|
|
278
|
+
```
|
package/index.js
ADDED
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
const HttpError = require('@stores.com/http-error');
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Throws an HttpError for any non-200 response and returns the parsed JSON body otherwise.
|
|
5
|
+
*
|
|
6
|
+
* @private
|
|
7
|
+
* @param {Response} res - A fetch Response.
|
|
8
|
+
* @returns {Promise.<Object>} The parsed JSON body.
|
|
9
|
+
* @throws {HttpError} If the response status is not 200.
|
|
10
|
+
*/
|
|
11
|
+
async function parseResponse(res) {
|
|
12
|
+
if (res.status !== 200) {
|
|
13
|
+
throw await HttpError.from(res);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return await res.json();
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* A client for the Freight Club API.
|
|
21
|
+
*
|
|
22
|
+
* @param {Object} args - Client options.
|
|
23
|
+
* @param {string} args.api_token - Freight Club API token, without the `Bearer ` prefix.
|
|
24
|
+
* @param {number} [args.timeout=60000] - Milliseconds to wait before aborting a request.
|
|
25
|
+
* @param {string} [args.url='https://api.freightclub.com'] - API endpoint.
|
|
26
|
+
* @see https://api.freightclub.com/ApiDoc/index
|
|
27
|
+
* @example
|
|
28
|
+
* const freightClub = new FreightClub({ api_token: 'your_api_token' });
|
|
29
|
+
*/
|
|
30
|
+
function FreightClub(args) {
|
|
31
|
+
const _options = Object.assign({
|
|
32
|
+
// Freight Club fans rate requests out to its carrier network and waits up to 40 seconds (the maxTime default) for the slowest carrier
|
|
33
|
+
timeout: 60000,
|
|
34
|
+
url: 'https://api.freightclub.com'
|
|
35
|
+
}, args);
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Supplying the quote number returned by GetRate and GetRates, this method books a shipment at that specific quoted rate with the chosen carrier.
|
|
39
|
+
*
|
|
40
|
+
* @param {Object} request - A BookShipment request. Carriers require a contact Email at booking (Error Code 13010), even though Freight Club's API documentation marks it optional.
|
|
41
|
+
* @param {Object} [options] - Per-call options.
|
|
42
|
+
* @param {number} [options.timeout] - Milliseconds to wait before aborting the request, overriding the constructor value.
|
|
43
|
+
* @returns {Promise.<Object>} The booking confirmation, including ConfirmationNumber and ShipmentNumber.
|
|
44
|
+
* @throws {HttpError} If the response status is not 200.
|
|
45
|
+
* @see https://api.freightclub.com/ApiDoc/index
|
|
46
|
+
* @example
|
|
47
|
+
* const booking = await freightClub.bookShipment(request, { timeout: 180000 });
|
|
48
|
+
*/
|
|
49
|
+
this.bookShipment = async function(request, options = {}) {
|
|
50
|
+
const res = await fetch(`${_options.url}/Book/BookShipment`, {
|
|
51
|
+
body: JSON.stringify(request),
|
|
52
|
+
headers: {
|
|
53
|
+
'Authorization': `Bearer ${_options.api_token}`,
|
|
54
|
+
'Content-Type': 'application/json'
|
|
55
|
+
},
|
|
56
|
+
method: 'POST',
|
|
57
|
+
signal: AbortSignal.timeout(options.timeout || _options.timeout)
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
return await parseResponse(res);
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* This method will cancel a shipment, provided it has not yet been picked up by a carrier.
|
|
65
|
+
*
|
|
66
|
+
* @param {string} confirmationNumber - The confirmation number supplied from a successful booking.
|
|
67
|
+
* @param {Object} [options] - Per-call options.
|
|
68
|
+
* @param {number} [options.timeout] - Milliseconds to wait before aborting the request, overriding the constructor value.
|
|
69
|
+
* @returns {Promise.<Object>} The cancellation result.
|
|
70
|
+
* @throws {HttpError} If the response status is not 200.
|
|
71
|
+
* @example
|
|
72
|
+
* const cancellation = await freightClub.cancelShipment('FC59086014T860');
|
|
73
|
+
*/
|
|
74
|
+
this.cancelShipment = async function(confirmationNumber, options = {}) {
|
|
75
|
+
const res = await fetch(`${_options.url}/Cancel/CancelShipment/${encodeURIComponent(confirmationNumber)}`, {
|
|
76
|
+
headers: {
|
|
77
|
+
'Authorization': `Bearer ${_options.api_token}`
|
|
78
|
+
},
|
|
79
|
+
signal: AbortSignal.timeout(options.timeout || _options.timeout)
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
return await parseResponse(res);
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* This method will download the Bill of Lading (BOL) document itself for LTL shipments based on the confirmation number generated after successful booking of an order.
|
|
87
|
+
*
|
|
88
|
+
* @param {string} confirmationNumber - The confirmation number supplied from a successful booking.
|
|
89
|
+
* @param {Object} [options] - Per-call options.
|
|
90
|
+
* @param {string} [options.shipmentlabelFormatType] - The file format to receive: Pdf or Zpl.
|
|
91
|
+
* @param {number} [options.timeout] - Milliseconds to wait before aborting the request, overriding the constructor value.
|
|
92
|
+
* @returns {Promise.<Buffer>} The Bill of Lading document itself.
|
|
93
|
+
* @throws {HttpError} If the response status is not 200.
|
|
94
|
+
* @example
|
|
95
|
+
* const bolDocument = await freightClub.downloadBol('FC59086014T860', { shipmentlabelFormatType: 'Pdf' });
|
|
96
|
+
*/
|
|
97
|
+
this.downloadBol = async function(confirmationNumber, options = {}) {
|
|
98
|
+
let url = `${_options.url}/Bol/DownloadBol/${encodeURIComponent(confirmationNumber)}`;
|
|
99
|
+
|
|
100
|
+
if (options.shipmentlabelFormatType) {
|
|
101
|
+
url += `?shipmentlabelFormatType=${options.shipmentlabelFormatType}`;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const res = await fetch(url, {
|
|
105
|
+
headers: {
|
|
106
|
+
'Authorization': `Bearer ${_options.api_token}`
|
|
107
|
+
},
|
|
108
|
+
signal: AbortSignal.timeout(options.timeout || _options.timeout)
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
if (res.status !== 200) {
|
|
112
|
+
throw await HttpError.from(res);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// DownloadBol streams the document itself rather than a JSON envelope
|
|
116
|
+
return Buffer.from(await res.arrayBuffer());
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* This method will retrieve all the booked orders for the period you specify, up to a 30-day window. Freight Club's API documentation says the parameters are optional, but the API requires both.
|
|
121
|
+
*
|
|
122
|
+
* @param {Object} query - Export parameters.
|
|
123
|
+
* @param {string} query.from - The starting date from which orders were placed (YYYY-MM-DD).
|
|
124
|
+
* @param {string} query.to - The last date that orders were placed (YYYY-MM-DD), EXCLUSIVE: a single day is from=2022-08-14, to=2022-08-15.
|
|
125
|
+
* @param {Object} [options] - Per-call options.
|
|
126
|
+
* @param {number} [options.timeout] - Milliseconds to wait before aborting the request, overriding the constructor value.
|
|
127
|
+
* @returns {Promise.<Array.<Object>>} The booked orders for the period.
|
|
128
|
+
* @throws {HttpError} If the response status is not 200.
|
|
129
|
+
* @example
|
|
130
|
+
* const orders = await freightClub.exportOrders({ from: '2022-08-14', to: '2022-08-20' });
|
|
131
|
+
*/
|
|
132
|
+
this.exportOrders = async function(query, options = {}) {
|
|
133
|
+
let url = `${_options.url}/api/orders/export`;
|
|
134
|
+
const queryString = new URLSearchParams(query).toString();
|
|
135
|
+
|
|
136
|
+
if (queryString) {
|
|
137
|
+
url += `?${queryString}`;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const res = await fetch(url, {
|
|
141
|
+
headers: {
|
|
142
|
+
'Authorization': `Bearer ${_options.api_token}`
|
|
143
|
+
},
|
|
144
|
+
signal: AbortSignal.timeout(options.timeout || _options.timeout)
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
return await parseResponse(res);
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* This method will return Bill of Lading (BOL) details for LTL shipments based on the confirmation number generated after successful booking of an order.
|
|
152
|
+
*
|
|
153
|
+
* @param {string} confirmationNumber - The confirmation number supplied from a successful booking.
|
|
154
|
+
* @param {Object} [options] - Per-call options.
|
|
155
|
+
* @param {boolean} [options.contentBase64Needed] - Also return the document itself, Base64-encoded in the response's ContentBase64 field.
|
|
156
|
+
* @param {number} [options.timeout] - Milliseconds to wait before aborting the request, overriding the constructor value.
|
|
157
|
+
* @returns {Promise.<Object>} Bill of Lading details, including TrackingNumber, CarrierWayBill and BolURL.
|
|
158
|
+
* @throws {HttpError} If the response status is not 200.
|
|
159
|
+
* @example
|
|
160
|
+
* const bol = await freightClub.getBol('FC59086014T860', { contentBase64Needed: true });
|
|
161
|
+
*/
|
|
162
|
+
this.getBol = async function(confirmationNumber, options = {}) {
|
|
163
|
+
const query = new URLSearchParams();
|
|
164
|
+
|
|
165
|
+
if (options.contentBase64Needed !== undefined) {
|
|
166
|
+
query.set('contentBase64Needed', options.contentBase64Needed);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
let url = `${_options.url}/Bol/GetBol/${encodeURIComponent(confirmationNumber)}`;
|
|
170
|
+
const queryString = query.toString();
|
|
171
|
+
|
|
172
|
+
if (queryString) {
|
|
173
|
+
url += `?${queryString}`;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
const res = await fetch(url, {
|
|
177
|
+
headers: {
|
|
178
|
+
'Authorization': `Bearer ${_options.api_token}`
|
|
179
|
+
},
|
|
180
|
+
signal: AbortSignal.timeout(options.timeout || _options.timeout)
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
return await parseResponse(res);
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* This method will return the shipping label based on the confirmation number generated after a successful booking.
|
|
188
|
+
*
|
|
189
|
+
* @param {string} confirmationNumber - The confirmation number supplied from a successful booking.
|
|
190
|
+
* @param {Object} [options] - Per-call options.
|
|
191
|
+
* @param {boolean} [options.contentBase64Needed] - Also return the label itself, Base64-encoded in the response's ContentBase64 field.
|
|
192
|
+
* @param {string} [options.shipmentlabelFormatType] - The file format to receive: Pdf or Zpl.
|
|
193
|
+
* @param {number} [options.timeout] - Milliseconds to wait before aborting the request, overriding the constructor value.
|
|
194
|
+
* @returns {Promise.<Object>} Label details, including LabelURL.
|
|
195
|
+
* @throws {HttpError} If the response status is not 200.
|
|
196
|
+
* @example
|
|
197
|
+
* const label = await freightClub.getLabel('FC59086014T860', { shipmentlabelFormatType: 'Zpl' });
|
|
198
|
+
*/
|
|
199
|
+
this.getLabel = async function(confirmationNumber, options = {}) {
|
|
200
|
+
const query = new URLSearchParams();
|
|
201
|
+
|
|
202
|
+
if (options.contentBase64Needed !== undefined) {
|
|
203
|
+
query.set('contentBase64Needed', options.contentBase64Needed);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
if (options.shipmentlabelFormatType) {
|
|
207
|
+
query.set('shipmentlabelFormatType', options.shipmentlabelFormatType);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
let url = `${_options.url}/Label/GetLabel/${encodeURIComponent(confirmationNumber)}`;
|
|
211
|
+
const queryString = query.toString();
|
|
212
|
+
|
|
213
|
+
if (queryString) {
|
|
214
|
+
url += `?${queryString}`;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
const res = await fetch(url, {
|
|
218
|
+
headers: {
|
|
219
|
+
'Authorization': `Bearer ${_options.api_token}`
|
|
220
|
+
},
|
|
221
|
+
signal: AbortSignal.timeout(options.timeout || _options.timeout)
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
return await parseResponse(res);
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* This method will retrieve the current status of a specific order providing the essential details like important shipping dates and the current status.
|
|
229
|
+
*
|
|
230
|
+
* @param {Object} query - Order status parameters; supply one of them.
|
|
231
|
+
* @param {string} [query.OrderID] - The Freight Club OrderID linked to the shipment.
|
|
232
|
+
* @param {string} [query.OrderReferenceID] - The order reference assigned to the shipment, URL encoded to account for spaces.
|
|
233
|
+
* @param {string} [query.TrackingNo] - The tracking number assigned to the shipment.
|
|
234
|
+
* @param {string} [query.WayBill] - The carrier's waybill value assigned to the shipment.
|
|
235
|
+
* @param {Object} [options] - Per-call options.
|
|
236
|
+
* @param {number} [options.timeout] - Milliseconds to wait before aborting the request, overriding the constructor value.
|
|
237
|
+
* @returns {Promise.<Array.<Object>>} The matching orders' statuses, including CurrentStatus, ConfirmationNumber and Dates.
|
|
238
|
+
* @throws {HttpError} If the response status is not 200.
|
|
239
|
+
* @example
|
|
240
|
+
* const statuses = await freightClub.getOrderStatus({ OrderID: '59086014' });
|
|
241
|
+
*/
|
|
242
|
+
this.getOrderStatus = async function(query, options = {}) {
|
|
243
|
+
const res = await fetch(`${_options.url}/api/orders/orderstatus?${new URLSearchParams(query)}`, {
|
|
244
|
+
headers: {
|
|
245
|
+
'Authorization': `Bearer ${_options.api_token}`
|
|
246
|
+
},
|
|
247
|
+
signal: AbortSignal.timeout(options.timeout || _options.timeout)
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
return await parseResponse(res);
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Use GetRate when you're only interested in a specific Service Level. This call is much quicker than the GetRates call and will provide all available rates for carriers that are open to your account for the Service Level you specified.
|
|
255
|
+
*
|
|
256
|
+
* @param {Object} request - A GetRate request. A ServiceLevel is required (Error Code 9036).
|
|
257
|
+
* @param {Object} [options] - Per-call options.
|
|
258
|
+
* @param {number} [options.maxTime] - Seconds to wait for the carrier network to return quotes, 1 to 40 (default 40); Freight Club recommends 10 or greater.
|
|
259
|
+
* @param {number} [options.timeout] - Milliseconds to wait before aborting the request, overriding the constructor value.
|
|
260
|
+
* @returns {Promise.<Object>} The quotes, with the cheapest quote number in Quote and its cost in TotalNetCharge.
|
|
261
|
+
* @throws {HttpError} If the response status is not 200.
|
|
262
|
+
* @see https://api.freightclub.com/ApiDoc/index
|
|
263
|
+
* @example
|
|
264
|
+
* const rate = await freightClub.getRate(request, { maxTime: 30 });
|
|
265
|
+
*/
|
|
266
|
+
this.getRate = async function(request, options = {}) {
|
|
267
|
+
let url = `${_options.url}/Rate/GetRate`;
|
|
268
|
+
|
|
269
|
+
if (options.maxTime) {
|
|
270
|
+
url += `?maxTime=${options.maxTime}`;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
const res = await fetch(url, {
|
|
274
|
+
body: JSON.stringify(request),
|
|
275
|
+
headers: {
|
|
276
|
+
'Authorization': `Bearer ${_options.api_token}`,
|
|
277
|
+
'Content-Type': 'application/json'
|
|
278
|
+
},
|
|
279
|
+
method: 'POST',
|
|
280
|
+
signal: AbortSignal.timeout(options.timeout || _options.timeout)
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
return await parseResponse(res);
|
|
284
|
+
};
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* This method will retrieve quotes for all Service Levels, valid for both LTL and Parcel depending on Carriers that are open to your account.
|
|
288
|
+
*
|
|
289
|
+
* @param {Object} request - A GetRates request. Despite rating all Service Levels, a ServiceLevel is still required (Error Code 9036).
|
|
290
|
+
* @param {Object} [options] - Per-call options.
|
|
291
|
+
* @param {number} [options.maxTime] - Seconds to wait for the carrier network to return quotes, 1 to 40 (default 40); Freight Club recommends 10 or greater.
|
|
292
|
+
* @param {number} [options.timeout] - Milliseconds to wait before aborting the request, overriding the constructor value.
|
|
293
|
+
* @returns {Promise.<Object>} The quotes, with the cheapest quote number in Quote and its cost in TotalNetCharge.
|
|
294
|
+
* @throws {HttpError} If the response status is not 200.
|
|
295
|
+
* @see https://api.freightclub.com/ApiDoc/index
|
|
296
|
+
* @example
|
|
297
|
+
* const rates = await freightClub.getRates(request, { maxTime: 30 });
|
|
298
|
+
*/
|
|
299
|
+
this.getRates = async function(request, options = {}) {
|
|
300
|
+
let url = `${_options.url}/Rate/GetRates`;
|
|
301
|
+
|
|
302
|
+
if (options.maxTime) {
|
|
303
|
+
url += `?maxTime=${options.maxTime}`;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
const res = await fetch(url, {
|
|
307
|
+
body: JSON.stringify(request),
|
|
308
|
+
headers: {
|
|
309
|
+
'Authorization': `Bearer ${_options.api_token}`,
|
|
310
|
+
'Content-Type': 'application/json'
|
|
311
|
+
},
|
|
312
|
+
method: 'POST',
|
|
313
|
+
signal: AbortSignal.timeout(options.timeout || _options.timeout)
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
return await parseResponse(res);
|
|
317
|
+
};
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* This method will return a list of tracking information for specific shipments.
|
|
321
|
+
*
|
|
322
|
+
* @param {Object} query - Tracking parameters; supply one of them.
|
|
323
|
+
* @param {string} [query.CustomerNumber] - Your own internal reference number, URL encoded to account for spaces.
|
|
324
|
+
* @param {string} [query.shipmentId] - Internal Freight Club order number (OrderId).
|
|
325
|
+
* @param {string} [query.trackingNo] - Freight Club tracking number.
|
|
326
|
+
* @param {string} [query.wayBillNumber] - Waybill number which Freight Club uses to register the shipment.
|
|
327
|
+
* @param {Object} [options] - Per-call options.
|
|
328
|
+
* @param {number} [options.timeout] - Milliseconds to wait before aborting the request, overriding the constructor value.
|
|
329
|
+
* @returns {Promise.<Array.<Object>>} The shipment's tracking events.
|
|
330
|
+
* @throws {HttpError} If the response status is not 200.
|
|
331
|
+
* @example
|
|
332
|
+
* const tracking = await freightClub.getShipmentTracking({ shipmentId: '59086014' });
|
|
333
|
+
*/
|
|
334
|
+
this.getShipmentTracking = async function(query, options = {}) {
|
|
335
|
+
const res = await fetch(`${_options.url}/api/tracking/ShipmentTracking?${new URLSearchParams(query)}`, {
|
|
336
|
+
headers: {
|
|
337
|
+
'Authorization': `Bearer ${_options.api_token}`
|
|
338
|
+
},
|
|
339
|
+
signal: AbortSignal.timeout(options.timeout || _options.timeout)
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
return await parseResponse(res);
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
module.exports = FreightClub;
|
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"dependencies": {
|
|
3
|
+
"@stores.com/http-error": "~1.2.0"
|
|
4
|
+
},
|
|
5
|
+
"description": "The Freight Club API is an interface that allows you to set up an integrated experience between your daily operations and our application. APIs give you the ability to manage all your Parcel or LTL shipments with capabilities that include rating shipments, creating Bills of Lading or parcel labels, booking shipments with carriers and getting tracking information from those bookings.",
|
|
6
|
+
"devDependencies": {
|
|
7
|
+
"@eslint/js": "*",
|
|
8
|
+
"globals": "*"
|
|
9
|
+
},
|
|
10
|
+
"engines": {
|
|
11
|
+
"node": ">=18"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"freight",
|
|
15
|
+
"freight club",
|
|
16
|
+
"logistics",
|
|
17
|
+
"ltl",
|
|
18
|
+
"shipping",
|
|
19
|
+
"tracking"
|
|
20
|
+
],
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"name": "freight-club",
|
|
23
|
+
"publishConfig": {
|
|
24
|
+
"access": "public"
|
|
25
|
+
},
|
|
26
|
+
"repository": {
|
|
27
|
+
"type": "git",
|
|
28
|
+
"url": "git+https://github.com/stores-com/freight-club.git"
|
|
29
|
+
},
|
|
30
|
+
"scripts": {
|
|
31
|
+
"coveralls": "node --test --test-force-exit --experimental-test-coverage --test-reporter=spec --test-reporter-destination=stdout --test-reporter=lcov --test-reporter-destination=lcov.info test && coveralls < lcov.info",
|
|
32
|
+
"test": "node --test --test-force-exit test",
|
|
33
|
+
"test:only": "node --test --test-force-exit --test-only test"
|
|
34
|
+
},
|
|
35
|
+
"version": "0.0.1"
|
|
36
|
+
}
|