/api/v1/inbound-shipments write:inbound_shipment Tells us a package of your cards is on its way. Send the carrier tracking number as soon as the label exists, and the site — the warehouse the label is addressed to (list them with GET /sites). Each warehouse works only its own incoming list, so a package with the wrong site is not expected where it lands; it is still received there, and received_site then differs from destination_site. When the box reaches the warehouse, the receiving operator scans its label and the shipment moves to RECEIVED. Read that back with GET /inbound-shipments/:id, or wait for the inbound_shipment.received event on your activity log. Received means the box is on our floor, not that its cards are intaken; those still appear one by one in GET /cards as they are scanned. Announcing the same box twice is safe. If you already have a live announcement for this tracking number, or we received a box with it in the last 120 days, you get that shipment back with 200 and created: false instead of a duplicate. Re-announcing a box we already have is therefore a quick way to learn it arrived. To change where a box is going, cancel it and announce it again with the right site. We match on letters and digits only (spaces, dashes and case are ignored), and a USPS or FedEx label barcode matches even though it carries extra digits around the tracking number. Send exactly the number the carrier gave you.
This endpoint needs its own write:inbound_shipment scope. Ask your account manager to add it to your key; no existing scope stands in for it.
POST /api/v1/inbound-shipments write {
"tracking_number": "9400111899223197428490",
"site": "oregon-1",
"carrier": "usps",
"card_count": 120,
"reference": "PO-1001",
"idempotency_key": "docs-inbound-9400111899223197428490"
}Not run yet. Press Run to make a live call against https://service.rip.fun (through this demo's server-side proxy; the API key never reaches the browser).
curl -X POST 'https://service.rip.fun/api/v1/inbound-shipments' \
-H 'X-API-Key: rip_…' \
-H 'Content-Type: application/json' \
-d '{"tracking_number":"9400111899223197428490","site":"oregon-1","carrier":"usps","card_count":120,"reference":"PO-1001","idempotency_key":"docs-inbound-9400111899223197428490"}' | Field | Type | Required | Description |
|---|---|---|---|
tracking_number | string | yes | The carrier tracking number, up to 64 chars. Must contain 8–64 letters or digits once spaces and punctuation are removed |
site | string | yes | The warehouse the package is addressed to, by site code — today "oregon-1", the only site receiving packages. Matched case-insensitively. Must be one of the codes GET /sites returns; a missing code, an unknown one, or a site that is not receiving packages returns 400 naming the valid ones |
carrier | string | — | Free text, up to 32 chars, stored lower-cased: "usps", "ups", "fedex", "dhl", … |
card_count | int | — | How many cards are in the box, 0..100000. Shown to the receiving operator; informational — nothing is billed on it |
reference | string | — | Your own reference for the box (PO, batch, consignment id), up to 128 chars |
note | string | — | Up to 512 chars |
idempotency_key | string | — | Up to 128 chars; a replay returns the original shipment with 200 and created: false |
data)| Field | Description |
|---|---|
inbound_shipment.id / tracking_number / carrier / card_count / reference / note | What you submitted (tracking_number as sent, trimmed) |
inbound_shipment.destination_site | { code, name } — the site you addressed it to. null only on packages announced before sites were required |
inbound_shipment.received_site | { code, name } — where it was actually scanned in; null until it is received. Differs from destination_site when a box arrived at the other warehouse |
inbound_shipment.status | "EXPECTED" on create; EXPECTED → RECEIVED when the warehouse scans it in, or EXPECTED → CANCELLED if you cancel it first |
inbound_shipment.source | "tenant" for a package you announced; "warehouse" for one that arrived unannounced and was logged against your account at the door |
inbound_shipment.created_at / received_at / cancelled_at / updated_at | Timestamps; received_at and cancelled_at are null until they happen |
created | true (201) when this request recorded the announcement; false (200) when the box was already on file |
| Status | Code | When |
|---|---|---|
| 400 | invalid site | site missing, unknown, or a warehouse that is not receiving packages ("texas-1 is not receiving packages — send them to: oregon-1") |
| 409 | no site receiving | no warehouse is taking packages at all right now — contact your account manager |
| 400 | invalid input | tracking_number missing or too short/long, card_count not a whole number in range, a text field over its limit, or idempotency_key over 128 chars |
| 403 | Insufficient permissions | key is tenant-scoped but carries neither write:inbound_shipment nor admin |
See Errors for the response envelope and the full code list.