The blog  ·  2026-07-31

The only 3PL that hands you GTIN, lot, and a receiving object

Written for ED-3 — the in-house supply-chain platform team — the platform engineer at a brand whose physical fulfillment lives at a 3PL.

One thesis: everyone's API can tell you something shipped; almost nobody's API can tell you something was received — and ShipBob's Warehouse Receiving Order is the standout exception, a first-class receiving object that compiles straight to a recadv reference, with GTIN-grade product identity and lot support riding along, behind keys you can issue yourself this afternoon.

Why receiving is the rare side

Run the census across our verified connector matrix and the asymmetry is stark. Shipping-shaped objects are everywhere: every ecommerce platform has fulfillments, every parcel aggregator has trackers, every ERP has outbound documents. Receiving-shaped objects — the goods-receipt grain that closes the cycle and feeds a reconcile verdict and closes the cycle as recadv — exist as first-class API objects in exactly seven surfaces: the three full-cycle ERPs, and in the warehouse tier ShipBob's Warehouse Receiving Orders, ShipHero's inbound purchase_orders, Extensiv's /inventory/receivers, and Lightspeed's consignments. That's it. The document CBV names recadv is the least-implemented reference type in the commercial API economy.

Which is why a 3PL API that models receiving properly is worth a post of its own.

The compile map

ShipBob's surface (REST at developer.shipbob.com, date-versioned; auth by self-serve non-expiring PAT or OAuth2-with-PKCE for distributed apps) compiles four-for-four:

  • /orders → the po-adjacent outbound order
  • /shipmentsdesadv
  • /warehouse-receiving-orders — the WRO — → recadv, and the inbound ASN expectation it was received against
  • /returnsrma

Webhooks cover the lifecycle the record cares about — order_shipped, shipment_delivered, shipment_exception, shipment_onhold, shipment_cancelled — and the sandbox at sandbox-api.shipbob.com is full and self-serve, so the entire compile map is verifiable against live calls before any commercial conversation. There is also an official hosted MCP server, which puts ShipBob on the short list of counterparty systems a deputized agent can already operate directly — composable with this layer's own machine door.

Identity: the best in the warehouse tier

The product model carries sku, upc, gtin, and a barcodes[] array — the strongest product-identity posture of any WMS in the matrix, and one of the few places outside the ERP top end where the GTIN gap doesn't apply. Lot support is real: lot_information.is_lot on the product, lot_number and lot_date on inventory — which is exactly the grain FSMA-shaped questions ask in, and it lands as class-level identity and ILMD on the compiled events.

The honest boundary, stated as plainly as the strengths: no SSCC, and fulfillment centers are address-only — no GLN anywhere in the surface. That is not a ShipBob failure; it is the category. No WMS in our matrix exposes GLN or SSCC at all. Logistic-unit identity comes from the EDI rail (the 856's MAN segments are where SSCCs actually live), and facility identity resolves through the party master and the enrichment layer, grade attached.

The proof artifact: one WRO, closed

A WRO for one lot-tracked product, received complete, compiles to the receiving-side skeleton:

{
  "type": "ObjectEvent",
  "action": "OBSERVE",
  "bizStep": "receiving",
  "disposition": "in_progress",
  "quantityList": [
    {
      "epcClass": "urn:epc:class:lgtin:0614141.107346.LOT2026C",
      "quantity": 96,
      "uom": "EA"
    }
  ],
  "bizTransactionList": [
    { "type": "recadv", "bizTransaction": "urn:epc:id:gdti:0614141.00001.WRO8841" },
    { "type": "po", "bizTransaction": "urn:epc:id:gdti:0614141.00001.PO2210" }
  ]
}

The GTIN came from the product's own gtin field, checksum-verified — not scraped from a free-text barcode. The lot came from lot_information. The recadv reference is the WRO itself; the po is the inbound order it fulfilled. Core CBV fields throughout, validated against the pinned official EPCIS 2.0 JSON schema before the pipeline lets go of it: superset where the WRO carries more than the standard models, and conformant always.

The category read

Where the rest of the warehouse tier sits, so you can place your own 3PL on the map. ShipHero (GraphQL, 18 webhook types) models inbound receiving through its purchase_orders and speaks barcode-and-lots, no GTIN-named field. Extensiv's /inventory/receivers is the multi-shipper 3PL's receiving grain, with lot, expiry, and a proprietary palletIdentifier — rich data, but keys are issued by Extensiv and mediated through your warehouse representative rather than self-serve. And the enterprise WMSs — Manhattan Active, Blue Yonder — are customer-gated surfaces with login-walled references: real, reachable only through the customer's own instance, and we say that plainly rather than inferring API shapes we cannot verify anonymously.

The pattern for a brand's platform team: your 3PL's tier decides whether receiving context is an afternoon (ShipBob), a negotiation (Extensiv), or your customer's-side project (enterprise WMS). In every case the compile target is the same recadv reference on the same conformant record — which is what makes the choice reversible.

Why the receiving object outranks the shipping one

Everyone has shipping because shipping is the seller's claim, and sellers fund software. Receiving is the buyer's answer, and the answer is what closes the reconcile loop: the ASN said 96, the WRO says what actually crossed the dock, and the delta is a typed verdict instead of a phone call. A record that carries both references — desadv from the claim side, recadv from the close side — is the record the executive layer can stand on with an auditor in the room.

If your fulfillment runs through a 3PL — this one or any other — tell us which. The access flow asks, because the warehouse branch gets built in the order the answers arrive.


877 words. The access flow is at /get-access/; the family's event door is epcis.dev.