Dispatch
Dispatch books freight with a carrier. If you already have a rate, the whole request is one field. Shipwell tenders the shipment, requests the eBOL and PRO number where the carrier issues them, and reports the carrier's answer on one job you poll.
How it works
-
Create a dispatch job
with
POST /dispatching/jobs. The response is immediate: a job inPROCESSINGwith aresource_id. - Shipwell tenders the carrier , and requests the eBOL and PRO number as part of the same booking. See eBOL & PRO Numbers .
-
Poll the job
with
GET /dispatching/jobs/{dispatch_job_id}untilis_terminalistrue. -
Keep the
resource_id. Tracking, documents and cancellation are all addressed by it.
A job always finishes. A dispatch the carrier never confirms is marked EXPIRED, so is_terminal arrives either way.
Endpoints
| Endpoint | What it does |
|---|---|
POST /dispatching/jobs |
Book freight. Returns 201 with the job in PROCESSING. |
GET /dispatching/jobs/{dispatch_job_id} |
Read the job and the carrier's answer. |
POST /dispatching/jobs/{resource_id}/cancel |
Cancel a booking, by its resource_id. |
Book from a rate
This is the usual path. Everything about the shipment comes from the rate, including the stop contacts you sent when rating. If your rating request had a pickup contact with company_name, first_name and phone and a delivery contact with company_name and phone, as the Rating example does, the body is just the rate_id:
Example request
curl --request POST 'https://sandbox-api.shipwell.com/dispatching/jobs' \
--header 'Authorization: Token <user-token>' \
--header 'Content-Type: application/json' \
--header 'Idempotency-Key: 9b4f02d8-po-4417-booking' \
--data-raw '{
"rate_id": "01HZKD9M4TQ4Z8XW0NKZ6RYX4J"
}'If a rating stop had no contact, or one missing those fields, add the contact for that stop. The carrier needs someone to call for the pickup, and the bill of lading names the consignee:
Example request, adding contacts
curl --request POST 'https://sandbox-api.shipwell.com/dispatching/jobs' \
--header 'Authorization: Token <user-token>' \
--header 'Content-Type: application/json' \
--header 'Idempotency-Key: 9b4f02d8-po-4417-booking' \
--data-raw '{
"rate_id": "01HZKD9M4TQ4Z8XW0NKZ6RYX4J",
"origin_contact": {"company_name": "Acme", "first_name": "Dock", "last_name": "Team", "email": "dock@acme.com", "phone": "+15125551234"},
"destination_contact": {"company_name": "Beta Receiving", "first_name": "Receiving", "last_name": "Desk", "email": "rec@beta.com", "phone": "+17135554500"}
}'| Field | Required |
|---|---|
rate_id |
Yes. The id of an LTL or VLTL rate that has charges. An FTL rate is booked by tendering in the Shipwell app, and sending one here returns 400 unsupported_transportation_mode. See Booking an FTL rate. |
origin_contact (company_name, first_name, phone) |
Only if the rating pickup stop had no contact with all three. The carrier rejects a pickup with nobody to call. |
destination_contact (company_name, phone) |
Only if the rating delivery stop had no contact with both. Without it the request is rejected with 400 missing_delivery_contact. |
origin_planned_window / destination_planned_window |
No. Only if the date moved since you rated. |
references / notes_for_carrier |
No. |
Book without a rate
If you have a negotiated arrangement and no rate to book against, state the shipment in full and name the carrier account. Only an account with COLLECT billing terms can book this way. Sending rate_id together with any of these fields is rejected, because the two shapes can't be mixed.
Example request
curl --request POST 'https://sandbox-api.shipwell.com/dispatching/jobs' \
--header 'Authorization: Token <user-token>' \
--header 'Content-Type: application/json' \
--header 'Idempotency-Key: 2e7d6c11-abf-booking' \
--data-raw '{
"account_id": "01KBZ91QKW3D9VDP5PVY4HWQ1G",
"provider_code": "ABF",
"mode": "LTL",
"stops": [
{
"sequence_number": 1,
"location": {"line_1": "Cincinnati Museum Ctr", "locality": "Cincinnati", "region": "OH", "postal_code": "45203", "country": "US"},
"contact": {"company_name": "Acme", "first_name": "Dock", "last_name": "Team", "phone": "+16124323789"},
"requested_window": {"earliest": "2026-12-01T14:00:00Z", "latest": "2026-12-01T22:00:00Z"}
},
{
"sequence_number": 2,
"location": {"line_1": "4340 Directors Row", "locality": "Houston", "region": "TX", "postal_code": "77092", "country": "US"},
"contact": {"company_name": "Beta", "first_name": "Receiving", "last_name": "Desk", "phone": "+17136864500"}
}
],
"handling_units": [
{
"quantity": 1,
"freight_class": "70",
"weight": {"value": 500, "unit": "LB", "qualifier": "PER_ITEM"},
"dimensions": {"measurement_type": "DIMENSIONS", "unit": "IN", "length": {"value": 48, "unit": "IN"}, "width": {"value": 40, "unit": "IN"}, "height": {"value": 50, "unit": "IN"}}
}
]
}'| Field | Required |
|---|---|
account_id, provider_code, mode |
Yes |
stops (2 or more) |
Yes |
requested_window on the pickup stop (earliest, latest) |
Yes |
contact.company_name, first_name and phone on the pickup stop |
Yes |
contact.company_name and phone on the delivery stop |
Yes |
handling_units (1 or more) |
Yes |
equipment, accessorials, service_code, carrier_rate_id, gross_weight, total_declared_value, customer_reference_number |
No |
LTL and VLTL are the modes you can book through the API today.
Read the carrier's answer
Example response (200)
{
"data": {
"id": "01KBZC9J8Q0000000000000000",
"resource_type": "dispatch_job",
"self_link": "https://sandbox-api.shipwell.com/dispatching/jobs/01KBZC9J8Q0000000000000000",
"status": "COMPLETED",
"is_terminal": true,
"created_at": "2026-08-19T15:30:32.591Z",
"resource_id": "9f2c1b84-6d3a-4c17-9b0e-2f5a7c48d31e",
"provider_code": "ABF",
"carrier_name": "ABF Freight",
"capacity_provider": {"account_id": "01KBZ91QKW3D9VDP5PVY4HWQ1G", "account_name": "ABF - Main"},
"references": [
{"qualifier": "BOL_NUMBER", "value": "BOL-77120"},
{"qualifier": "PICKUP_NUMBER", "value": "PU-448201"},
{"qualifier": "PRO_NUMBER", "value": "123456789"}
],
"errors": []
}
}| Status | What it means | What to do |
|---|---|---|
PROCESSING |
The carrier hasn't answered yet. | Keep polling. |
COMPLETED |
The carrier confirmed the booking. Its pickup number is in references, and so is its PRO number when the carrier issued one. |
Check references for PRO_NUMBER (see eBOL & PRO Numbers), then start tracking. |
ERRORED |
The carrier refused the booking. Its reason is in errors. |
Fix the request, or book another rate. |
EXPIRED |
The carrier never answered. | The tender may still have reached the carrier, so confirm with it before booking the same freight again. |
CANCELLED |
The booking was cancelled with the carrier. | |
CANCELLED_INTERNALLY |
Shipwell released the booking, but this carrier can't cancel through Shipwell. | Cancel the freight with the carrier directly. |
Note
Send an Idempotency-Key on every booking. Without one, a retried request books again and the carrier gets a second pickup. With one, a retry with the same key and body returns the original dispatch.
Cancel a booking
Cancel with POST /dispatching/jobs/{resource_id}/cancel. The path takes the resource_id from the booking, not the dispatch job id.
The answer is always 200, because whether a carrier can cancel is a fact about the carrier, not an HTTP error:
Example response (200)
{
"data": {
"resource_id": "9f2c1b84-6d3a-4c17-9b0e-2f5a7c48d31e",
"carrier_cancellation_requested": false,
"requires_manual_carrier_cancellation": true,
"reason": "This carrier does not support dispatch cancellation through Shipwell. You must cancel the load directly with the carrier."
}
}-
carrier_cancellation_requested: true: Shipwell asked the carrier to cancel. Poll the dispatch job for the final status. -
requires_manual_carrier_cancellation: true: this carrier can't cancel through Shipwell. The booking is released on Shipwell's side, andreasontells you to cancel with the carrier directly.
Which carriers support cancellation is shown in Supported Carriers.
API reference
Dispatching API reference: every field, with request and response examples and code samples.
Next steps
Once the dispatch is COMPLETED, track the freight and pull its documents, both by the resource_id.