Method POST/partner/dispatch/shipments/{shipment_id}/units

The logistics scan: allocate up to 1000 units to a B2B order, one result per unit. Requires the dispatch:write scope.

On this page

This is the logistics scan. You send the units the picker has just put into the box, up to 1000 per call, and each one gets its own result. A call with 1000 units of which 3 are wrong records the 997 others and names the 3. The whole flow is in the guide Tie each unit to its order.

This call can be replayed: a unit already in the order answers already_in_shipment, never an error, and never a second row.

#Authorization

API key in the Authorization header, Bearer format, with the dispatch:write scope. A key without it gets a 403 whose message names the missing scope. The plan of the key's brand must include API access, and the shipment's brand must be on the Compliance + Identity offer.

HTTP
Authorization: Bearer votre_clef

#Rate limit

The same as the other partner routes: one counter per key and one for the sum of your brand's keys, 120 calls per 60-second window by default. Every call that writes takes 1 unit of the key's daily quota, whatever the number of units it carries.

#Request body

NameTypeRequiredDescription
unitsarray of stringyes1 to 1000 units, each as the scanner read it: the 12-character serial printed on the label, the unit link (https://sealtrust.io/p/{serial}), its GS1 Digital Link (.../01/{gtin}/21/{serial}) or its signed QR link.
reallocatebooleannotrue moves into this order the units that are in another order of your brand. Absent or false, such a unit answers already_allocated.
reasonstringwith reallocateWhy the units move, 200 characters at most. It is written on the old row and in the audit log.

A unit belongs to one active order at a time. The database guarantees it, even when two pickers scan the same unit in the same second.

#Example request

curl
curl -i -X POST "https://api.sealtrust.io/v1/partner/dispatch/shipments/318/units" \
  -H "Authorization: Bearer st_live_0000000000000000000000000000000000000000000000" \
  -H "Content-Type: application/json" \
  -d '{"units": ["H897RFWJ4972", "https://sealtrust.io/p/Y5T2VGGF2NP9", "K2M8Q0R4T6V1", "000000000000"]}'

#Example response

HTTP 200, even when some units are refused.

JSON
{
  "shipment_id": 318,
  "order_ref": "SO-2026-1042",
  "accepted": 2,
  "rejected": 2,
  "units_allocated": 2,
  "results": [
    {"input": "H897RFWJ4972", "status": "allocated", "ok": true, "product_id": 4096, "serial": "H897RFWJ4972", "other_order_ref": null},
    {"input": "https://sealtrust.io/p/Y5T2VGGF2NP9", "status": "allocated", "ok": true, "product_id": 4097, "serial": "Y5T2VGGF2NP9", "other_order_ref": null},
    {"input": "K2M8Q0R4T6V1", "status": "already_allocated", "ok": false, "product_id": 4098, "serial": "K2M8Q0R4T6V1", "other_order_ref": "SO-2026-0998"},
    {"input": "000000000000", "status": "unknown_unit", "ok": false, "product_id": null, "serial": null, "other_order_ref": null}
  ]
}

#The result of each unit

statusokWhat it means
allocatedtrueThe unit is now in this order.
already_in_shipmenttrueIt already was. Nothing changed: a second scan or a replayed call has no effect.
reallocatedtrueIt was in another order, named by other_order_ref, and you asked for the move.
unreadablefalseThe value is not a unit code: neither a serial nor a unit link. A lot or model link names no unit.
unknown_unitfalseNo unit of your brand carries this code. A unit of another brand gets exactly the same answer, so that a code is never confirmed to exist elsewhere.
not_mintedfalseThe unit exists but is not registered on chain yet. Retry once the mint is confirmed.
already_allocatedfalseIt is in another order of your brand, named by other_order_ref. Remove it from that order, or call again with reallocate.

#Errors

CodeConditionWhat to do
401Key missing, malformed or unknown.Send Authorization: Bearer <your key> with the whole key.
403The key lacks the dispatch:write scope. Message Missing required scopes: dispatch:write.Create a key that carries this scope.
403The brand is on the Compliance offer. detail.code is OFFER_EXCLUDES_IDENTITY and detail.feature is dispatch. Nothing is recorded.Move to the Compliance + Identity offer. Retrying changes nothing.
429Rate limit or daily quota reached.Wait the number of seconds in Retry-After, or midnight UTC for the quota.
404No shipment of your brand has this id. A shipment of another brand gets exactly the same answer.Check the id returned at creation.
409The shipment is closed or cancelled. detail.code is shipment_not_open.A closed shipment no longer changes. Create a new order.
400reallocate without reason. detail.code is reason_required.Add a reason.
422More than 1000 units, or an invalid body.Split the batch into calls of 1000 units at most.

Your answer opens a pre-filled email in your mail app, addressed to contact@sealtrust.io. You read it over before sending it.

Suggest a correctionReport a problem