Keep your webshop's stock in sync
Show your customers only what your warehouse can deliver. Read Picked's sellable figure for your products on a schedule and publish it to your shop.
When to use this
Use this recipe when your webshop isn't one of the built-in connectors. A connected shop gets its stock from Picked by itself.
You need a token with the stock:read ability (see Authentication).
Which figure to publish
GET /api/v1/stock gives four figures per product, in total and per warehouse:
| Field | Meaning |
|---|---|
quantity |
Everything on hand, in every location. |
reserved |
Units held for a pick that is under way. |
available |
quantity minus reserved. |
sellable |
What you can still sell: stock in locations you sell from, minus what is reserved and what accepted orders have claimed. Never below zero. |
Publish sellable. It is the figure Picked itself sends to connected shops. Publish the total, not the sum of the warehouses: each warehouse is floored at zero, so the warehouses don't always add up to it.
Read many products at once
Ask for up to 100 SKUs per call, separated by commas:
curl "https://picked.nl/api/v1/stock?skus=BEL-ZW-01,BAND-28-622" \
-H "Authorization: Bearer $PICKED_TOKEN" \
-H "Accept: application/json"
HTTP/1.1 200 OK
Content-Type: application/json
{
"data": [
{
"sku": "BEL-ZW-01",
"quantity": 40,
"reserved": 4,
"available": 36,
"sellable": 30,
"warehouses": [
{ "code": "UTR", "quantity": 40, "reserved": 4, "available": 36, "sellable": 30 }
],
"_links": { "self": { "href": "/api/v1/stock?sku=BEL-ZW-01" } }
},
{
"sku": "BAND-28-622",
"quantity": 0,
"reserved": 0,
"available": 0,
"sellable": 0,
"warehouses": [],
"_links": { "self": { "href": "/api/v1/stock?sku=BAND-28-622" } }
}
],
"_links": {
"self": { "href": "/api/v1/stock?skus=BEL-ZW-01%2CBAND-28-622" }
}
}
The answer lists each SKU once, in the order you asked. A SKU Picked doesn't know comes back with zeros, so a typo looks like an empty shelf: check new SKUs once with a single lookup, which answers 404 for an unknown SKU.
curl "https://picked.nl/api/v1/stock?sku=BEL-ZW-01" \
-H "Authorization: Bearer $PICKED_TOKEN" \
-H "Accept: application/json"
HTTP/1.1 200 OK
Content-Type: application/json
{
"sku": "BEL-ZW-01",
"quantity": 40,
"reserved": 4,
"available": 36,
"sellable": 30,
"warehouses": [
{ "code": "UTR", "quantity": 40, "reserved": 4, "available": 36, "sellable": 30 }
],
"_links": {
"self": { "href": "/api/v1/stock?sku=BEL-ZW-01" }
}
}
Keep it up to date
- First load. Walk your catalogue in groups of 100 SKUs and publish each
sellable. - Then poll for what changed. Every minute or two, ask for the products whose
sellablemay have moved since your last poll, and publish those:
curl "https://picked.nl/api/v1/stock?changed_since=2026-10-12T08:59:00Z" \
-H "Authorization: Bearer $PICKED_TOKEN" \
-H "Accept: application/json"
HTTP/1.1 200 OK
Content-Type: application/json
{
"data": [
{
"sku": "BEL-ZW-01",
"quantity": 40,
"reserved": 4,
"available": 36,
"sellable": 30,
"warehouses": [
{ "code": "UTR", "quantity": 40, "reserved": 4, "available": 36, "sellable": 30 }
],
"_links": { "self": { "href": "/api/v1/stock?sku=BEL-ZW-01" } }
}
],
"pagination": {
"current_page": 1,
"per_page": 100,
"last_page": 1,
"total": 1,
"from": 1,
"to": 1
},
"_links": {
"self": { "href": "/api/v1/stock?changed_since=2026-10-12T08%3A59%3A00Z&page=1" }
}
}
The answer covers every product whose stock changed, that an order claimed or released, or that sits in a location that changed, such as one you stopped selling from. Follow _links.next until it is absent, or read every page until current_page reaches last_page. A product can show up with the figure it already had; publishing it again does no harm. A changed_since more than 30 days back lists every product, as a full reload.
Note the moment you start each poll, taken from the Date header of Picked's last response rather than from your own clock, and use it, minus a minute of overlap, as the next poll's changed_since. The overlap catches a change that was being saved as you asked.
Don't use GET /api/v1/stock/changes to pick which products to update. It lists what happened on the shelves, but an order that claims stock lowers sellable without a stock change. Paging through stock changes explains what that endpoint is for.
Or let Picked push the changes
Rather than polling, subscribe a URL to stock.changed in Settings → Developers → Webhooks: Picked POSTs the product's stock, in the same shape as GET /api/v1/stock?sku=, each time its sellable or available figure changes. Keep a nightly full read as a safety net. See Receive webhooks.
Errors to handle
| Status | What to do |
|---|---|
422 validation_failed |
Send exactly one of sku, skus and changed_since, with at most 100 SKUs. |
404 not_found |
Only on a single sku lookup: Picked has no product with that SKU. |
403 missing_ability |
The token lacks stock:read. |
Errors lists every code, and Rate limits what to do on a 429.
Testing
Reading stock writes nothing, so there's nothing to dry-run. Point your sync at a test shop first, or run it once and compare a few products with the stock overview in Picked.