Skip to content
SyncMyShop

Systems

ShipBob integration with your store and ERP: orders to the warehouse, stock and tracking back

ShipBob allows 150 API requests a minute per user and application, rejects a second order with the same reference_id, and reports several stock numbers of which only one can ship today. We build the integration between ShipBob, your store and your ERP on those rules, then host and run it.

What ShipBob is and who runs it

ShipBob is a fulfillment and storage provider for e-commerce merchants: a third-party logistics company (3PL) with its own network of fulfillment centers. A merchant sends stock in, ShipBob stores it, picks and packs orders and ships them. The integration question is how orders get to ShipBob, and how stock, tracking and returns get back to the store and the ERP.

ShipBob's API has dated versions since July 2025. A new version comes every six months, in January and July, and each is supported for 24 months.

Version Released End of support
1.0 and 2.0 before July 2025 31 July 2026; 1.0 returns 410 Gone from 29 August 2026
2025-07 31 July 2025 31 July 2027
2026-01 31 January 2026 31 January 2028
2026-07 31 July 2026 31 July 2028

An integration built today runs on https://api.shipbob.com/2026-07/ and needs one version step every two years at least.

What connects to ShipBob

The store owns the order. ShipBob owns what is physically in its fulfillment centers. The ERP owns item master data and purchasing.

Flow Direction ShipBob resource
Orders store to ShipBob POST /order with reference_id and shipping_method
Products ERP or store to ShipBob /product, reference_id is the SKU
Stock ShipBob to store and ERP GET /inventory-level
Shipments and tracking ShipBob to store webhooks order.shipped, order.shipment.tracking.updated
Inbound stock ERP to ShipBob warehouse receiving order (WRO)
Returns store to ShipBob and back /return, webhooks return.created, return.completed

A WRO is ShipBob's version of an advance ship notice: the ERP's purchase order becomes a receiving order, and the wro.box.stowed webhook tells the integration when the stock is on the shelf.

How ShipBob exposes data

Authentication and channels

ShipBob accepts a Personal Access Token or OAuth 2.0, both as a bearer token. A Personal Access Token does not expire and has full account access. OAuth gives an access token valid for 1 hour and a refresh token valid for 30 days, renewed on every refresh, with scopes such as orders_write and inventory_read. Every write carries a shipbob_channel_id header. A channel is one installation of an application, and an application can read data from all of the merchant's channels but writes only to its own.

150 requests a minute

ShipBob limits calls to 150 a minute in a sliding window, counted per user and per application across all ShipBob APIs. Over the limit it answers 429 and says how long to wait:

HTTP/1.1 429 Too Many Requests
x-retry-after: 25
x-remaining-calls: 0

{"statusCode":429,"message":"Rate limit is exceeded. Try again in 25 seconds."}

Worked through for a sale day with 3,000 orders: one POST /order each is 3,000 calls, which at 150 a minute is 20 minutes of the full budget. Reading tracking back per order would cost another 3,000 calls and another 20 minutes. With the order.shipped webhook it costs none, and the budget stays for orders, stock and retries. The API throttling and backoff note covers the retry side.

Webhooks

Webhooks are signed with HMAC SHA-256 over webhook-id, webhook-timestamp and the raw body, and the receiver must answer 2xx within 15 seconds. A failed message is retried immediately, then after 5 seconds, 5 minutes, 30 minutes, 2 hours, 5 hours, 10 hours and 10 hours, each period counted from the previous failure. The last attempt comes 27 hours 35 minutes 5 seconds after the first. After that the message is marked failed, and an endpoint that fails for 5 days is disabled. The webhook-id stays the same on a resend, so the integration stores it and drops a message it has already processed. More in webhooks are not a guarantee.

Where a ShipBob integration gets stuck

Which stock number

The inventory-level endpoint returns a set of totals per inventory item: total_on_hand_quantity, total_committed_quantity, total_fulfillable_quantity (on hand minus committed), total_awaiting_quantity, total_backordered_quantity and total_sellable_quantity. Its field reference defines sellable as fulfillable plus awaiting minus quarantine minus damaged. ShipBob's concepts page defines it as fulfillable minus exception orders. The two definitions differ, and the first includes stock that has not arrived.

ShipBob fulfillable quantity against sellable quantity for one SKU 120 units are on hand in ShipBob, 30 are committed to pending orders, so 90 are fulfillable. A receiving order of 200 units is on its way. ShipBob's total_sellable_quantity adds the awaiting quantity, so it reports 290, while only 90 can ship today. On hand in ShipBob fulfillment centers 120 on hand Fulfillable 90 Committed 30 total_fulfillable_quantity 90 Sellable, with a receiving order of 200 on its way 290 Fulfillable 90 Awaiting, not yet received 200 total_sellable_quantity 290 Quarantine and damaged are 0 in this example. Sending sellable to the store sells 200 units that have not arrived.
Fulfillable is what can ship today. ShipBob's sellable field adds stock that is still on its way.

The integration sends total_fulfillable_quantity to the store, per SKU, with a buffer where you want one. The which stock counts note covers the general rule.

Bundles and merges

ShipBob tracks stock per inventory item, not per bundle SKU. A gift pack of 3 items has no stock of its own; its availability is the lowest of its components divided by the quantity each one takes. A merge goes the other way: several products from several channels resolve to one inventory item, and the inventory_id can change after a merge. The integration reconciles its stored inventory IDs on a schedule, as ShipBob's inventory guide recommends. See kits and bundles.

Reference IDs and shipping methods

An order's reference_id must be unique in the account; a second POST gets 422 Duplicate reference ID. Line items identified by reference_id create a new product when no product with that SKU exists, so a SKU with a trailing space or a changed prefix creates an empty product and the shipment goes to exception for missing stock. The integration checks every SKU against the product list before it posts. The shipping_method text must match the ship option mapping in the ShipBob portal exactly; an unknown value creates a new mapping that defaults to Standard, and an express order ships at standard speed.

Platforms and systems we integrate with ShipBob

ShipBob sits between the store and the customer, and often next to an ERP or inventory system:

All flows are listed on integrations. We build the integration for a fixed price, then host, run and monitor it for a monthly fee, with a dashboard, logs and a per-run diff. Before go-live it runs as a dry run that sends nothing to ShipBob. Tell us which store and ERP run next to your ShipBob account.

Frequently asked questions

Should the integration use a Personal Access Token or OAuth?

ShipBob offers both. A Personal Access Token does not expire and has full account access, which suits one merchant's own integration but has to be stored as a secret and rotated by hand. OAuth 2.0 gives an access token valid for 1 hour and a refresh token valid for 30 days, with scopes per resource. Both must be created with the root user of the ShipBob account.

What happens when the same order is sent twice?

ShipBob answers 422 Duplicate reference ID, because reference_id must be unique in the account. The integration treats that answer on a retry as proof the order exists and reads it back with GET orders filtered on ReferenceIds. No second shipment is created. See duplicate customers and orders.

Which stock number goes to the store?

total_fulfillable_quantity: on hand minus committed. ShipBob's total_sellable_quantity adds stock that is still awaiting receipt, so it is higher than what can ship. Bundles are tracked per component, so a bundle's stock is calculated from its parts. A safety buffer per SKU is applied in the integration, as ShipBob's own inventory guide suggests.

Our integration still calls API version 1.0. What now?

Versions 1.0 and 2.0 reached end of support on 31 July 2026. From 8 August 2026 ShipBob blocked a growing share of 1.0 requests, and from 29 August 2026 every 1.0 request returns 410 Gone. The integration has to move to a dated version such as 2026-07, which is supported until 31 July 2028.

How does tracking get back to the store?

Through the order.shipped webhook, which fires when all labels of an order are printed, and order.shipment.tracking.updated for later carrier status. The integration writes carrier and tracking number to the store order and marks the fulfillment there. A poll on LastTrackingUpdateStartDate catches anything a webhook missed.

Tell us what you need

Tell us which systems you use and what needs to work better. We reply personally within one working day. We help you define the work, then agree the price and timing before you commit.

  • You know the price and the timeline before you commit to anything
  • We work out the connection that takes the work off your hands
  • We handle the build, hosting, monitoring and maintenance
  • Your team has less information to retype and fewer discrepancies to chase

Suppliers, products, orders per day, a rough estimate is fine.

Or email directly: carsten@syncmyshop.com