Added
Batch quotes: price up to 1,000 shipments at once
October 12th, 2026
You can now send a list of shipments to the Shipper API and get a quote for each. A batch is accepted at once and priced in the background. Read it until it is done, then book any quoted item with its quote ID, exactly as you would a single quote.
How it works
- Create the batch.
POST /v1/shipper/quotes/batchwith 1 to 1,000 items. Each item is a regular quote request, the same shape you send toPOST /v1/shipper/quote. The response is201 Createdwith the batch in statusPRICING, aLocationheader pointing at the batch, and aRetry-Afterheader saying how long to wait before reading it. - Read the batch.
GET /v1/shipper/quotes/batch/{batchId}returns the same body as the create call, brought up to date. Results are in the order you sent the items, so match them by position. Keep reading untilstatusisCOMPLETEDorFAILED; while it isPRICING,Retry-Aftertells you when to come back. - Act on each item. Every item ends in one of three states:
QUOTED:quotecarries the fields a single quote request answers with, including theidyou book with and when the price expires.NOT_QUOTED:problemsays why, in the shape a single quote request would have used. A400withviolationsmeans the item was malformed; a422with areasoncode means we cannot serve that lane or load as asked.UNDER_REVIEW: no automatic price can be trusted for this item, so a person decides.problem.reasonisunder_review. The item later becomesQUOTEDorNOT_QUOTED; read the batch again, or look it up by itscustomerReference.
While pricing, items show PENDING. Once a batch is COMPLETED, items change in one direction only, from UNDER_REVIEW to QUOTED or NOT_QUOTED; nothing else on the batch moves.
A refused or malformed item never fails the batch. The whole call is refused only when the envelope cannot be taken: no items, more than 1,000, or an empty item.
Example
POST /v1/shipper/quotes/batch
Idempotency-Key: plan-2026-10-14
Content-Type: application/json
{
"customerReference": "plan-2026-10-14",
"items": [
{
"customerReference": "PO-48213",
"pickupAddress": { "zipCode": "91730" },
"deliveryAddress": { "zipCode": "95206" },
"orderComponents": [ { "palletCount": 6, "poundsWeight": 1200 } ],
"requiredPickupDate": "2026-10-14T08:00:00-07:00"
},
{
"pickupAddress": { "zipCode": "91730" },
"deliveryAddress": { "zipCode": "97201" },
"orderComponents": [ { "palletCount": 2, "poundsWeight": 900 } ]
}
]
}HTTP/1.1 201 Created
Location: /v1/shipper/quotes/batch/QB-8F3K29XA
Retry-After: 5
{
"id": "QB-8F3K29XA",
"status": "PRICING",
"customerReference": "plan-2026-10-14",
"createdAt": "2026-10-12T13:05:00Z",
"counts": { "items": 2, "quoted": 0, "notQuoted": 0, "underReview": 0, "pending": 2 },
"items": [
{ "customerReference": "PO-48213", "status": "PENDING" },
{ "status": "PENDING" }
]
}A few seconds later:
GET /v1/shipper/quotes/batch/QB-8F3K29XA
{
"id": "QB-8F3K29XA",
"status": "COMPLETED",
"customerReference": "plan-2026-10-14",
"createdAt": "2026-10-12T13:05:00Z",
"completedAt": "2026-10-12T13:05:09Z",
"counts": { "items": 2, "quoted": 1, "notQuoted": 1, "underReview": 0, "pending": 0 },
"items": [
{
"customerReference": "PO-48213",
"status": "QUOTED",
"quote": {
"id": "68e9c2f1a4b7d3e2f0c91a77",
"quotedPriceInCents": 123400,
"quoteExpirationTime": "2026-10-14T13:05:09Z",
"transitDays": 2,
"estimatedDeliveryDate": "2026-10-16T13:05:09Z"
}
},
{
"status": "NOT_QUOTED",
"problem": {
"title": "Unprocessable Entity",
"status": 422,
"detail": "We can't cover this lane right now",
"reason": "no_coverage"
}
}
]
}References
- The batch's
customerReferenceis yours for the whole set, such as a plan or file name. It is stored on the batch only. - An item's
customerReference(up to 64 characters) is stored on its quote, so a later shipment can name it andGET /v1/shipper/quotes/by-referencecan find it. An item without one is matched by position only; no reference is invented for it. - An item whose reference is longer than 64 characters is
NOT_QUOTEDwith a400; the rest of the batch prices as usual.
Idempotency, limits and failure
Idempotency-Keyworks as it does on shipment creation: retrying the same request with the same key within 24 hours returns the original response; reusing the key with a different body returns409with reasonidempotency_key_conflict.- Without a key, sending the same items for your account within 24 hours returns the batch that already ran, however far it has got. Quotes stay valid for two days, so a replay never returns an expired price.
- One batch at a time per account. A different batch sent while one is still
PRICINGis refused with409and reasonbatch_in_progress; the running batch's ID is indetail. - Up to 1,000 items per batch. Results come back in the order you sent them.
FAILEDmeans the run could not finish. A batch that stops making progress is markedFAILEDafter about 15 minutes, and its items may be submitted again at once; the same items are then priced afresh rather than answered with the failed batch.
Also in this release
customerReferenceon single quote requests.POST /v1/shipper/quotenow accepts your own reference for the load, up to 64 characters. It is stored on the quote, so a later shipment can name it andGET /v1/shipper/quotes/by-referencecan find it.- Quote lookups are scoped to your account.
GET /v1/shipper/quote/{quoteId}answers404for a quote that does not belong to your company. - Pickup dates.
requiredPickupDateis read as a day in the pickup location's time zone. Send it with that zone's offset, for example2026-10-14T08:00:00-07:00, so the day is unambiguous.
The OpenAPI specification is version 1.3.0. SDK support for batches follows in the next SDK release.