Update stock and receive returns
Keep stock levels current and tell Nucleo what came back in a return.
Keep stock levels up to date
PUT /stock takes absolute levels — not increments — per item, stock location code and classification, at most 500 items per call. Send the full stock once a day and only what changed in between: items you do not send keep their last level.
curl -X PUT https://api-commerce.nucleoplatform.com/api/fulfillment/v1/stock \
-H "Authorization: Bearer $NUCLEO_FULFILLMENT_KEY" \
-H "Content-Type: application/json" \
-d '{"items": [
{"sku": "TEE-BLK-M", "quantity": 42, "counted_at": "2026-10-13T06:00:00Z"},
{"barcode": "2000000000022", "quantity": 3, "classification": "damaged"}
]}'const batches = (items, size = 500) => Array.from({ length: Math.ceil(items.length / size) }, (_, i) => items.slice(i * size, i * size + size));
for (const items of batches(levelsFromWms)) {
const result = await nucleo("/stock", { method: "PUT", body: { items } });
for (const skipped of result.ignored) console.warn(skipped.reason, skipped.sku ?? skipped.barcode);
}<?php
foreach (array_chunk($levelsFromWms, 500) as $items) {
$result = json_decode($nucleo->put('stock', ['json' => ['items' => $items]])->getBody(), true);
foreach ($result['ignored'] as $skipped) {
error_log($skipped['reason'] . ': ' . ($skipped['sku'] ?? $skipped['barcode']));
}
}- Report stock net of the orders you have accepted. Nucleo subtracts the orders you have not accepted yet before publishing availability, so nothing is sold twice.
- Only
sellablestock (the default) is published as available to the sales channels.damaged,quarantine,reservedandunsellableare stored for the merchant; if the merchant chooses so, they are also published to the sales channel as damaged (not sellable) stock. - Send
counted_at(without it, the time Nucleo receives the call counts): a level older than the last one applied for the same item, location code and classification is not applied and is listed inignoredwith reasonstale, so a late retry cannot roll stock back. location_codeis one of thestock_location_codesfrom/ping; you can omit it when there is only one.- Unknown items are skipped and listed in
ignoredwith reasonunknown_item(the merchant is alerted); the others are applied and counted inaccepted.
Receive returns
Returns approved by the merchant and addressed to your warehouse appear in GET /returns?status=expected (and trigger the return.expected webhook). Confirm you expect one with POST /returns/{id}/accept, then, when the parcel arrives, report what was in it — every item with its condition:
curl -X POST https://api-commerce.nucleoplatform.com/api/fulfillment/v1/returns/R1042-1/receipt \
-H "Authorization: Bearer $NUCLEO_FULFILLMENT_KEY" \
-H "Content-Type: application/json" \
-d '{"lines": [
{"sku": "TEE-BLK-M", "quantity": 1, "condition": "sellable"},
{"sku": "HOOD-GRY-L", "quantity": 1, "condition": "damaged", "note": "Stain on the left sleeve."}
]}'const ret = await nucleo("/returns/R1042-1/receipt", {
method: "POST",
body: {
lines: [
{ sku: "TEE-BLK-M", quantity: 1, condition: "sellable" },
{ sku: "HOOD-GRY-L", quantity: 1, condition: "damaged", note: "Stain on the left sleeve." },
],
},
});
console.log(ret.outcome); // "not_compliant"<?php
$ret = json_decode($nucleo->post('returns/R1042-1/receipt', ['json' => ['lines' => [
['sku' => 'TEE-BLK-M', 'quantity' => 1, 'condition' => 'sellable'],
['sku' => 'HOOD-GRY-L', 'quantity' => 1, 'condition' => 'damaged', 'note' => 'Stain on the left sleeve.'],
]]])->getBody(), true);- Conditions:
sellable,damaged,defective,used,wrong_item. - The return is compliant when every expected item arrived in the expected quantity and
sellable; otherwise not compliant, and the merchant's customer service takes over. Refunds and exchanges are the merchant's business, not the warehouse's. - Report returned stock separately with
PUT /stock: a receipt does not change stock levels. - A second receipt updates only the items it lists — the others keep what you reported before — and the outcome is evaluated again. To correct, list every item again.
- A receipt for a return that is cancelled or already closed is recorded anyway and the merchant is alerted: the goods are in your warehouse and need a decision.
- A parcel nobody announced?
POST /returns/unannouncedwith the order number, your parcel reference and the lines. Nucleo creates the return and alerts the merchant. Sending the same content again returns the same return. Only for orders your warehouse fulfilled: another warehouse's order answers404. status=cancelledlists returns that will not come: stop waiting for them.