ShipBob Logistics API

View as Markdown

This API lets you create shipping labels and sync tracking numbers for orders processed through ShipBob’s logistics system. It’s straightforward to integrate and works in both sandbox and production environments.

Create an Account

To get started, you’ll need a ShipBob account. Sign up here. After signing up, reach out to your ShipBob representative and they’ll guide you through the process and provide the necessary credentials.

Base URLs

Base URL
https://logisticslabelprintingapi.shipbob.com

Authentication

Authentication depends on the API you’re calling:

For https://logisticslabelprintingapi-stage.shipbob.dev/ or https://logisticslabelprintingapi.shipbob.com/:

Every endpoint accepts either of the following. Pick one — you do not need both.

Option 1 — Token (SBL_authToken or PAT)

Use an SBL_authToken provided by your ShipBob rep, or a Personal Access Token (PAT) generated in the ShipBob dashboard under Integrations > API Tokens > Generate new token.

Authorization: <SBL_authToken>

The Bearer prefix is optional for this API — both of the following are accepted:

Authorization: <Personal_Access_Token>
Authorization: Bearer <Personal_Access_Token>

Option 2 — OAuth 2.0 (Authorization Code with PKCE)

Recommended for multi-user applications. Register an OAuth app in the ShipBob dashboard under Integrations > OAuth Apps > Create App, run the authorization code flow with PKCE, then send the returned access token as a Bearer token:

Authorization: Bearer <OAuth_Access_Token>
SettingValue
Grant typeAuthorization Code (With PKCE)
Authorization URLhttps://auth.shipbob.com/connect/authorize
Access token URLhttps://auth.shipbob.com/connect/token
Code challenge methodS256 (SHA-256)
Scopeorders_write (add offline_access for a refresh token)
Client authenticationSend client credentials as a Basic Auth header

On sandbox, replace auth.shipbob.com with authstage.shipbob.com.

The same settings in Postman’s Authorization tab:

Postman OAuth 2.0 token configuration for ShipBob Logistics

The token exchange call carries the PKCE verifier:

grant_type=authorization_code
code=<authorization-code>
redirect_uri=<your-registered-callback-url>
client_id=<your-client-id>
client_secret=<your-client-secret>
code_verifier=<pkce-code-verifier>

Access tokens expire after 1 hour. For the full step-by-step flow, including how to generate the code_verifier and code_challenge, see Authentication.

For https://sandbox-api.shipbob.com/ or https://api.shipbob.com/:

Use a Personal Access Token (PAT), which you can generate in the ShipBob dashboard by going to Integrations > API Tokens > Generate new token.

Authorization: Bearer <Personal_Access_Token>

Create an Order and Purchase a Label

POST /api/v1/CreateOrderAndPurchaseLabel

Creates a packed order and purchases its final-mile carrier label in a single synchronous call, returning the carrier, tracking number, and a URL to the label.

If an order with the same reference_id already exists but has no final-mile label yet, the existing order is reused and only the label is purchased. If it already has a label, the call returns 409 — retrieve the existing label instead.

Headers

HeaderValueRequired?Description
Authorization<SBL_authToken> / Bearer <PAT> / Bearer <OAuth_Access_Token>YesAny of the methods in Authentication
Content-Typeapplication/jsonYesAccepted content type

This endpoint does not use the Label-Type header. Request the label format with the order.label_file_format field in the body instead.

Request Body

POST /api/v1/CreateOrderAndPurchaseLabel
{
"order": {
"shipping_method": "Standard",
"recipient": {
"name": "Test Test",
"email": "johndoe@shipbob.com",
"phone_number": "444-333-2222",
"address": {
"address1": "223 E 5th St",
"address2": null,
"company_name": null,
"city": "Greenville",
"state": "NC",
"country": "US",
"zip_code": "27957"
}
},
"location_id": 33,
"reference_id": "101",
"measurements": {
"total_weight_oz": 4,
"length_in": 2,
"width_in": 4,
"depth_in": 6
},
"products": [
{ "name": "Light Roast Coffee", "sku": "LIGHT-ROAST", "quantity": 1 }
],
"label_file_format": "PNG", // optional
"requires_signature": true // optional
},
"meta": {
"order_number": "101",
"order_id": "101",
"customer_name": "ABC Merch"
}
}

Key Fields

FieldTypeRequiredDescription
order.shipping_methodstringYesShipping option (e.g., "Standard")
order.recipientobjectYesRecipient details. name and address are required; email and phone_number are optional
order.location_idintegerYesShipBob location ID. Sandbox: use 33 or 19. Production: contact your ShipBob rep for your location ID.
order.reference_idstringYesUnique order identifier
order.measurementsobjectYesRequired for this endpoint. All four values (total_weight_oz, length_in, width_in, depth_in) must be positive whole numbers
order.productsobject[]YesRequired for this endpoint. At least one product, each with name, sku, and quantity
order.label_file_formatstringNoPNG or ZPL. Defaults to PNG.
order.requires_signaturebooleanNoDefaults to false
meta.order_numberstring | numberYesYour order number
meta.order_idstring | numberYesYour order ID
meta.customer_namestringYesYour customer’s name

Unlike POST /api/order:createLabel, measurements and products are mandatory here, and every measurement must be a positive whole number. Unrecognized fields are ignored.

Response

On success (HTTP 200):

{
"interim_order_id": "67c8a7f30c3c1d16d05179db",
"reference_id": "101",
"shipment_id": 100000001,
"final_mile_label": {
"carrier": "OnTrac",
"carrier_service": "Ground",
"tracking_id": "D10010000000000",
"tracking_url": "https://www.ontrac.com/tracking/?number=D10010000000000",
"label": {
"file_type": "PNG",
"url": "https://.../label.png"
}
}
}
  • tracking_url may be null if the carrier URL is not yet available. This is never fatal — the label is still valid.

Error Responses

StatusMeaning
400Request body failed validation, or the address is an Army Post Office / not serviceable
401Missing or invalid credentials, or the token cannot be mapped to a ShipBob user
402Payment declined — update the payment information on the account
409A final-mile label already exists for this order
422An order with this reference_id already exists, or the label could not be purchased/rendered
500Server issue — try again later
502Upstream label purchase failed
503Payment status could not be verified — retry

400 responses include the failing fields:

{
"error": "Invalid request to create order and purchase label.",
"messages": ["\"order.measurements.length_in\" must be a positive number"],
"fields": ["order.measurements.length_in"]
}

How This Differs From POST /api/order:createLabel

Both endpoints create a ShipBob order and return a shipping label, and both produce a normal ShipBob shipment. Choose based on how much of the order you know upfront:

POST /api/v1/CreateOrderAndPurchaseLabelPOST /api/order:createLabel
Use whenYou have a fully packed order — final dimensions, weight, and contents — and want the label immediatelyYou want a label without committing product or dimension detail upfront
measurementsRequired, all four values positive whole numbersOptional
productsRequired, at least oneOptional (used for pick lists and batching)
Label formatorder.label_file_format in the body: PNG (default) or ZPLLabel-Type header: ZPL by default, application/pdf for PDF
Label deliveryHosted URL in final_mile_label.label.urlLabel data inline in label
Also returnsCarrier, carrier service, tracking number, tracking URLOrder and shipment identifiers only
Optional order fieldslabel_file_format, requires_signature only — anything else is ignoredtags, insurance_amount, packing_slip, requires_signature

Both endpoints behave identically downstream. Orders created here appear in Sync Tracking Numbers — including the order.shipment.tracking_received webhook — and can be refunded or resubmitted through Bulk Cancel Labels using the same reference_id.

Available in sandbox at https://logisticslabelprintingapi-stage.shipbob.dev. Use location_id 33 or 19 when testing; contact your ShipBob rep for your production location_id.

Create a Shipping Label

POST /api/order:createLabel

Generate a shipping label for an order. Labels default to ZPL format, but you can request PDF by adding a Label-Type header.

Headers

HeaderValueRequired?Description
Authorization<SBL_authToken> or Bearer <token>YesSBL_authToken, PAT, or OAuth 2.0 access token. See Authentication.
Label-Typeapplication/pdfNoSet to get a PDF label (optional)

Request Body

Send a JSON object with order details:

POST /api/order:createLabel
{
"order": {
"shipping_method": "Standard",
"recipient": {
"name": "Test Test",
"email": "johndoe@shipbob.com",
"phone_number": "444-333-2222",
"address": {
"address1": "223 E 5th St",
"address2": null,
"company_name": null,
"city": "Greenville",
"state": "NC",
"country": "US",
"zip_code": "27957"
}
},
"location_id": 33,
"reference_id": "101",
"measurements": {
"total_weight_oz": 4,
"length_in": 2,
"width_in": 4,
"depth_in": 6
},
"products": [ // optional
{ "name": "Light Roast Coffee", "sku": "LIGHT-ROAST", "quantity": 1 }
],
"tags": [ // optional
{ "name": "size", "value": "small" }
],
"requires_signature": true, // optional
"insurance_amount": 400, // optional
"packing_slip": true // optional
},
"meta": {
"order_number": "101",
"order_id": "101",
"customer_name": "ABC Merch"
}
}

Key Fields

FieldTypeRequiredDescription
shipping_methodstringYesShipping option (e.g., "Standard")
recipientobject[]YesRecipient details (see Recipient table)
location_idintegerYesShipBob location ID. Sandbox: always use 33 or 19. Production: contact your ShipBob rep for your location ID.
reference_idstringYesUnique order identifier
measurementsobjectYesPackage dimensions and weight. All values must be whole numbers. Weight in ounces.
metaobject[]YesExtra information for your records
productsobject[]NoPass products to print pick lists and use batching
requires_signaturebooleanNotrue / false
insurance_amountnumberNoAmount in dollars. If >= 300, requires_signature automatically becomes true.
packing_slipbooleanNotrue / false
tagsobject[]NoKey/value tags

Response

On success (HTTP 200):

{
"interim_order_id": "67c8a7f30c3c1d16d05179db",
"reference_id": "101",
"shipment_id": 100000001,
"label": "<label_data>"
}
  • label: ZPL string or PDF data (based on Label-Type).

Error Responses

  • 400: Bad request (check your JSON).
  • 401: Invalid or missing credentials (SBL_authToken, PAT, or OAuth 2.0 access token).
  • 500: Server issue—try again later.

Bulk Cancel Labels

POST /api/order:bulk-cancel

You can use this endpoint to refund or cancel shipping labels. Additionally, it allows you to cancel and resubmit one or more orders using the same reference_id. Once an order is canceled through this endpoint, it can be resubmitted as needed. However, please note that canceled orders will no longer be accessible in the UI or via the API.

Headers

HeaderValueRequired?Description
Authorization<SBL_authToken> or Bearer <token>YesSBL_authToken, PAT, or OAuth 2.0 access token. See Authentication.
Content-Typeapplication/jsonNoAccepted content type

Request Body

Send a JSON object with order details:

POST /api/order:bulk-cancel
{
"reference_ids": ["ORDER-1","ORDER-2"]
}

Sync Tracking Numbers

To receive tracking updates, subscribe to the order.shipment.tracking_received webhook that fires usually within 5 minutes after creating a shipping label.

Learn how to subscribe here.

Tips for Success

  • Test in the sandbox first (use location_id: 33 for label creation).
  • Generate your Personal Access Token in the ShipBob dashboard for sandbox-api or api.shipbob.com calls.
  • Contact your ShipBob rep for your production location_id or if you hit a 401 error with your SBL_authToken.
  • Poll at least every 30 minutes to avoid missing tracking updates.

Diagram

FAQs

Sign up for a sandbox by following this link.

Other Resources