Announce an incoming delivery
Tell the warehouse what a supplier is about to deliver, then follow how the goods are received.
When to use this
Use this recipe when your purchasing happens in your own ERP. Your receiving team sees the expected delivery in Picked and scans the goods in against it.
You need:
- a token with the
receipts:writeability (see Authentication). It covers reading a receipt back too; - the id of the warehouse the goods go to:
GET /api/v1/warehouseslists your warehouses with theirwarehouse_id(see Getting started).
Announce the delivery
POST /api/v1/receipts takes one delivery. Each line names a product Picked already knows, by sku or by product_id, not both. Name the supplier with supplier as text, or with supplier_id for a supplier you set up in Picked.
curl -X POST "https://picked.nl/api/v1/receipts" \
-H "Authorization: Bearer $PICKED_TOKEN" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"warehouse_id": 12,
"reference": "INK-2026-0457",
"supplier": "Fietsgroothandel Rijnmond BV",
"expected_at": "2026-10-14",
"lines": [
{ "sku": "BEL-ZW-01", "quantity_expected": 48 },
{ "sku": "BAND-28-622", "quantity_expected": 120 }
]
}'
HTTP/1.1 201 Created
Content-Type: application/json
Location: /api/v1/receipts/731
{
"id": 731,
"reference": "INK-2026-0457",
"status": "expected",
"warehouse_id": 12,
"supplier": "Fietsgroothandel Rijnmond BV",
"expected_at": "2026-10-14",
"expected_total": 168,
"received_total": 0,
"lines": [
{ "product_id": 2210, "sku": "BEL-ZW-01", "quantity_expected": 48, "quantity_received": 0 },
{ "product_id": 9134, "sku": "BAND-28-622", "quantity_expected": 120, "quantity_received": 0 }
],
"created_at": "2026-10-10T09:14:03+02:00",
"_links": {
"self": { "href": "/api/v1/receipts/731" }
}
}
A delivery has 1 to 500 lines. Without expected_at, Picked expects it on the day you announce it.
Always send a reference, such as your purchase order number. Announcing the same reference again returns the receipt from the first call with 200 OK, so a retry never announces a delivery twice. Without one, every call is a new delivery. Idempotency explains the details.
Follow the receiving
Read the receipt back with the id from the answer:
curl "https://picked.nl/api/v1/receipts/731" \
-H "Authorization: Bearer $PICKED_TOKEN" \
-H "Accept: application/json"
HTTP/1.1 200 OK
Content-Type: application/json
{
"id": 731,
"reference": "INK-2026-0457",
"status": "receiving",
"warehouse_id": 12,
"supplier": "Fietsgroothandel Rijnmond BV",
"expected_at": "2026-10-14",
"expected_total": 168,
"received_total": 48,
"lines": [
{ "product_id": 2210, "sku": "BEL-ZW-01", "quantity_expected": 48, "quantity_received": 48 },
{ "product_id": 9134, "sku": "BAND-28-622", "quantity_expected": 120, "quantity_received": 0 }
],
"created_at": "2026-10-10T09:14:03+02:00",
"_links": {
"self": { "href": "/api/v1/receipts/731" }
}
}
status moves forward only: expected → receiving once the first line is received → received once every line is complete → completed when the warehouse closes it. The warehouse can also complete a receipt that is still receiving, so completed doesn't mean every line arrived, and it can cancel a receipt (cancelled) until it is completed. Per line, compare quantity_received with quantity_expected to see what is still missing.
There is no notification when a receipt changes, so read it back now and then, for instance a few times a day while it is open. Stop once it is completed or cancelled.
Errors to handle
| Status | What to do |
|---|---|
422 validation_failed |
Fix the request: errors names each field. A SKU Picked doesn't know is refused here, unlike on orders, so add the product first. |
404 not_found |
On a read: no receipt with that id in your workspace. |
403 missing_ability |
The token lacks receipts:write. |
503 or another 5xx |
Send the same request again after a pause. The reference keeps it from announcing twice. |
Errors lists every code, and Rate limits what to do on a 429.
Try it with a dry run
Add the header Picked-Dry-Run: true to check an announcement without writing anything:
curl -X POST "https://picked.nl/api/v1/receipts" \
-H "Authorization: Bearer $PICKED_TOKEN" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-H "Picked-Dry-Run: true" \
-d '{
"warehouse_id": 12,
"reference": "INK-2026-0458",
"supplier": "Fietsgroothandel Rijnmond BV",
"lines": [
{ "sku": "BEL-ZW-01", "quantity_expected": 24 }
]
}'
HTTP/1.1 200 OK
Content-Type: application/json
{
"id": null,
"reference": "INK-2026-0458",
"status": "expected",
"warehouse_id": 12,
"supplier": "Fietsgroothandel Rijnmond BV",
"expected_at": "2026-10-13",
"expected_total": 24,
"received_total": 0,
"lines": [
{ "product_id": 2210, "sku": "BEL-ZW-01", "quantity_expected": 24, "quantity_received": 0 }
],
"created_at": null,
"dry_run": true,
"would": "created"
}
Read Dry runs for what a dry run checks.