Contents
Fulfillment API
Connect any warehouse to Nucleo Orders — orders to fulfil, picking, shipments, stock levels and returns.
The native API for warehouse management systems (WMS) and logistics providers that fulfil orders for a merchant on Nucleo Commerce. One API key per warehouse: the key identifies the merchant and the locations your warehouse serves, so every call only sees your orders, lines and returns.
The warehouse is the caller. You read the orders to fulfil, accept them, report the picking and the shipment, keep stock levels up to date and report the returns you receive. Optional webhooks tell you when something changed, so you do not have to poll as often.
Conventions
- JSON in UTF-8,
snake_casefield names, dates in ISO 8601 UTC (2026-10-13T08:30:00Z). - Amounts are decimal strings with their currency:
{"amount": "180.00", "currency": "EUR"}. - Lists are paginated with an opaque cursor:
limit(1–200, default 50), answer{data, next_cursor}. Follownext_cursoruntil it isnull. - Every response carries
X-Request-Id. Errors always have the same shape:{"error": {"code", "message", "request_id", "details"}}. POSTandPUTaccept anIdempotency-Key: a retry with the same key and body returns the first answer without doing the work twice.- Order numbers are the merchant's (
#1042). In paths you can omit the#or encode it as%23.
Authentication
apiKeyHTTP bearer (nfk_…)Authorization: Bearer <api_key>. One key per warehouse connection, issued by Nucleo and shown once. A missing or wrong key — or a call from an IP outside the connection's allowlist, when the merchant set one — answers401. After 30 failed attempts in 5 minutes the calling IP is blocked for the rest of the window.webhookSignatureAPI key · header · X-Nucleo-SignatureWebhooks Nucleo sends to your
webhook_url.X-Nucleo-Signature: t=<unix time>,v1=<signature>, where the signature is the lowercase hex HMAC-SHA256 of<t>.<raw body>keyed with the connection's webhook secret (whsec_…). Verify it on the exact bytes you received, in constant time, and reject atmore than 5 minutes away from your clock.
- Base URL
- https://api-commerce.nucleoplatform.com/api/fulfillment/v1Production
- Who calls it
- Warehouses
- Endpoints
- 17 + 3 webhook
- OpenAPI 3.1 specification
- fulfillment.yaml
Connection
Check that your API key works and see which company, connection and locations it opens.
Getting a key. Nucleo sets up a Fulfillment API connection for your warehouse with the merchant
and links the locations you serve to it. The endpoint, the API key (nfk_…) and the webhook secret
(whsec_…) are shown once; rotating the credentials replaces both at once. A new connection is a
draft and answers 403 connection_not_active until it is turned on.
Base URL. Call the endpoint shown with the credentials: it can be the connection's own host instead of the default server below.
/pingCheck your API key
The company, the connection and the locations your key opens, who makes the carrier labels and whether webhooks are on. Safe to call at any time.
Responses
200The key works.application/json
HeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
api_version"v1"companyobjectChild attributes
idintegernamestring | null
connectionobjectChild attributes
idstring (uuid)namestringstatusstringerrorwhile Nucleo considers the warehouse silent; your next call clears it.One ofactiveerror
locationsarray of objectNucleo locations your warehouse serves.
Attributes of each item
codestringnamestringstock_location_codesarray of stringCodes to use as
location_codein stock updates.
labels_bystringOne ofnucleowarehousewebhooksobjectChild attributes
enabledboolean
server_timestring (date-time)
401Missing or invalid API key (
unauthorized).application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
403The connection is paused (
connection_paused) or not active yet (connection_not_active). Nothing was read or changed: retry later. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
429
rate_limited: more calls in a minute than the connection allows (600 by default, all endpoints together; the merchant can set another limit), or too many failed authentications from your IP. Wait the seconds inRetry-After. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.Retry-AfterSeconds to wait before retrying.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
curl -X GET https://api-commerce.nucleoplatform.com/api/fulfillment/v1/ping \
-H "Authorization: Bearer $NUCLEO_ACCESS_TOKEN" \
-H 'Accept: application/json'const res = await fetch("https://api-commerce.nucleoplatform.com/api/fulfillment/v1/ping", {
method: "GET",
headers: {
Authorization: `Bearer ${process.env.NUCLEO_ACCESS_TOKEN}`,
Accept: "application/json",
},
});
const data = await res.json();
console.log(res.status, data);<?php
require 'vendor/autoload.php';
$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api-commerce.nucleoplatform.com/api/fulfillment/v1/ping', [
'headers' => [
'Authorization' => 'Bearer ' . getenv('NUCLEO_ACCESS_TOKEN'),
'Accept' => 'application/json',
],
'http_errors' => false,
]);
echo $response->getStatusCode(), PHP_EOL;
echo $response->getBody();{
"api_version": "v1",
"company": {
"id": 1042,
"name": "Acme Apparel"
},
"connection": {
"id": "6a1f2c3d-4e5b-4c6d-8e7f-9a0b1c2d3e4f",
"name": "Acme Logistics Verona",
"status": "active"
},
"locations": [
{
"code": "VRN",
"name": "Verona warehouse",
"stock_location_codes": [
"VR1"
]
}
],
"labels_by": "warehouse",
"webhooks": {
"enabled": true
},
"server_time": "2026-10-13T08:30:00Z"
}{
"error": {
"code": "unauthorized",
"message": "Missing or invalid API key.",
"request_id": "0b6c3e4f-1a2d-4c5b-8e7f-9a0b1c2d3e4f"
}
}{
"error": {
"code": "connection_paused",
"message": "This connection is paused: nothing was changed.",
"request_id": "3c2b1a0f-9e8d-4c7b-a6f5-4e3d2c1b0a9f"
}
}{
"error": {
"code": "rate_limited",
"message": "Too many requests: retry after the number of seconds in Retry-After.",
"request_id": "4f3e2d1c-0b9a-4f8e-8d7c-6b5a4f3e2d1c"
}
}Orders
The life of an order in your warehouse:
| Status | Meaning | Your next call |
|---|---|---|
to_fulfill | Ready for your warehouse and not yet accepted. | accept or reject |
accepted | You took it over. | picked |
processed | Picking reported. | shipments |
shipped | Your part has left the warehouse. | — |
cancel_requested | Cancelled by the merchant after you accepted it, with pieces still to ship: stop if you still can. Only warehouses that accepted it see this status; for the others it is cancelled. | cancel to confirm you stopped, or shipments if the parcel already left |
cancelled | Cancelled. | — |
rejected | You refused it; the merchant fixes it and it can come back as to_fulfill. | — |
not_ready | Assigned to you but waiting (payment, hold, documents). | wait |
closed | Nothing left for your warehouse to do — for example you gave up your part of a split order with cancel. | — |
Orders split across warehouses (v1). An order can be split between your warehouse and another one — by line, or even within a line (for example 2 pieces from you, 1 from the other warehouse).
- What works: each warehouse sees only its own lines and its own status. Every quantity you see and report — ordered, open, picked, unfulfillable, shipped, cancelled — is your share of the line; your picking and shipments never change the other warehouse's share. Until you accept the order, your part stays reserved out of the stock you report.
cancelgives up only your part: it becomesclosed, what is left of your share becomes unfulfillable (refunded once, if the merchant enabled automatic refunds), andpickedandshipmentson it answer409 invalid_state. This works also when the other warehouse already shipped its part.- Cancelled by the merchant: in v1 a split order is not closed or refunded automatically. It stays
cancel_requestedfor every warehouse that accepted it and still has something to ship; each one confirms withcancel(then seescancelled) or reports the shipment if its parcel already left (it stays shipped). The merchant completes the cancellation and the refund in Nucleo. A warehouse that never accepted it sees it ascancelledand has nothing to confirm (409 order_not_accepted).
Nothing happens on read. Listing or reading orders never takes them over: only accept does.
Until you accept an order, Nucleo keeps its items reserved out of the stock you report.
/ordersList orders
Orders of your warehouse in one status, with all the details of Get an order.
to_fulfill(default): ready for you and not yet accepted or rejected, oldest first. This is the queue to poll. An order appears here only when everything it needs is ready (payment, carrier, item codes, customs documents when required).accepted,processed,shipped,cancelled: sorted by last update, oldest first. Useupdated_sinceto sync only what changed.cancelledalso includescancel_requestedorders.
Reading never changes an order. A to_fulfill page can hold fewer than limit orders — even none —
while next_cursor is not null: keep following next_cursor until it is null.
Query parameters
statusstringWhich orders to list.
One ofto_fulfillacceptedprocessedshippedcancelleddefault to_fulfillExample:to_fulfillupdated_sincestring (date-time)Only items updated at or after this time (ISO 8601).
Example:2026-10-13T06:00:00Zcursorstringnext_cursorof the previous page. A cursor only works with the samestatus.limitintegerItems per page.
min 1max 200default 50Example:50
Responses
200One page of orders.application/json
HeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
dataarray of OrderrequiredAttributes of each item
idstring (uuid)requirednumberstringrequiredThe merchant's order number.
Example:#1042statusstringrequiredStatus of your warehouse's part of the order (see the Orders tag).
One ofto_fulfillacceptedprocessedshippedcancel_requestedcancelledrejectednot_readyclosedplaced_atstring (date-time) | nullupdated_atstring (date-time)channelstringSales channel the order came from.
Example:shopifycustomerobjectChild attributes
namestring | nullemailstring (email) | nullphonestring | null
shipping_addressAddressChild attributes
first_namestring | nulllast_namestring | nullcompanystring | nulladdress1string | nulladdress2string | nullcitystring | nullpostal_codestring | nullprovince_codestring | nullcountry_codestring | nullISO 3166-1 alpha-2.
phonestring | null
shippingobjectChild attributes
method_codestring | nullShipping method chosen at checkout.
method_namestring | nullcarrier_codestring | nullCarrier to use, from the merchant's carrier rules.
service_codestring | nullCarrier service (for example
EXPRESS).typestringOne ofstandardexpresslabels_bystringWho makes the carrier labels.
One ofnucleowarehouse
priorityinteger1 is the highest. Express orders come first by default.
notesstring | nullNotes for the warehouse (the customer's note and the merchant's instructions).
documentsobjectChild attributes
external_requiredbooleanThe parcel needs customs documents outside (see Get documents).
external_readyboolean | null
currencystringtotal_weight_ginteger | nullSum of the line weights in grams, when known.
linesarray of OrderLinerequiredOnly the lines assigned to your warehouse.
Attributes of each item
line_idstring (uuid)skustring | nullbarcodestring | nullEAN/GTIN of the variant.
item_keystring | nullThe item code agreed with your warehouse (the barcode, unless agreed otherwise).
titlestring | nullquantity_orderedintegerQuantity assigned to your warehouse (your share of the line).
quantity_openintegerStill to ship from your share — ordered minus shipped, cancelled and unfulfillable.
quantity_pickedintegerquantity_unfulfillableintegerDeclared missing in your picking report (or given up with
cancel).quantity_shippedintegerquantity_cancelledintegerweight_ginteger | nullUnit weight in grams, when known.
unit_priceMoneyChild attributes
amountstringrequiredDecimal amount with two decimals.
Example:29.00currencystringrequiredISO 4217 code.
Example:EUR
accepted_atstring (date-time) | nullwms_referencestring | nullYour reference, as sent when accepting.
cancellationobject | nullChild attributes
requested_bystringOne ofmerchantchannelwarehousecancelled_atstring (date-time) | null
next_cursorstring | nullrequiredPass it as
cursorto get the next page;nullon the last page.
400The request is not valid:
validation_failed(withdetailsper field),invalid_json,invalid_cursor. Nothing was changed. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
401Missing or invalid API key (
unauthorized).application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
403The connection is paused (
connection_paused) or not active yet (connection_not_active). Nothing was read or changed: retry later. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
429
rate_limited: more calls in a minute than the connection allows (600 by default, all endpoints together; the merchant can set another limit), or too many failed authentications from your IP. Wait the seconds inRetry-After. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.Retry-AfterSeconds to wait before retrying.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
curl -X GET 'https://api-commerce.nucleoplatform.com/api/fulfillment/v1/orders?status=to_fulfill&updated_since=2026-10-13T06%3A00%3A00Z&limit=50' \
-H "Authorization: Bearer $NUCLEO_ACCESS_TOKEN" \
-H 'Accept: application/json'const res = await fetch("https://api-commerce.nucleoplatform.com/api/fulfillment/v1/orders?status=to_fulfill&updated_since=2026-10-13T06%3A00%3A00Z&limit=50", {
method: "GET",
headers: {
Authorization: `Bearer ${process.env.NUCLEO_ACCESS_TOKEN}`,
Accept: "application/json",
},
});
const data = await res.json();
console.log(res.status, data);<?php
require 'vendor/autoload.php';
$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api-commerce.nucleoplatform.com/api/fulfillment/v1/orders?status=to_fulfill&updated_since=2026-10-13T06%3A00%3A00Z&limit=50', [
'headers' => [
'Authorization' => 'Bearer ' . getenv('NUCLEO_ACCESS_TOKEN'),
'Accept' => 'application/json',
],
'http_errors' => false,
]);
echo $response->getStatusCode(), PHP_EOL;
echo $response->getBody();{
"data": [
{
"id": "3f2a1b4c-5d6e-4f70-8a9b-0c1d2e3f4a5b",
"number": "#1042",
"status": "to_fulfill",
"placed_at": "2026-10-13T08:12:40Z",
"updated_at": "2026-10-13T08:29:51Z",
"channel": "shopify",
"customer": {
"name": "Giulia Verdi",
"email": "giulia.verdi@example.com",
"phone": "+39 333 0000000"
},
"shipping_address": {
"first_name": "Giulia",
"last_name": "Verdi",
"company": null,
"address1": "Via Roma 12",
"address2": "Scala B",
"city": "Milano",
"postal_code": "20121",
"province_code": "MI",
"country_code": "IT",
"phone": "+39 333 0000000"
},
"shipping": {
"method_code": "express",
"method_name": "Express 24h",
"carrier_code": "EXAMPLE",
"service_code": "EXPRESS",
"type": "express",
"labels_by": "warehouse"
},
"priority": 1,
"notes": "Gift wrap, please.",
"documents": {
"external_required": false,
"external_ready": null
},
"currency": "EUR",
"total_weight_g": 1540,
"lines": [
{
"line_id": "0f1e2d3c-4b5a-4968-8776-5a4b3c2d1e0f",
"sku": "TEE-BLK-M",
"barcode": "2000000000015",
"item_key": "2000000000015",
"title": "Organic Cotton Tee · Black · M",
"quantity_ordered": 1,
"quantity_open": 1,
"quantity_picked": 0,
"quantity_unfulfillable": 0,
"quantity_shipped": 0,
"quantity_cancelled": 0,
"weight_g": 220,
"unit_price": {
"amount": "29.00",
"currency": "EUR"
}
},
{
"line_id": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"sku": "HOOD-GRY-L",
"barcode": "2000000000022",
"item_key": "2000000000022",
"title": "Fleece Hoodie · Grey · L",
"quantity_ordered": 2,
"quantity_open": 2,
"quantity_picked": 0,
"quantity_unfulfillable": 0,
"quantity_shipped": 0,
"quantity_cancelled": 0,
"weight_g": 660,
"unit_price": {
"amount": "75.50",
"currency": "EUR"
}
}
],
"accepted_at": null,
"wms_reference": null,
"cancellation": null
}
],
"next_cursor": "WyJvcmRlcnM6dG9fZnVsZmlsbCIsIjIwMjYtMTAtMTMgMDg6MTI6NDEiLCIzZjJhMWI0YyJd"
}{
"error": {
"code": "validation_failed",
"message": "The request is not valid.",
"request_id": "1f7e3c2a-9b8d-4e6f-a5c4-3b2a1d0e9f8c",
"details": {
"lines.0.quantity": [
"The lines.0.quantity field must be at least 0."
],
"reason_code": [
"The reason code field is required."
]
}
}
}{
"error": {
"code": "unauthorized",
"message": "Missing or invalid API key.",
"request_id": "0b6c3e4f-1a2d-4c5b-8e7f-9a0b1c2d3e4f"
}
}{
"error": {
"code": "connection_paused",
"message": "This connection is paused: nothing was changed.",
"request_id": "3c2b1a0f-9e8d-4c7b-a6f5-4e3d2c1b0a9f"
}
}{
"error": {
"code": "rate_limited",
"message": "Too many requests: retry after the number of seconds in Retry-After.",
"request_id": "4f3e2d1c-0b9a-4f8e-8d7c-6b5a4f3e2d1c"
}
}/orders/{number}Get an order
One order of your warehouse, in any status: customer and shipping address, shipping method and carrier, priority, notes for the warehouse, the lines assigned to you with their quantities, weights and prices (for customs), and the status of your part.
An order of another warehouse answers 404, exactly like an order that does not exist.
Path parameters
numberstringrequiredThe merchant's order number. The leading
#can be omitted, or encoded as%23.Example:1042
Responses
200The order.application/json
HeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
idstring (uuid)requirednumberstringrequiredThe merchant's order number.
Example:#1042statusstringrequiredStatus of your warehouse's part of the order (see the Orders tag).
One ofto_fulfillacceptedprocessedshippedcancel_requestedcancelledrejectednot_readyclosedplaced_atstring (date-time) | nullupdated_atstring (date-time)channelstringSales channel the order came from.
Example:shopifycustomerobjectChild attributes
namestring | nullemailstring (email) | nullphonestring | null
shipping_addressAddressChild attributes
first_namestring | nulllast_namestring | nullcompanystring | nulladdress1string | nulladdress2string | nullcitystring | nullpostal_codestring | nullprovince_codestring | nullcountry_codestring | nullISO 3166-1 alpha-2.
phonestring | null
shippingobjectChild attributes
method_codestring | nullShipping method chosen at checkout.
method_namestring | nullcarrier_codestring | nullCarrier to use, from the merchant's carrier rules.
service_codestring | nullCarrier service (for example
EXPRESS).typestringOne ofstandardexpresslabels_bystringWho makes the carrier labels.
One ofnucleowarehouse
priorityinteger1 is the highest. Express orders come first by default.
notesstring | nullNotes for the warehouse (the customer's note and the merchant's instructions).
documentsobjectChild attributes
external_requiredbooleanThe parcel needs customs documents outside (see Get documents).
external_readyboolean | null
currencystringtotal_weight_ginteger | nullSum of the line weights in grams, when known.
linesarray of OrderLinerequiredOnly the lines assigned to your warehouse.
Attributes of each item
line_idstring (uuid)skustring | nullbarcodestring | nullEAN/GTIN of the variant.
item_keystring | nullThe item code agreed with your warehouse (the barcode, unless agreed otherwise).
titlestring | nullquantity_orderedintegerQuantity assigned to your warehouse (your share of the line).
quantity_openintegerStill to ship from your share — ordered minus shipped, cancelled and unfulfillable.
quantity_pickedintegerquantity_unfulfillableintegerDeclared missing in your picking report (or given up with
cancel).quantity_shippedintegerquantity_cancelledintegerweight_ginteger | nullUnit weight in grams, when known.
unit_priceMoneyChild attributes
amountstringrequiredDecimal amount with two decimals.
Example:29.00currencystringrequiredISO 4217 code.
Example:EUR
accepted_atstring (date-time) | nullwms_referencestring | nullYour reference, as sent when accepting.
cancellationobject | nullChild attributes
requested_bystringOne ofmerchantchannelwarehousecancelled_atstring (date-time) | null
401Missing or invalid API key (
unauthorized).application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
403The connection is paused (
connection_paused) or not active yet (connection_not_active). Nothing was read or changed: retry later. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
404
order_not_foundorreturn_not_found— it does not exist or it belongs to another warehouse;not_foundfor an unknown path. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
429
rate_limited: more calls in a minute than the connection allows (600 by default, all endpoints together; the merchant can set another limit), or too many failed authentications from your IP. Wait the seconds inRetry-After. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.Retry-AfterSeconds to wait before retrying.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
curl -X GET https://api-commerce.nucleoplatform.com/api/fulfillment/v1/orders/1042 \
-H "Authorization: Bearer $NUCLEO_ACCESS_TOKEN" \
-H 'Accept: application/json'const res = await fetch("https://api-commerce.nucleoplatform.com/api/fulfillment/v1/orders/1042", {
method: "GET",
headers: {
Authorization: `Bearer ${process.env.NUCLEO_ACCESS_TOKEN}`,
Accept: "application/json",
},
});
const data = await res.json();
console.log(res.status, data);<?php
require 'vendor/autoload.php';
$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api-commerce.nucleoplatform.com/api/fulfillment/v1/orders/1042', [
'headers' => [
'Authorization' => 'Bearer ' . getenv('NUCLEO_ACCESS_TOKEN'),
'Accept' => 'application/json',
],
'http_errors' => false,
]);
echo $response->getStatusCode(), PHP_EOL;
echo $response->getBody();{
"id": "3f2a1b4c-5d6e-4f70-8a9b-0c1d2e3f4a5b",
"number": "#1042",
"status": "to_fulfill",
"placed_at": "2026-10-13T08:12:40Z",
"updated_at": "2026-10-13T08:29:51Z",
"channel": "shopify",
"customer": {
"name": "Giulia Verdi",
"email": "giulia.verdi@example.com",
"phone": "+39 333 0000000"
},
"shipping_address": {
"first_name": "Giulia",
"last_name": "Verdi",
"company": null,
"address1": "Via Roma 12",
"address2": "Scala B",
"city": "Milano",
"postal_code": "20121",
"province_code": "MI",
"country_code": "IT",
"phone": "+39 333 0000000"
},
"shipping": {
"method_code": "express",
"method_name": "Express 24h",
"carrier_code": "EXAMPLE",
"service_code": "EXPRESS",
"type": "express",
"labels_by": "warehouse"
},
"priority": 1,
"notes": "Gift wrap, please.",
"documents": {
"external_required": false,
"external_ready": null
},
"currency": "EUR",
"total_weight_g": 1540,
"lines": [
{
"line_id": "0f1e2d3c-4b5a-4968-8776-5a4b3c2d1e0f",
"sku": "TEE-BLK-M",
"barcode": "2000000000015",
"item_key": "2000000000015",
"title": "Organic Cotton Tee · Black · M",
"quantity_ordered": 1,
"quantity_open": 1,
"quantity_picked": 0,
"quantity_unfulfillable": 0,
"quantity_shipped": 0,
"quantity_cancelled": 0,
"weight_g": 220,
"unit_price": {
"amount": "29.00",
"currency": "EUR"
}
},
{
"line_id": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"sku": "HOOD-GRY-L",
"barcode": "2000000000022",
"item_key": "2000000000022",
"title": "Fleece Hoodie · Grey · L",
"quantity_ordered": 2,
"quantity_open": 2,
"quantity_picked": 0,
"quantity_unfulfillable": 0,
"quantity_shipped": 0,
"quantity_cancelled": 0,
"weight_g": 660,
"unit_price": {
"amount": "75.50",
"currency": "EUR"
}
}
],
"accepted_at": null,
"wms_reference": null,
"cancellation": null
}{
"error": {
"code": "unauthorized",
"message": "Missing or invalid API key.",
"request_id": "0b6c3e4f-1a2d-4c5b-8e7f-9a0b1c2d3e4f"
}
}{
"error": {
"code": "connection_paused",
"message": "This connection is paused: nothing was changed.",
"request_id": "3c2b1a0f-9e8d-4c7b-a6f5-4e3d2c1b0a9f"
}
}{
"error": {
"code": "order_not_found",
"message": "Order 1042 not found.",
"request_id": "6d5c4b3a-2f1e-4d0c-9b8a-7f6e5d4c3b2a"
}
}{
"error": {
"code": "rate_limited",
"message": "Too many requests: retry after the number of seconds in Retry-After.",
"request_id": "4f3e2d1c-0b9a-4f8e-8d7c-6b5a4f3e2d1c"
}
}/orders/{number}/acceptAccept an order
Takes the order over: it leaves to_fulfill and becomes accepted. Optionally store your own
reference for it. Accepting an order you already accepted changes nothing (it only updates
wms_reference if you send one).
When Nucleo makes the labels, the label of the first parcel is created now, ready for Get labels.
409 when the order is not ready yet (order_not_ready), cancelled (order_cancelled,
order_cancel_requested), already picked (invalid_state) or already shipped by your warehouse
(order_already_shipped).
Path parameters
numberstringrequiredThe merchant's order number. The leading
#can be omitted, or encoded as%23.Example:1042
Headers
Idempotency-KeystringAny unique string you generate (1–255 printable ASCII characters, no spaces), for example a UUID. For 48 hours, the same key with the same request — same method, same path written the same way (
/orders/1042and/orders/%231042differ) and same body — returns the stored answer without doing the work again (headerIdempotent-Replayed: true; the replayed body keeps the originalrequest_id, theX-Request-Idheader is the new call's). The same key with a different request answers409 idempotency_key_reused; while the first request is still running,409 idempotency_key_in_progress. A key left in progress for more than 2 minutes (an interrupted call) is free again. Keys are per connection. Server errors (5xx) and429are not stored: retry them with the same key.max length 255Example:2f0c9a1e-6b4d-4f3a-9e7c-5d1b8a2c4e6f
Request bodyapplication/json
wms_referencestring | nullYour own order reference, shown to the merchant.
max length 120
Responses
200The order after the change.application/json
HeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.Idempotent-Replayedtruewhen the answer is the stored one of an earlier request with the sameIdempotency-Key.
idstring (uuid)requirednumberstringrequiredThe merchant's order number.
Example:#1042statusstringrequiredStatus of your warehouse's part of the order (see the Orders tag).
One ofto_fulfillacceptedprocessedshippedcancel_requestedcancelledrejectednot_readyclosedplaced_atstring (date-time) | nullupdated_atstring (date-time)channelstringSales channel the order came from.
Example:shopifycustomerobjectChild attributes
namestring | nullemailstring (email) | nullphonestring | null
shipping_addressAddressChild attributes
first_namestring | nulllast_namestring | nullcompanystring | nulladdress1string | nulladdress2string | nullcitystring | nullpostal_codestring | nullprovince_codestring | nullcountry_codestring | nullISO 3166-1 alpha-2.
phonestring | null
shippingobjectChild attributes
method_codestring | nullShipping method chosen at checkout.
method_namestring | nullcarrier_codestring | nullCarrier to use, from the merchant's carrier rules.
service_codestring | nullCarrier service (for example
EXPRESS).typestringOne ofstandardexpresslabels_bystringWho makes the carrier labels.
One ofnucleowarehouse
priorityinteger1 is the highest. Express orders come first by default.
notesstring | nullNotes for the warehouse (the customer's note and the merchant's instructions).
documentsobjectChild attributes
external_requiredbooleanThe parcel needs customs documents outside (see Get documents).
external_readyboolean | null
currencystringtotal_weight_ginteger | nullSum of the line weights in grams, when known.
linesarray of OrderLinerequiredOnly the lines assigned to your warehouse.
Attributes of each item
line_idstring (uuid)skustring | nullbarcodestring | nullEAN/GTIN of the variant.
item_keystring | nullThe item code agreed with your warehouse (the barcode, unless agreed otherwise).
titlestring | nullquantity_orderedintegerQuantity assigned to your warehouse (your share of the line).
quantity_openintegerStill to ship from your share — ordered minus shipped, cancelled and unfulfillable.
quantity_pickedintegerquantity_unfulfillableintegerDeclared missing in your picking report (or given up with
cancel).quantity_shippedintegerquantity_cancelledintegerweight_ginteger | nullUnit weight in grams, when known.
unit_priceMoneyChild attributes
amountstringrequiredDecimal amount with two decimals.
Example:29.00currencystringrequiredISO 4217 code.
Example:EUR
accepted_atstring (date-time) | nullwms_referencestring | nullYour reference, as sent when accepting.
cancellationobject | nullChild attributes
requested_bystringOne ofmerchantchannelwarehousecancelled_atstring (date-time) | null
400The request is not valid:
validation_failed(withdetailsper field),invalid_json,invalid_cursor. Nothing was changed. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
401Missing or invalid API key (
unauthorized).application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
403The connection is paused (
connection_paused) or not active yet (connection_not_active). Nothing was read or changed: retry later. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
404
order_not_foundorreturn_not_found— it does not exist or it belongs to another warehouse;not_foundfor an unknown path. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
409The request conflicts with the current state:
order_not_ready,order_not_accepted,order_already_accepted,order_cancelled,order_cancel_requested,order_already_shipped,invalid_state,documents_not_ready,labels_not_ready; or with anIdempotency-Key:idempotency_key_reused,idempotency_key_in_progress(withRetry-After). Read the order or return again before retrying. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.Retry-AfterSeconds to wait before retrying.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
429
rate_limited: more calls in a minute than the connection allows (600 by default, all endpoints together; the merchant can set another limit), or too many failed authentications from your IP. Wait the seconds inRetry-After. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.Retry-AfterSeconds to wait before retrying.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
curl -X POST https://api-commerce.nucleoplatform.com/api/fulfillment/v1/orders/1042/accept \
-H "Authorization: Bearer $NUCLEO_ACCESS_TOKEN" \
-H 'Idempotency-Key: 2f0c9a1e-6b4d-4f3a-9e7c-5d1b8a2c4e6f' \
-H 'Content-Type: application/json' \
-d '{
"wms_reference": "VR-2026-004211"
}'const res = await fetch("https://api-commerce.nucleoplatform.com/api/fulfillment/v1/orders/1042/accept", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.NUCLEO_ACCESS_TOKEN}`,
"Idempotency-Key": "2f0c9a1e-6b4d-4f3a-9e7c-5d1b8a2c4e6f",
"Content-Type": "application/json",
},
body: JSON.stringify({
"wms_reference": "VR-2026-004211"
}),
});
const data = await res.json();
console.log(res.status, data);<?php
require 'vendor/autoload.php';
$client = new GuzzleHttp\Client();
$response = $client->request('POST', 'https://api-commerce.nucleoplatform.com/api/fulfillment/v1/orders/1042/accept', [
'headers' => [
'Authorization' => 'Bearer ' . getenv('NUCLEO_ACCESS_TOKEN'),
'Idempotency-Key' => '2f0c9a1e-6b4d-4f3a-9e7c-5d1b8a2c4e6f',
],
'json' => [
'wms_reference' => 'VR-2026-004211',
],
'http_errors' => false,
]);
echo $response->getStatusCode(), PHP_EOL;
echo $response->getBody();{
"id": "9b2f4c1e-5d7a-4e8b-9c3d-2a1f0e6b7c8d",
"number": "#1042",
"status": "to_fulfill",
"placed_at": "2026-10-01T09:30:00Z",
"updated_at": "2026-10-01T09:30:00Z",
"channel": "shopify",
"customer": {
"name": "string",
"email": "jane@example.com",
"phone": "string"
},
"shipping_address": {
"first_name": "string",
"last_name": "string",
"company": "string",
"address1": "string",
"address2": "string",
"city": "string",
"postal_code": "string",
"province_code": "string",
"country_code": "string",
"phone": "string"
},
"shipping": {
"method_code": "string",
"method_name": "string",
"carrier_code": "string",
"service_code": "string",
"type": "standard",
"labels_by": "nucleo"
},
"priority": 1,
"notes": "string",
"documents": {
"external_required": true,
"external_ready": true
},
"currency": "string",
"total_weight_g": 1,
"lines": [
{
"line_id": "9b2f4c1e-5d7a-4e8b-9c3d-2a1f0e6b7c8d",
"sku": "string",
"barcode": "string",
"item_key": "string",
"title": "string",
"quantity_ordered": 1,
"quantity_open": 1,
"quantity_picked": 1,
"quantity_unfulfillable": 1,
"quantity_shipped": 1,
"quantity_cancelled": 1,
"weight_g": 1,
"unit_price": {
"amount": "29.00",
"currency": "EUR"
}
}
],
"accepted_at": "2026-10-01T09:30:00Z",
"wms_reference": "string",
"cancellation": {
"requested_by": "merchant",
"cancelled_at": "2026-10-01T09:30:00Z"
}
}{
"error": {
"code": "validation_failed",
"message": "The request is not valid.",
"request_id": "1f7e3c2a-9b8d-4e6f-a5c4-3b2a1d0e9f8c",
"details": {
"lines.0.quantity": [
"The lines.0.quantity field must be at least 0."
],
"reason_code": [
"The reason code field is required."
]
}
}
}{
"error": {
"code": "unauthorized",
"message": "Missing or invalid API key.",
"request_id": "0b6c3e4f-1a2d-4c5b-8e7f-9a0b1c2d3e4f"
}
}{
"error": {
"code": "connection_paused",
"message": "This connection is paused: nothing was changed.",
"request_id": "3c2b1a0f-9e8d-4c7b-a6f5-4e3d2c1b0a9f"
}
}{
"error": {
"code": "order_not_found",
"message": "Order 1042 not found.",
"request_id": "6d5c4b3a-2f1e-4d0c-9b8a-7f6e5d4c3b2a"
}
}{
"error": {
"code": "order_not_accepted",
"message": "Accept order",
"request_id": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d"
}
}{
"error": {
"code": "rate_limited",
"message": "Too many requests: retry after the number of seconds in Retry-After.",
"request_id": "4f3e2d1c-0b9a-4f8e-8d7c-6b5a4f3e2d1c"
}
}/orders/{number}/rejectReject an order
Refuses an order you have not accepted, with a reason. The merchant is alerted, fixes the order
(for example the address) and releases it again: it then comes back as to_fulfill.
For an order you already accepted use Cancel an order: rejecting it answers
409 order_already_accepted.
Path parameters
numberstringrequiredThe merchant's order number. The leading
#can be omitted, or encoded as%23.Example:1042
Headers
Idempotency-KeystringAny unique string you generate (1–255 printable ASCII characters, no spaces), for example a UUID. For 48 hours, the same key with the same request — same method, same path written the same way (
/orders/1042and/orders/%231042differ) and same body — returns the stored answer without doing the work again (headerIdempotent-Replayed: true; the replayed body keeps the originalrequest_id, theX-Request-Idheader is the new call's). The same key with a different request answers409 idempotency_key_reused; while the first request is still running,409 idempotency_key_in_progress. A key left in progress for more than 2 minutes (an interrupted call) is free again. Keys are per connection. Server errors (5xx) and429are not stored: retry them with the same key.max length 255Example:2f0c9a1e-6b4d-4f3a-9e7c-5d1b8a2c4e6f
Request bodyapplication/json
reason_codestringrequiredYour reason code, shown to the merchant.
max length 30messagestring | nullmax length 500
Responses
200The order after the change.application/json
HeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.Idempotent-Replayedtruewhen the answer is the stored one of an earlier request with the sameIdempotency-Key.
idstring (uuid)requirednumberstringrequiredThe merchant's order number.
Example:#1042statusstringrequiredStatus of your warehouse's part of the order (see the Orders tag).
One ofto_fulfillacceptedprocessedshippedcancel_requestedcancelledrejectednot_readyclosedplaced_atstring (date-time) | nullupdated_atstring (date-time)channelstringSales channel the order came from.
Example:shopifycustomerobjectChild attributes
namestring | nullemailstring (email) | nullphonestring | null
shipping_addressAddressChild attributes
first_namestring | nulllast_namestring | nullcompanystring | nulladdress1string | nulladdress2string | nullcitystring | nullpostal_codestring | nullprovince_codestring | nullcountry_codestring | nullISO 3166-1 alpha-2.
phonestring | null
shippingobjectChild attributes
method_codestring | nullShipping method chosen at checkout.
method_namestring | nullcarrier_codestring | nullCarrier to use, from the merchant's carrier rules.
service_codestring | nullCarrier service (for example
EXPRESS).typestringOne ofstandardexpresslabels_bystringWho makes the carrier labels.
One ofnucleowarehouse
priorityinteger1 is the highest. Express orders come first by default.
notesstring | nullNotes for the warehouse (the customer's note and the merchant's instructions).
documentsobjectChild attributes
external_requiredbooleanThe parcel needs customs documents outside (see Get documents).
external_readyboolean | null
currencystringtotal_weight_ginteger | nullSum of the line weights in grams, when known.
linesarray of OrderLinerequiredOnly the lines assigned to your warehouse.
Attributes of each item
line_idstring (uuid)skustring | nullbarcodestring | nullEAN/GTIN of the variant.
item_keystring | nullThe item code agreed with your warehouse (the barcode, unless agreed otherwise).
titlestring | nullquantity_orderedintegerQuantity assigned to your warehouse (your share of the line).
quantity_openintegerStill to ship from your share — ordered minus shipped, cancelled and unfulfillable.
quantity_pickedintegerquantity_unfulfillableintegerDeclared missing in your picking report (or given up with
cancel).quantity_shippedintegerquantity_cancelledintegerweight_ginteger | nullUnit weight in grams, when known.
unit_priceMoneyChild attributes
amountstringrequiredDecimal amount with two decimals.
Example:29.00currencystringrequiredISO 4217 code.
Example:EUR
accepted_atstring (date-time) | nullwms_referencestring | nullYour reference, as sent when accepting.
cancellationobject | nullChild attributes
requested_bystringOne ofmerchantchannelwarehousecancelled_atstring (date-time) | null
400The request is not valid:
validation_failed(withdetailsper field),invalid_json,invalid_cursor. Nothing was changed. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
401Missing or invalid API key (
unauthorized).application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
403The connection is paused (
connection_paused) or not active yet (connection_not_active). Nothing was read or changed: retry later. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
404
order_not_foundorreturn_not_found— it does not exist or it belongs to another warehouse;not_foundfor an unknown path. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
409The request conflicts with the current state:
order_not_ready,order_not_accepted,order_already_accepted,order_cancelled,order_cancel_requested,order_already_shipped,invalid_state,documents_not_ready,labels_not_ready; or with anIdempotency-Key:idempotency_key_reused,idempotency_key_in_progress(withRetry-After). Read the order or return again before retrying. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.Retry-AfterSeconds to wait before retrying.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
429
rate_limited: more calls in a minute than the connection allows (600 by default, all endpoints together; the merchant can set another limit), or too many failed authentications from your IP. Wait the seconds inRetry-After. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.Retry-AfterSeconds to wait before retrying.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
curl -X POST https://api-commerce.nucleoplatform.com/api/fulfillment/v1/orders/1042/reject \
-H "Authorization: Bearer $NUCLEO_ACCESS_TOKEN" \
-H 'Idempotency-Key: 2f0c9a1e-6b4d-4f3a-9e7c-5d1b8a2c4e6f' \
-H 'Content-Type: application/json' \
-d '{
"reason_code": "ADDRESS_INCOMPLETE",
"message": "Street number missing."
}'const res = await fetch("https://api-commerce.nucleoplatform.com/api/fulfillment/v1/orders/1042/reject", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.NUCLEO_ACCESS_TOKEN}`,
"Idempotency-Key": "2f0c9a1e-6b4d-4f3a-9e7c-5d1b8a2c4e6f",
"Content-Type": "application/json",
},
body: JSON.stringify({
"reason_code": "ADDRESS_INCOMPLETE",
"message": "Street number missing."
}),
});
const data = await res.json();
console.log(res.status, data);<?php
require 'vendor/autoload.php';
$client = new GuzzleHttp\Client();
$response = $client->request('POST', 'https://api-commerce.nucleoplatform.com/api/fulfillment/v1/orders/1042/reject', [
'headers' => [
'Authorization' => 'Bearer ' . getenv('NUCLEO_ACCESS_TOKEN'),
'Idempotency-Key' => '2f0c9a1e-6b4d-4f3a-9e7c-5d1b8a2c4e6f',
],
'json' => [
'reason_code' => 'ADDRESS_INCOMPLETE',
'message' => 'Street number missing.',
],
'http_errors' => false,
]);
echo $response->getStatusCode(), PHP_EOL;
echo $response->getBody();{
"id": "9b2f4c1e-5d7a-4e8b-9c3d-2a1f0e6b7c8d",
"number": "#1042",
"status": "to_fulfill",
"placed_at": "2026-10-01T09:30:00Z",
"updated_at": "2026-10-01T09:30:00Z",
"channel": "shopify",
"customer": {
"name": "string",
"email": "jane@example.com",
"phone": "string"
},
"shipping_address": {
"first_name": "string",
"last_name": "string",
"company": "string",
"address1": "string",
"address2": "string",
"city": "string",
"postal_code": "string",
"province_code": "string",
"country_code": "string",
"phone": "string"
},
"shipping": {
"method_code": "string",
"method_name": "string",
"carrier_code": "string",
"service_code": "string",
"type": "standard",
"labels_by": "nucleo"
},
"priority": 1,
"notes": "string",
"documents": {
"external_required": true,
"external_ready": true
},
"currency": "string",
"total_weight_g": 1,
"lines": [
{
"line_id": "9b2f4c1e-5d7a-4e8b-9c3d-2a1f0e6b7c8d",
"sku": "string",
"barcode": "string",
"item_key": "string",
"title": "string",
"quantity_ordered": 1,
"quantity_open": 1,
"quantity_picked": 1,
"quantity_unfulfillable": 1,
"quantity_shipped": 1,
"quantity_cancelled": 1,
"weight_g": 1,
"unit_price": {
"amount": "29.00",
"currency": "EUR"
}
}
],
"accepted_at": "2026-10-01T09:30:00Z",
"wms_reference": "string",
"cancellation": {
"requested_by": "merchant",
"cancelled_at": "2026-10-01T09:30:00Z"
}
}{
"error": {
"code": "validation_failed",
"message": "The request is not valid.",
"request_id": "1f7e3c2a-9b8d-4e6f-a5c4-3b2a1d0e9f8c",
"details": {
"lines.0.quantity": [
"The lines.0.quantity field must be at least 0."
],
"reason_code": [
"The reason code field is required."
]
}
}
}{
"error": {
"code": "unauthorized",
"message": "Missing or invalid API key.",
"request_id": "0b6c3e4f-1a2d-4c5b-8e7f-9a0b1c2d3e4f"
}
}{
"error": {
"code": "connection_paused",
"message": "This connection is paused: nothing was changed.",
"request_id": "3c2b1a0f-9e8d-4c7b-a6f5-4e3d2c1b0a9f"
}
}{
"error": {
"code": "order_not_found",
"message": "Order 1042 not found.",
"request_id": "6d5c4b3a-2f1e-4d0c-9b8a-7f6e5d4c3b2a"
}
}{
"error": {
"code": "order_not_accepted",
"message": "Accept order",
"request_id": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d"
}
}{
"error": {
"code": "rate_limited",
"message": "Too many requests: retry after the number of seconds in Retry-After.",
"request_id": "4f3e2d1c-0b9a-4f8e-8d7c-6b5a4f3e2d1c"
}
}/orders/{number}/pickedReport the picking
What you picked for an accepted order, with lots, expiry dates and serial numbers, and the parcels you
packed. All or nothing: every line must be an item of this order assigned to your warehouse
(by sku or barcode), otherwise nothing is recorded (422 unknown_item).
Report the quantity actually picked for every item. A quantity lower than ordered marks the missing pieces as unfulfillable: the merchant is alerted and, if configured, the customer is refunded for them. An item you do not list counts as picked 0. You can send it again to correct it until you ship: the last report counts. With automatic refunds, a later report with more pieces missing refunds only the difference; a refund already made is never taken back, so a correction with fewer pieces missing is flagged to the merchant. Report the picking when it is complete.
Labels made by Nucleo. Each parcel you list gets its own label (parcel 1, 2, …): your reference, weight and sizes are added to it and the label's tracking number is kept.
409 order_not_accepted before you accept the order; 409 order_already_shipped after your
shipment; 409 order_cancelled or order_cancel_requested when the merchant cancelled it.
Path parameters
numberstringrequiredThe merchant's order number. The leading
#can be omitted, or encoded as%23.Example:1042
Headers
Idempotency-KeystringAny unique string you generate (1–255 printable ASCII characters, no spaces), for example a UUID. For 48 hours, the same key with the same request — same method, same path written the same way (
/orders/1042and/orders/%231042differ) and same body — returns the stored answer without doing the work again (headerIdempotent-Replayed: true; the replayed body keeps the originalrequest_id, theX-Request-Idheader is the new call's). The same key with a different request answers409 idempotency_key_reused; while the first request is still running,409 idempotency_key_in_progress. A key left in progress for more than 2 minutes (an interrupted call) is free again. Keys are per connection. Server errors (5xx) and429are not stored: retry them with the same key.max length 255Example:2f0c9a1e-6b4d-4f3a-9e7c-5d1b8a2c4e6f
Request bodyapplication/json
picked_atstring (date-time) | nulllinesarray of ItemRef & objectrequiredmin items 1max items 500Attributes of each item
skustring | nullmax length 255barcodestring | nullmax length 255quantityintegerrequiredPieces picked (0 if none).
min 0lot_numberstring | nullmax length 100lot_expirationstring (date) | nullserial_numberstring | nullmax length 100
parcelsarray of ParcelInputAt most 50 parcels, or 10 when Nucleo makes the labels (one label per parcel).
max items 50Attributes of each item
referencestring | nullYour parcel ID.
max length 120tracking_numberstring | nullmax length 120weight_ginteger | nullmin 0height_mminteger | nullmin 0width_mminteger | nullmin 0depth_mminteger | nullmin 0
Responses
200The order after the change.application/json
HeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.Idempotent-Replayedtruewhen the answer is the stored one of an earlier request with the sameIdempotency-Key.
idstring (uuid)requirednumberstringrequiredThe merchant's order number.
Example:#1042statusstringrequiredStatus of your warehouse's part of the order (see the Orders tag).
One ofto_fulfillacceptedprocessedshippedcancel_requestedcancelledrejectednot_readyclosedplaced_atstring (date-time) | nullupdated_atstring (date-time)channelstringSales channel the order came from.
Example:shopifycustomerobjectChild attributes
namestring | nullemailstring (email) | nullphonestring | null
shipping_addressAddressChild attributes
first_namestring | nulllast_namestring | nullcompanystring | nulladdress1string | nulladdress2string | nullcitystring | nullpostal_codestring | nullprovince_codestring | nullcountry_codestring | nullISO 3166-1 alpha-2.
phonestring | null
shippingobjectChild attributes
method_codestring | nullShipping method chosen at checkout.
method_namestring | nullcarrier_codestring | nullCarrier to use, from the merchant's carrier rules.
service_codestring | nullCarrier service (for example
EXPRESS).typestringOne ofstandardexpresslabels_bystringWho makes the carrier labels.
One ofnucleowarehouse
priorityinteger1 is the highest. Express orders come first by default.
notesstring | nullNotes for the warehouse (the customer's note and the merchant's instructions).
documentsobjectChild attributes
external_requiredbooleanThe parcel needs customs documents outside (see Get documents).
external_readyboolean | null
currencystringtotal_weight_ginteger | nullSum of the line weights in grams, when known.
linesarray of OrderLinerequiredOnly the lines assigned to your warehouse.
Attributes of each item
line_idstring (uuid)skustring | nullbarcodestring | nullEAN/GTIN of the variant.
item_keystring | nullThe item code agreed with your warehouse (the barcode, unless agreed otherwise).
titlestring | nullquantity_orderedintegerQuantity assigned to your warehouse (your share of the line).
quantity_openintegerStill to ship from your share — ordered minus shipped, cancelled and unfulfillable.
quantity_pickedintegerquantity_unfulfillableintegerDeclared missing in your picking report (or given up with
cancel).quantity_shippedintegerquantity_cancelledintegerweight_ginteger | nullUnit weight in grams, when known.
unit_priceMoneyChild attributes
amountstringrequiredDecimal amount with two decimals.
Example:29.00currencystringrequiredISO 4217 code.
Example:EUR
accepted_atstring (date-time) | nullwms_referencestring | nullYour reference, as sent when accepting.
cancellationobject | nullChild attributes
requested_bystringOne ofmerchantchannelwarehousecancelled_atstring (date-time) | null
400The request is not valid:
validation_failed(withdetailsper field),invalid_json,invalid_cursor. Nothing was changed. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
401Missing or invalid API key (
unauthorized).application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
403The connection is paused (
connection_paused) or not active yet (connection_not_active). Nothing was read or changed: retry later. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
404
order_not_foundorreturn_not_found— it does not exist or it belongs to another warehouse;not_foundfor an unknown path. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
409The request conflicts with the current state:
order_not_ready,order_not_accepted,order_already_accepted,order_cancelled,order_cancel_requested,order_already_shipped,invalid_state,documents_not_ready,labels_not_ready; or with anIdempotency-Key:idempotency_key_reused,idempotency_key_in_progress(withRetry-After). Read the order or return again before retrying. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.Retry-AfterSeconds to wait before retrying.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
422Valid JSON that cannot be applied:
unknown_item(an item that is not on the order or not known, withdetailsper line),too_many_items,labels_not_enabled. Nothing was changed. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
429
rate_limited: more calls in a minute than the connection allows (600 by default, all endpoints together; the merchant can set another limit), or too many failed authentications from your IP. Wait the seconds inRetry-After. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.Retry-AfterSeconds to wait before retrying.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
curl -X POST https://api-commerce.nucleoplatform.com/api/fulfillment/v1/orders/1042/picked \
-H "Authorization: Bearer $NUCLEO_ACCESS_TOKEN" \
-H 'Idempotency-Key: 2f0c9a1e-6b4d-4f3a-9e7c-5d1b8a2c4e6f' \
-H 'Content-Type: application/json' \
-d '{
"picked_at": "2026-10-13T09:12:00Z",
"lines": [
{
"sku": "TEE-BLK-M",
"quantity": 1
},
{
"barcode": "2000000000022",
"quantity": 2,
"lot_number": "L2026-41",
"lot_expiration": "2028-12-31"
}
],
"parcels": [
{
"reference": "PK-1",
"weight_g": 640,
"height_mm": 80,
"width_mm": 300,
"depth_mm": 400
},
{
"reference": "PK-2",
"weight_g": 980
}
]
}'const res = await fetch("https://api-commerce.nucleoplatform.com/api/fulfillment/v1/orders/1042/picked", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.NUCLEO_ACCESS_TOKEN}`,
"Idempotency-Key": "2f0c9a1e-6b4d-4f3a-9e7c-5d1b8a2c4e6f",
"Content-Type": "application/json",
},
body: JSON.stringify({
"picked_at": "2026-10-13T09:12:00Z",
"lines": [
{
"sku": "TEE-BLK-M",
"quantity": 1
},
{
"barcode": "2000000000022",
"quantity": 2,
"lot_number": "L2026-41",
"lot_expiration": "2028-12-31"
}
],
"parcels": [
{
"reference": "PK-1",
"weight_g": 640,
"height_mm": 80,
"width_mm": 300,
"depth_mm": 400
},
{
"reference": "PK-2",
"weight_g": 980
}
]
}),
});
const data = await res.json();
console.log(res.status, data);<?php
require 'vendor/autoload.php';
$client = new GuzzleHttp\Client();
$response = $client->request('POST', 'https://api-commerce.nucleoplatform.com/api/fulfillment/v1/orders/1042/picked', [
'headers' => [
'Authorization' => 'Bearer ' . getenv('NUCLEO_ACCESS_TOKEN'),
'Idempotency-Key' => '2f0c9a1e-6b4d-4f3a-9e7c-5d1b8a2c4e6f',
],
'json' => [
'picked_at' => '2026-10-13T09:12:00Z',
'lines' => [
[
'sku' => 'TEE-BLK-M',
'quantity' => 1,
],
[
'barcode' => '2000000000022',
'quantity' => 2,
'lot_number' => 'L2026-41',
'lot_expiration' => '2028-12-31',
],
],
'parcels' => [
[
'reference' => 'PK-1',
'weight_g' => 640,
'height_mm' => 80,
'width_mm' => 300,
'depth_mm' => 400,
],
[
'reference' => 'PK-2',
'weight_g' => 980,
],
],
],
'http_errors' => false,
]);
echo $response->getStatusCode(), PHP_EOL;
echo $response->getBody();{
"id": "9b2f4c1e-5d7a-4e8b-9c3d-2a1f0e6b7c8d",
"number": "#1042",
"status": "to_fulfill",
"placed_at": "2026-10-01T09:30:00Z",
"updated_at": "2026-10-01T09:30:00Z",
"channel": "shopify",
"customer": {
"name": "string",
"email": "jane@example.com",
"phone": "string"
},
"shipping_address": {
"first_name": "string",
"last_name": "string",
"company": "string",
"address1": "string",
"address2": "string",
"city": "string",
"postal_code": "string",
"province_code": "string",
"country_code": "string",
"phone": "string"
},
"shipping": {
"method_code": "string",
"method_name": "string",
"carrier_code": "string",
"service_code": "string",
"type": "standard",
"labels_by": "nucleo"
},
"priority": 1,
"notes": "string",
"documents": {
"external_required": true,
"external_ready": true
},
"currency": "string",
"total_weight_g": 1,
"lines": [
{
"line_id": "9b2f4c1e-5d7a-4e8b-9c3d-2a1f0e6b7c8d",
"sku": "string",
"barcode": "string",
"item_key": "string",
"title": "string",
"quantity_ordered": 1,
"quantity_open": 1,
"quantity_picked": 1,
"quantity_unfulfillable": 1,
"quantity_shipped": 1,
"quantity_cancelled": 1,
"weight_g": 1,
"unit_price": {
"amount": "29.00",
"currency": "EUR"
}
}
],
"accepted_at": "2026-10-01T09:30:00Z",
"wms_reference": "string",
"cancellation": {
"requested_by": "merchant",
"cancelled_at": "2026-10-01T09:30:00Z"
}
}{
"error": {
"code": "validation_failed",
"message": "The request is not valid.",
"request_id": "1f7e3c2a-9b8d-4e6f-a5c4-3b2a1d0e9f8c",
"details": {
"lines.0.quantity": [
"The lines.0.quantity field must be at least 0."
],
"reason_code": [
"The reason code field is required."
]
}
}
}{
"error": {
"code": "unauthorized",
"message": "Missing or invalid API key.",
"request_id": "0b6c3e4f-1a2d-4c5b-8e7f-9a0b1c2d3e4f"
}
}{
"error": {
"code": "connection_paused",
"message": "This connection is paused: nothing was changed.",
"request_id": "3c2b1a0f-9e8d-4c7b-a6f5-4e3d2c1b0a9f"
}
}{
"error": {
"code": "order_not_found",
"message": "Order 1042 not found.",
"request_id": "6d5c4b3a-2f1e-4d0c-9b8a-7f6e5d4c3b2a"
}
}{
"error": {
"code": "order_not_accepted",
"message": "Accept order",
"request_id": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d"
}
}{
"error": {
"code": "unknown_item",
"message": "Some lines do not match an item of this order assigned to your warehouse. Nothing was changed.",
"request_id": "2e1d0c9b-8a7f-4e6d-9c5b-4a3f2e1d0c9b",
"details": {
"lines.1": [
"Not an item of this order assigned to your warehouse."
]
}
}
}{
"error": {
"code": "rate_limited",
"message": "Too many requests: retry after the number of seconds in Retry-After.",
"request_id": "4f3e2d1c-0b9a-4f8e-8d7c-6b5a4f3e2d1c"
}
}/orders/{number}/shipmentsReport a shipment
Your part of the order has left the warehouse: carrier, service, one tracking number per parcel. Nucleo marks the order shipped and creates the fulfilment on the sales channel, so the customer gets the tracking.
- Without
lines, the shipment contains what you reported as picked (or, without a picking report, everything still open on your lines). Withlines, only those quantities: use it for partial shipments, then send another shipment for the rest. Once a shipment exists,pickedandcancelanswer409 order_already_shipped: if the rest cannot leave, the merchant sees the order as partly shipped and closes it in Nucleo. - Idempotent on the tracking number: the same first
tracking_numberagain answers200with the shipment already recorded, without a second fulfilment. A different tracking number when nothing is left open answers409 order_already_shipped. - When Nucleo makes the labels,
carrier_codeandparcelsare optional andparcelstakes at most 10 items: withoutparcelsthe shipment has one parcel per ready label, with the tracking numbers of the labels and the carrier and service of the order, and is the same shipment as the labels (sending it again answers200). With no ready label it answers409 labels_not_ready: create the labels first, or send the parcels with their tracking numbers. - The order status is checked first: a cancelled order answers
409 order_cancelled, a part you gave up409 invalid_state, an order you have not accepted409 order_not_accepted. - On a split order the shipment contains only your share, and "nothing left open" means nothing left of your share.
201 for a new shipment, 200 for a repeated one.
Path parameters
numberstringrequiredThe merchant's order number. The leading
#can be omitted, or encoded as%23.Example:1042
Headers
Idempotency-KeystringAny unique string you generate (1–255 printable ASCII characters, no spaces), for example a UUID. For 48 hours, the same key with the same request — same method, same path written the same way (
/orders/1042and/orders/%231042differ) and same body — returns the stored answer without doing the work again (headerIdempotent-Replayed: true; the replayed body keeps the originalrequest_id, theX-Request-Idheader is the new call's). The same key with a different request answers409 idempotency_key_reused; while the first request is still running,409 idempotency_key_in_progress. A key left in progress for more than 2 minutes (an interrupted call) is free again. Keys are per connection. Server errors (5xx) and429are not stored: retry them with the same key.max length 255Example:2f0c9a1e-6b4d-4f3a-9e7c-5d1b8a2c4e6f
Request bodyapplication/json
carrier_codestringmax length 60Example:EXAMPLEcarrier_namestring | nullmax length 120service_codestring | nullmax length 60tracking_urlstring (uri) | nullhttpsonly. Without it Nucleo builds the carrier's tracking link when it knows the carrier.shipped_atstring (date-time) | nullparcelsarray of ParcelInput & objectAt most 50 parcels, or 10 when Nucleo makes the labels.
min items 1max items 50Attributes of each item
referencestring | nullYour parcel ID.
max length 120tracking_numberstring | nullrequiredmax length 120weight_ginteger | nullmin 0height_mminteger | nullmin 0width_mminteger | nullmin 0depth_mminteger | nullmin 0
linesarray of ItemRef & objectPartial shipment only. Omit it to ship everything picked.
Attributes of each item
skustring | nullmax length 255barcodestring | nullmax length 255quantityintegerrequiredmin 1
return_carrier_codestring | nullCarrier of the prepaid return label in the parcel, if any.
max length 60return_tracking_numberstring | nullmax length 120
Responses
200The same shipment was already recorded; nothing changed.application/json
HeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
idstring (uuid)order_numberstringorder_statusstringStatus of your part of the order after the shipment.
carrier_codestring | nullcarrier_namestring | nullservice_codestring | nulltracking_urlstring | nullshipped_atstring (date-time) | nullparcelsarray of objectAttributes of each item
numberintegerreferencestring | nulltracking_numberstring | nullweight_ginteger | null
linesarray of objectAttributes of each item
line_idstring (uuid)skustring | nullbarcodestring | nullquantityinteger
201Shipment recorded.application/json
HeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
idstring (uuid)order_numberstringorder_statusstringStatus of your part of the order after the shipment.
carrier_codestring | nullcarrier_namestring | nullservice_codestring | nulltracking_urlstring | nullshipped_atstring (date-time) | nullparcelsarray of objectAttributes of each item
numberintegerreferencestring | nulltracking_numberstring | nullweight_ginteger | null
linesarray of objectAttributes of each item
line_idstring (uuid)skustring | nullbarcodestring | nullquantityinteger
400The request is not valid:
validation_failed(withdetailsper field),invalid_json,invalid_cursor. Nothing was changed. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
401Missing or invalid API key (
unauthorized).application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
403The connection is paused (
connection_paused) or not active yet (connection_not_active). Nothing was read or changed: retry later. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
404
order_not_foundorreturn_not_found— it does not exist or it belongs to another warehouse;not_foundfor an unknown path. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
409The request conflicts with the current state:
order_not_ready,order_not_accepted,order_already_accepted,order_cancelled,order_cancel_requested,order_already_shipped,invalid_state,documents_not_ready,labels_not_ready; or with anIdempotency-Key:idempotency_key_reused,idempotency_key_in_progress(withRetry-After). Read the order or return again before retrying. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.Retry-AfterSeconds to wait before retrying.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
422Valid JSON that cannot be applied:
unknown_item(an item that is not on the order or not known, withdetailsper line),too_many_items,labels_not_enabled. Nothing was changed. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
429
rate_limited: more calls in a minute than the connection allows (600 by default, all endpoints together; the merchant can set another limit), or too many failed authentications from your IP. Wait the seconds inRetry-After. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.Retry-AfterSeconds to wait before retrying.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
curl -X POST https://api-commerce.nucleoplatform.com/api/fulfillment/v1/orders/1042/shipments \
-H "Authorization: Bearer $NUCLEO_ACCESS_TOKEN" \
-H 'Idempotency-Key: 2f0c9a1e-6b4d-4f3a-9e7c-5d1b8a2c4e6f' \
-H 'Content-Type: application/json' \
-d '{
"carrier_code": "EXAMPLE",
"carrier_name": "Example Express",
"service_code": "EXPRESS",
"shipped_at": "2026-10-13T15:40:00Z",
"tracking_url": "https://tracking.example.com/064152003391",
"parcels": [
{
"tracking_number": "064152003391",
"reference": "PK-1",
"weight_g": 640
},
{
"tracking_number": "064152003392",
"reference": "PK-2",
"weight_g": 980
}
],
"return_carrier_code": "EXAMPLE",
"return_tracking_number": "064152003399"
}'const res = await fetch("https://api-commerce.nucleoplatform.com/api/fulfillment/v1/orders/1042/shipments", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.NUCLEO_ACCESS_TOKEN}`,
"Idempotency-Key": "2f0c9a1e-6b4d-4f3a-9e7c-5d1b8a2c4e6f",
"Content-Type": "application/json",
},
body: JSON.stringify({
"carrier_code": "EXAMPLE",
"carrier_name": "Example Express",
"service_code": "EXPRESS",
"shipped_at": "2026-10-13T15:40:00Z",
"tracking_url": "https://tracking.example.com/064152003391",
"parcels": [
{
"tracking_number": "064152003391",
"reference": "PK-1",
"weight_g": 640
},
{
"tracking_number": "064152003392",
"reference": "PK-2",
"weight_g": 980
}
],
"return_carrier_code": "EXAMPLE",
"return_tracking_number": "064152003399"
}),
});
const data = await res.json();
console.log(res.status, data);<?php
require 'vendor/autoload.php';
$client = new GuzzleHttp\Client();
$response = $client->request('POST', 'https://api-commerce.nucleoplatform.com/api/fulfillment/v1/orders/1042/shipments', [
'headers' => [
'Authorization' => 'Bearer ' . getenv('NUCLEO_ACCESS_TOKEN'),
'Idempotency-Key' => '2f0c9a1e-6b4d-4f3a-9e7c-5d1b8a2c4e6f',
],
'json' => [
'carrier_code' => 'EXAMPLE',
'carrier_name' => 'Example Express',
'service_code' => 'EXPRESS',
'shipped_at' => '2026-10-13T15:40:00Z',
'tracking_url' => 'https://tracking.example.com/064152003391',
'parcels' => [
[
'tracking_number' => '064152003391',
'reference' => 'PK-1',
'weight_g' => 640,
],
[
'tracking_number' => '064152003392',
'reference' => 'PK-2',
'weight_g' => 980,
],
],
'return_carrier_code' => 'EXAMPLE',
'return_tracking_number' => '064152003399',
],
'http_errors' => false,
]);
echo $response->getStatusCode(), PHP_EOL;
echo $response->getBody();{
"id": "9b2f4c1e-5d7a-4e8b-9c3d-2a1f0e6b7c8d",
"order_number": "string",
"order_status": "string",
"carrier_code": "string",
"carrier_name": "string",
"service_code": "string",
"tracking_url": "string",
"shipped_at": "2026-10-01T09:30:00Z",
"parcels": [
{
"number": 1,
"reference": "string",
"tracking_number": "string",
"weight_g": 1
}
],
"lines": [
{
"line_id": "9b2f4c1e-5d7a-4e8b-9c3d-2a1f0e6b7c8d",
"sku": "string",
"barcode": "string",
"quantity": 1
}
]
}{
"id": "2c9d4e1f-7a3b-4c5d-9e8f-0a1b2c3d4e5f",
"order_number": "#1042",
"order_status": "shipped",
"carrier_code": "EXAMPLE",
"carrier_name": "Example Express",
"service_code": "EXPRESS",
"tracking_url": "https://tracking.example.com/064152003391",
"shipped_at": "2026-10-13T15:40:00Z",
"parcels": [
{
"number": 1,
"reference": "PK-1",
"tracking_number": "064152003391",
"weight_g": 640
},
{
"number": 2,
"reference": "PK-2",
"tracking_number": "064152003392",
"weight_g": 980
}
],
"lines": [
{
"line_id": "0f1e2d3c-4b5a-4968-8776-5a4b3c2d1e0f",
"sku": "TEE-BLK-M",
"barcode": "2000000000015",
"quantity": 1
},
{
"line_id": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"sku": "HOOD-GRY-L",
"barcode": "2000000000022",
"quantity": 2
}
]
}{
"error": {
"code": "validation_failed",
"message": "The request is not valid.",
"request_id": "1f7e3c2a-9b8d-4e6f-a5c4-3b2a1d0e9f8c",
"details": {
"lines.0.quantity": [
"The lines.0.quantity field must be at least 0."
],
"reason_code": [
"The reason code field is required."
]
}
}
}{
"error": {
"code": "unauthorized",
"message": "Missing or invalid API key.",
"request_id": "0b6c3e4f-1a2d-4c5b-8e7f-9a0b1c2d3e4f"
}
}{
"error": {
"code": "connection_paused",
"message": "This connection is paused: nothing was changed.",
"request_id": "3c2b1a0f-9e8d-4c7b-a6f5-4e3d2c1b0a9f"
}
}{
"error": {
"code": "order_not_found",
"message": "Order 1042 not found.",
"request_id": "6d5c4b3a-2f1e-4d0c-9b8a-7f6e5d4c3b2a"
}
}{
"error": {
"code": "order_not_accepted",
"message": "Accept order",
"request_id": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d"
}
}{
"error": {
"code": "unknown_item",
"message": "Some lines do not match an item of this order assigned to your warehouse. Nothing was changed.",
"request_id": "2e1d0c9b-8a7f-4e6d-9c5b-4a3f2e1d0c9b",
"details": {
"lines.1": [
"Not an item of this order assigned to your warehouse."
]
}
}
}{
"error": {
"code": "rate_limited",
"message": "Too many requests: retry after the number of seconds in Retry-After.",
"request_id": "4f3e2d1c-0b9a-4f8e-8d7c-6b5a4f3e2d1c"
}
}/orders/{number}/cancelCancel an order
Your warehouse cannot fulfil an order it accepted (stock damaged or missing, address the carrier
refuses…). The order becomes cancelled and the merchant is alerted to cancel and refund it on the
sales channel (or Nucleo does it, if the merchant configured so). Calling it again changes nothing.
- Order split with another warehouse (the other part still open, or already shipped):
cancelgives up only your part. What is left of your share becomes unfulfillable (refunded once, if the merchant enabled automatic refunds), your part becomesclosedandpickedandshipmentsanswer409 invalid_state; the other warehouse goes on with its own lines. - Order in
cancel_requested(the merchant cancelled it after you accepted it):cancelconfirms that you stopped. An order handled only by your warehouse is then closed ascancelled; if part of it already left, that part stays shipped and only the unshipped pieces are cancelled and refunded. A split order stayscancel_requesteduntil the merchant completes the cancellation in Nucleo. A warehouse that never accepted it gets409 order_not_accepted.
409 order_not_accepted for an order you have not accepted — use Reject an order;
409 order_already_shipped after your shipment.
Path parameters
numberstringrequiredThe merchant's order number. The leading
#can be omitted, or encoded as%23.Example:1042
Headers
Idempotency-KeystringAny unique string you generate (1–255 printable ASCII characters, no spaces), for example a UUID. For 48 hours, the same key with the same request — same method, same path written the same way (
/orders/1042and/orders/%231042differ) and same body — returns the stored answer without doing the work again (headerIdempotent-Replayed: true; the replayed body keeps the originalrequest_id, theX-Request-Idheader is the new call's). The same key with a different request answers409 idempotency_key_reused; while the first request is still running,409 idempotency_key_in_progress. A key left in progress for more than 2 minutes (an interrupted call) is free again. Keys are per connection. Server errors (5xx) and429are not stored: retry them with the same key.max length 255Example:2f0c9a1e-6b4d-4f3a-9e7c-5d1b8a2c4e6f
Request bodyapplication/json
reason_codestringrequiredmax length 50messagestring | nullmax length 500cancelled_atstring (date-time) | null
Responses
200The order after the change.application/json
HeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.Idempotent-Replayedtruewhen the answer is the stored one of an earlier request with the sameIdempotency-Key.
idstring (uuid)requirednumberstringrequiredThe merchant's order number.
Example:#1042statusstringrequiredStatus of your warehouse's part of the order (see the Orders tag).
One ofto_fulfillacceptedprocessedshippedcancel_requestedcancelledrejectednot_readyclosedplaced_atstring (date-time) | nullupdated_atstring (date-time)channelstringSales channel the order came from.
Example:shopifycustomerobjectChild attributes
namestring | nullemailstring (email) | nullphonestring | null
shipping_addressAddressChild attributes
first_namestring | nulllast_namestring | nullcompanystring | nulladdress1string | nulladdress2string | nullcitystring | nullpostal_codestring | nullprovince_codestring | nullcountry_codestring | nullISO 3166-1 alpha-2.
phonestring | null
shippingobjectChild attributes
method_codestring | nullShipping method chosen at checkout.
method_namestring | nullcarrier_codestring | nullCarrier to use, from the merchant's carrier rules.
service_codestring | nullCarrier service (for example
EXPRESS).typestringOne ofstandardexpresslabels_bystringWho makes the carrier labels.
One ofnucleowarehouse
priorityinteger1 is the highest. Express orders come first by default.
notesstring | nullNotes for the warehouse (the customer's note and the merchant's instructions).
documentsobjectChild attributes
external_requiredbooleanThe parcel needs customs documents outside (see Get documents).
external_readyboolean | null
currencystringtotal_weight_ginteger | nullSum of the line weights in grams, when known.
linesarray of OrderLinerequiredOnly the lines assigned to your warehouse.
Attributes of each item
line_idstring (uuid)skustring | nullbarcodestring | nullEAN/GTIN of the variant.
item_keystring | nullThe item code agreed with your warehouse (the barcode, unless agreed otherwise).
titlestring | nullquantity_orderedintegerQuantity assigned to your warehouse (your share of the line).
quantity_openintegerStill to ship from your share — ordered minus shipped, cancelled and unfulfillable.
quantity_pickedintegerquantity_unfulfillableintegerDeclared missing in your picking report (or given up with
cancel).quantity_shippedintegerquantity_cancelledintegerweight_ginteger | nullUnit weight in grams, when known.
unit_priceMoneyChild attributes
amountstringrequiredDecimal amount with two decimals.
Example:29.00currencystringrequiredISO 4217 code.
Example:EUR
accepted_atstring (date-time) | nullwms_referencestring | nullYour reference, as sent when accepting.
cancellationobject | nullChild attributes
requested_bystringOne ofmerchantchannelwarehousecancelled_atstring (date-time) | null
400The request is not valid:
validation_failed(withdetailsper field),invalid_json,invalid_cursor. Nothing was changed. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
401Missing or invalid API key (
unauthorized).application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
403The connection is paused (
connection_paused) or not active yet (connection_not_active). Nothing was read or changed: retry later. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
404
order_not_foundorreturn_not_found— it does not exist or it belongs to another warehouse;not_foundfor an unknown path. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
409The request conflicts with the current state:
order_not_ready,order_not_accepted,order_already_accepted,order_cancelled,order_cancel_requested,order_already_shipped,invalid_state,documents_not_ready,labels_not_ready; or with anIdempotency-Key:idempotency_key_reused,idempotency_key_in_progress(withRetry-After). Read the order or return again before retrying. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.Retry-AfterSeconds to wait before retrying.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
429
rate_limited: more calls in a minute than the connection allows (600 by default, all endpoints together; the merchant can set another limit), or too many failed authentications from your IP. Wait the seconds inRetry-After. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.Retry-AfterSeconds to wait before retrying.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
curl -X POST https://api-commerce.nucleoplatform.com/api/fulfillment/v1/orders/1042/cancel \
-H "Authorization: Bearer $NUCLEO_ACCESS_TOKEN" \
-H 'Idempotency-Key: 2f0c9a1e-6b4d-4f3a-9e7c-5d1b8a2c4e6f' \
-H 'Content-Type: application/json' \
-d '{
"reason_code": "OUT_OF_STOCK",
"message": "Last piece found damaged during picking."
}'const res = await fetch("https://api-commerce.nucleoplatform.com/api/fulfillment/v1/orders/1042/cancel", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.NUCLEO_ACCESS_TOKEN}`,
"Idempotency-Key": "2f0c9a1e-6b4d-4f3a-9e7c-5d1b8a2c4e6f",
"Content-Type": "application/json",
},
body: JSON.stringify({
"reason_code": "OUT_OF_STOCK",
"message": "Last piece found damaged during picking."
}),
});
const data = await res.json();
console.log(res.status, data);<?php
require 'vendor/autoload.php';
$client = new GuzzleHttp\Client();
$response = $client->request('POST', 'https://api-commerce.nucleoplatform.com/api/fulfillment/v1/orders/1042/cancel', [
'headers' => [
'Authorization' => 'Bearer ' . getenv('NUCLEO_ACCESS_TOKEN'),
'Idempotency-Key' => '2f0c9a1e-6b4d-4f3a-9e7c-5d1b8a2c4e6f',
],
'json' => [
'reason_code' => 'OUT_OF_STOCK',
'message' => 'Last piece found damaged during picking.',
],
'http_errors' => false,
]);
echo $response->getStatusCode(), PHP_EOL;
echo $response->getBody();{
"id": "9b2f4c1e-5d7a-4e8b-9c3d-2a1f0e6b7c8d",
"number": "#1042",
"status": "to_fulfill",
"placed_at": "2026-10-01T09:30:00Z",
"updated_at": "2026-10-01T09:30:00Z",
"channel": "shopify",
"customer": {
"name": "string",
"email": "jane@example.com",
"phone": "string"
},
"shipping_address": {
"first_name": "string",
"last_name": "string",
"company": "string",
"address1": "string",
"address2": "string",
"city": "string",
"postal_code": "string",
"province_code": "string",
"country_code": "string",
"phone": "string"
},
"shipping": {
"method_code": "string",
"method_name": "string",
"carrier_code": "string",
"service_code": "string",
"type": "standard",
"labels_by": "nucleo"
},
"priority": 1,
"notes": "string",
"documents": {
"external_required": true,
"external_ready": true
},
"currency": "string",
"total_weight_g": 1,
"lines": [
{
"line_id": "9b2f4c1e-5d7a-4e8b-9c3d-2a1f0e6b7c8d",
"sku": "string",
"barcode": "string",
"item_key": "string",
"title": "string",
"quantity_ordered": 1,
"quantity_open": 1,
"quantity_picked": 1,
"quantity_unfulfillable": 1,
"quantity_shipped": 1,
"quantity_cancelled": 1,
"weight_g": 1,
"unit_price": {
"amount": "29.00",
"currency": "EUR"
}
}
],
"accepted_at": "2026-10-01T09:30:00Z",
"wms_reference": "string",
"cancellation": {
"requested_by": "merchant",
"cancelled_at": "2026-10-01T09:30:00Z"
}
}{
"error": {
"code": "validation_failed",
"message": "The request is not valid.",
"request_id": "1f7e3c2a-9b8d-4e6f-a5c4-3b2a1d0e9f8c",
"details": {
"lines.0.quantity": [
"The lines.0.quantity field must be at least 0."
],
"reason_code": [
"The reason code field is required."
]
}
}
}{
"error": {
"code": "unauthorized",
"message": "Missing or invalid API key.",
"request_id": "0b6c3e4f-1a2d-4c5b-8e7f-9a0b1c2d3e4f"
}
}{
"error": {
"code": "connection_paused",
"message": "This connection is paused: nothing was changed.",
"request_id": "3c2b1a0f-9e8d-4c7b-a6f5-4e3d2c1b0a9f"
}
}{
"error": {
"code": "order_not_found",
"message": "Order 1042 not found.",
"request_id": "6d5c4b3a-2f1e-4d0c-9b8a-7f6e5d4c3b2a"
}
}{
"error": {
"code": "order_not_accepted",
"message": "Accept order",
"request_id": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d"
}
}{
"error": {
"code": "rate_limited",
"message": "Too many requests: retry after the number of seconds in Retry-After.",
"request_id": "4f3e2d1c-0b9a-4f8e-8d7c-6b5a4f3e2d1c"
}
}order.readyAn order is ready for your warehouse
Sent when an order assigned to your warehouse becomes ready to fulfil. Read it with
Get an order or poll status=to_fulfill. It is a hint, not the queue: keep polling as
a fallback (for example every 15 minutes), because an order can also become ready later than this
event (customs documents) and a webhook can fail.
Request Nucleo sendsapplication/json
idstring (uuid)requiredUnique per event and the same on every retry. Skip an
idyou already handled.typestringrequiredOne oforder.readyorder.cancelledreturn.expectedcreated_atstring (date-time)requireddataobjectrequiredorder.ready:order_id,order_number.order.cancelled:order_id,order_number,status(cancelledorcancel_requested).return.expected:return_id,return_number,order_number.
Expected response
200Answer with any
2xxwithin 10 seconds; the body is ignored. Any other answer, a redirect or a timeout is retried with exponential backoff (after about 30 seconds, then 1, 2, 4, 8, 16 and 32 minutes): 8 attempts in about an hour, then Nucleo gives up and alerts the merchant. Every attempt carries the sameid(also inX-Nucleo-Webhook-Id) and its number inX-Nucleo-Attempt. While the connection is paused or still a draft no webhook is sent, and the events of that time are not sent later: catch up by polling.
{
"id": "5b7e1c2d-3a4f-4b6c-8d9e-0f1a2b3c4d5e",
"type": "order.ready",
"created_at": "2026-10-13T08:29:51Z",
"data": {
"order_id": "3f2a1b4c-5d6e-4f70-8a9b-0c1d2e3f4a5b",
"order_number": "#1042"
}
}HTTP 200 — Answer with any `2xx` within 10 seconds; the body is ignored. Any other answer, a redirect or a
timeout is retried with exponential backoff (after about 30 seconds, then 1, 2, 4, 8, 16 and 32
minutes): 8 attempts in about an hour, then Nucleo gives up and alerts the merchant. Every attempt
carries the same `id` (also in `X-Nucleo-Webhook-Id`) and its number in `X-Nucleo-Attempt`.
While the connection is paused or still a draft no webhook is sent, and the events of that time are
not sent later: catch up by polling.
order.cancelledAn order was cancelled
Sent once when an order that was ready for your warehouse is cancelled by the merchant or on the
sales channel, with the status your part has: cancelled when you had not accepted it, or
cancel_requested when you had: stop picking if you still can, then cancel it — or
report the shipment if the parcel already left. Not sent to a warehouse that already shipped all its
part or gave it up.
Request Nucleo sendsapplication/json
idstring (uuid)requiredUnique per event and the same on every retry. Skip an
idyou already handled.typestringrequiredOne oforder.readyorder.cancelledreturn.expectedcreated_atstring (date-time)requireddataobjectrequiredorder.ready:order_id,order_number.order.cancelled:order_id,order_number,status(cancelledorcancel_requested).return.expected:return_id,return_number,order_number.
Expected response
200Answer with any
2xxwithin 10 seconds; the body is ignored. Any other answer, a redirect or a timeout is retried with exponential backoff (after about 30 seconds, then 1, 2, 4, 8, 16 and 32 minutes): 8 attempts in about an hour, then Nucleo gives up and alerts the merchant. Every attempt carries the sameid(also inX-Nucleo-Webhook-Id) and its number inX-Nucleo-Attempt. While the connection is paused or still a draft no webhook is sent, and the events of that time are not sent later: catch up by polling.
{
"id": "8c9d0e1f-2a3b-4c4d-9e5f-6a7b8c9d0e1f",
"type": "order.cancelled",
"created_at": "2026-10-13T10:02:14Z",
"data": {
"order_id": "3f2a1b4c-5d6e-4f70-8a9b-0c1d2e3f4a5b",
"order_number": "#1042",
"status": "cancel_requested"
}
}HTTP 200 — Answer with any `2xx` within 10 seconds; the body is ignored. Any other answer, a redirect or a
timeout is retried with exponential backoff (after about 30 seconds, then 1, 2, 4, 8, 16 and 32
minutes): 8 attempts in about an hour, then Nucleo gives up and alerts the merchant. Every attempt
carries the same `id` (also in `X-Nucleo-Webhook-Id`) and its number in `X-Nucleo-Attempt`.
While the connection is paused or still a draft no webhook is sent, and the events of that time are
not sent later: catch up by polling.
Labels and documents
When the merchant has Nucleo create the carrier labels (through the shipping platform connected to
Nucleo), you download them here instead of making your own. shipping.labels_by on the order tells
you who makes them: nucleo or warehouse. The carrier and service come from the order
(shipping.carrier_code, shipping.service_code), the tracking numbers from the labels. At most 10
labels (parcels) per order and warehouse. Documents (invoices, customs documents, inserts) are
available for every order.
/orders/{number}/labelsGet labels
The carrier labels Nucleo created for the order, one per parcel, as base64 content (PDF, 10×15 cm,
or ZPL). A label that could not be created has status: failed and no content: create it again with
Create labels. After your shipment it shows the labels the shipment left with.
Reading never creates anything.
Only when Nucleo makes the labels (shipping.labels_by: nucleo); otherwise 422 labels_not_enabled.
Path parameters
numberstringrequiredThe merchant's order number. The leading
#can be omitted, or encoded as%23.Example:1042
Responses
200Labels of the order.application/json
HeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
dataarray of LabelrequiredAttributes of each item
parcelintegerParcel number, from 1.
statusstringOne ofreadyfailedcarrier_codestring | nullcarrier_namestring | nulltracking_numberstring | nullformatstringOne ofpdfzplcontent_typestringOne ofapplication/pdfapplication/x-zplcontent_base64string | nullThe label file, base64-encoded;
nullwhenstatusisfailed.
401Missing or invalid API key (
unauthorized).application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
403The connection is paused (
connection_paused) or not active yet (connection_not_active). Nothing was read or changed: retry later. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
404
order_not_foundorreturn_not_found— it does not exist or it belongs to another warehouse;not_foundfor an unknown path. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
422Valid JSON that cannot be applied:
unknown_item(an item that is not on the order or not known, withdetailsper line),too_many_items,labels_not_enabled. Nothing was changed. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
429
rate_limited: more calls in a minute than the connection allows (600 by default, all endpoints together; the merchant can set another limit), or too many failed authentications from your IP. Wait the seconds inRetry-After. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.Retry-AfterSeconds to wait before retrying.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
curl -X GET https://api-commerce.nucleoplatform.com/api/fulfillment/v1/orders/1042/labels \
-H "Authorization: Bearer $NUCLEO_ACCESS_TOKEN" \
-H 'Accept: application/json'const res = await fetch("https://api-commerce.nucleoplatform.com/api/fulfillment/v1/orders/1042/labels", {
method: "GET",
headers: {
Authorization: `Bearer ${process.env.NUCLEO_ACCESS_TOKEN}`,
Accept: "application/json",
},
});
const data = await res.json();
console.log(res.status, data);<?php
require 'vendor/autoload.php';
$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api-commerce.nucleoplatform.com/api/fulfillment/v1/orders/1042/labels', [
'headers' => [
'Authorization' => 'Bearer ' . getenv('NUCLEO_ACCESS_TOKEN'),
'Accept' => 'application/json',
],
'http_errors' => false,
]);
echo $response->getStatusCode(), PHP_EOL;
echo $response->getBody();{
"data": [
{
"parcel": 1,
"status": "ready",
"carrier_code": "EXAMPLE",
"carrier_name": "Example Express",
"tracking_number": "1234567890",
"format": "pdf",
"content_type": "application/pdf",
"content_base64": "JVBERi0xLjQKJcfsj6IKNSAwIG9iago8PC9MZW5ndGggNiAwIFI+PgpzdHJlYW0K"
}
]
}{
"error": {
"code": "unauthorized",
"message": "Missing or invalid API key.",
"request_id": "0b6c3e4f-1a2d-4c5b-8e7f-9a0b1c2d3e4f"
}
}{
"error": {
"code": "connection_paused",
"message": "This connection is paused: nothing was changed.",
"request_id": "3c2b1a0f-9e8d-4c7b-a6f5-4e3d2c1b0a9f"
}
}{
"error": {
"code": "order_not_found",
"message": "Order 1042 not found.",
"request_id": "6d5c4b3a-2f1e-4d0c-9b8a-7f6e5d4c3b2a"
}
}{
"error": {
"code": "unknown_item",
"message": "Some lines do not match an item of this order assigned to your warehouse. Nothing was changed.",
"request_id": "2e1d0c9b-8a7f-4e6d-9c5b-4a3f2e1d0c9b",
"details": {
"lines.1": [
"Not an item of this order assigned to your warehouse."
]
}
}
}{
"error": {
"code": "rate_limited",
"message": "Too many requests: retry after the number of seconds in Retry-After.",
"request_id": "4f3e2d1c-0b9a-4f8e-8d7c-6b5a4f3e2d1c"
}
}/orders/{number}/labelsCreate labels
Makes sure there is one label for each parcel from 1 to parcels (at most 10): creates the missing
ones and retries the failed ones; labels already created are kept. Answers with all the labels of
the order. Only once your part is accepted (409 order_not_accepted before), and while you still
have something to ship: after a partial shipment it creates new labels for the rest, and the next
shipment without parcels takes them. Not for a cancelled part (409 order_cancelled,
409 order_cancel_requested), nor when your part is shipped in full or given up (409 invalid_state).
Path parameters
numberstringrequiredThe merchant's order number. The leading
#can be omitted, or encoded as%23.Example:1042
Headers
Idempotency-KeystringAny unique string you generate (1–255 printable ASCII characters, no spaces), for example a UUID. For 48 hours, the same key with the same request — same method, same path written the same way (
/orders/1042and/orders/%231042differ) and same body — returns the stored answer without doing the work again (headerIdempotent-Replayed: true; the replayed body keeps the originalrequest_id, theX-Request-Idheader is the new call's). The same key with a different request answers409 idempotency_key_reused; while the first request is still running,409 idempotency_key_in_progress. A key left in progress for more than 2 minutes (an interrupted call) is free again. Keys are per connection. Server errors (5xx) and429are not stored: retry them with the same key.max length 255Example:2f0c9a1e-6b4d-4f3a-9e7c-5d1b8a2c4e6f
Request bodyapplication/json
parcelsintegerrequiredNumber of parcels the order ships in.
min 1max 10
Responses
201Labels of the order, including the new ones.application/json
HeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
dataarray of LabelrequiredAttributes of each item
parcelintegerParcel number, from 1.
statusstringOne ofreadyfailedcarrier_codestring | nullcarrier_namestring | nulltracking_numberstring | nullformatstringOne ofpdfzplcontent_typestringOne ofapplication/pdfapplication/x-zplcontent_base64string | nullThe label file, base64-encoded;
nullwhenstatusisfailed.
400The request is not valid:
validation_failed(withdetailsper field),invalid_json,invalid_cursor. Nothing was changed. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
401Missing or invalid API key (
unauthorized).application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
403The connection is paused (
connection_paused) or not active yet (connection_not_active). Nothing was read or changed: retry later. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
404
order_not_foundorreturn_not_found— it does not exist or it belongs to another warehouse;not_foundfor an unknown path. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
409The request conflicts with the current state:
order_not_ready,order_not_accepted,order_already_accepted,order_cancelled,order_cancel_requested,order_already_shipped,invalid_state,documents_not_ready,labels_not_ready; or with anIdempotency-Key:idempotency_key_reused,idempotency_key_in_progress(withRetry-After). Read the order or return again before retrying. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.Retry-AfterSeconds to wait before retrying.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
422Valid JSON that cannot be applied:
unknown_item(an item that is not on the order or not known, withdetailsper line),too_many_items,labels_not_enabled. Nothing was changed. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
429
rate_limited: more calls in a minute than the connection allows (600 by default, all endpoints together; the merchant can set another limit), or too many failed authentications from your IP. Wait the seconds inRetry-After. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.Retry-AfterSeconds to wait before retrying.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
curl -X POST https://api-commerce.nucleoplatform.com/api/fulfillment/v1/orders/1042/labels \
-H "Authorization: Bearer $NUCLEO_ACCESS_TOKEN" \
-H 'Idempotency-Key: 2f0c9a1e-6b4d-4f3a-9e7c-5d1b8a2c4e6f' \
-H 'Content-Type: application/json' \
-d '{
"parcels": 2
}'const res = await fetch("https://api-commerce.nucleoplatform.com/api/fulfillment/v1/orders/1042/labels", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.NUCLEO_ACCESS_TOKEN}`,
"Idempotency-Key": "2f0c9a1e-6b4d-4f3a-9e7c-5d1b8a2c4e6f",
"Content-Type": "application/json",
},
body: JSON.stringify({
"parcels": 2
}),
});
const data = await res.json();
console.log(res.status, data);<?php
require 'vendor/autoload.php';
$client = new GuzzleHttp\Client();
$response = $client->request('POST', 'https://api-commerce.nucleoplatform.com/api/fulfillment/v1/orders/1042/labels', [
'headers' => [
'Authorization' => 'Bearer ' . getenv('NUCLEO_ACCESS_TOKEN'),
'Idempotency-Key' => '2f0c9a1e-6b4d-4f3a-9e7c-5d1b8a2c4e6f',
],
'json' => [
'parcels' => 2,
],
'http_errors' => false,
]);
echo $response->getStatusCode(), PHP_EOL;
echo $response->getBody();{
"data": [
{
"parcel": 1,
"status": "ready",
"carrier_code": "string",
"carrier_name": "string",
"tracking_number": "string",
"format": "pdf",
"content_type": "application/pdf",
"content_base64": "string"
}
]
}{
"error": {
"code": "validation_failed",
"message": "The request is not valid.",
"request_id": "1f7e3c2a-9b8d-4e6f-a5c4-3b2a1d0e9f8c",
"details": {
"lines.0.quantity": [
"The lines.0.quantity field must be at least 0."
],
"reason_code": [
"The reason code field is required."
]
}
}
}{
"error": {
"code": "unauthorized",
"message": "Missing or invalid API key.",
"request_id": "0b6c3e4f-1a2d-4c5b-8e7f-9a0b1c2d3e4f"
}
}{
"error": {
"code": "connection_paused",
"message": "This connection is paused: nothing was changed.",
"request_id": "3c2b1a0f-9e8d-4c7b-a6f5-4e3d2c1b0a9f"
}
}{
"error": {
"code": "order_not_found",
"message": "Order 1042 not found.",
"request_id": "6d5c4b3a-2f1e-4d0c-9b8a-7f6e5d4c3b2a"
}
}{
"error": {
"code": "order_not_accepted",
"message": "Accept order",
"request_id": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d"
}
}{
"error": {
"code": "unknown_item",
"message": "Some lines do not match an item of this order assigned to your warehouse. Nothing was changed.",
"request_id": "2e1d0c9b-8a7f-4e6d-9c5b-4a3f2e1d0c9b",
"details": {
"lines.1": [
"Not an item of this order assigned to your warehouse."
]
}
}
}{
"error": {
"code": "rate_limited",
"message": "Too many requests: retry after the number of seconds in Retry-After.",
"request_id": "4f3e2d1c-0b9a-4f8e-8d7c-6b5a4f3e2d1c"
}
}/orders/{number}/documentsGet documents
Documents to print and put in the parcel, as base64 PDFs: the order's documents (invoice, customs
documents) with kind: order_document, and the merchant's inserts in the customer's language
(return instructions, leaflets) with kind: insert. position says whether a document goes
inside the parcel (internal) or in the document pouch outside (external).
When the order needs customs documents that are not ready yet, 409 documents_not_ready: retry
later. Such orders do not appear in to_fulfill until their documents are ready.
Path parameters
numberstringrequiredThe merchant's order number. The leading
#can be omitted, or encoded as%23.Example:1042
Responses
200Documents of the order (possibly none).application/json
HeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
dataarray of DocumentrequiredAttributes of each item
idstringnamestringkindstringOne oforder_documentinsertpositionstring | nullOne ofinternalexternalnullpage_formatstringExample:A4content_type"application/pdf"content_base64string
401Missing or invalid API key (
unauthorized).application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
403The connection is paused (
connection_paused) or not active yet (connection_not_active). Nothing was read or changed: retry later. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
404
order_not_foundorreturn_not_found— it does not exist or it belongs to another warehouse;not_foundfor an unknown path. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
409The request conflicts with the current state:
order_not_ready,order_not_accepted,order_already_accepted,order_cancelled,order_cancel_requested,order_already_shipped,invalid_state,documents_not_ready,labels_not_ready; or with anIdempotency-Key:idempotency_key_reused,idempotency_key_in_progress(withRetry-After). Read the order or return again before retrying. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.Retry-AfterSeconds to wait before retrying.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
429
rate_limited: more calls in a minute than the connection allows (600 by default, all endpoints together; the merchant can set another limit), or too many failed authentications from your IP. Wait the seconds inRetry-After. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.Retry-AfterSeconds to wait before retrying.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
curl -X GET https://api-commerce.nucleoplatform.com/api/fulfillment/v1/orders/1042/documents \
-H "Authorization: Bearer $NUCLEO_ACCESS_TOKEN" \
-H 'Accept: application/json'const res = await fetch("https://api-commerce.nucleoplatform.com/api/fulfillment/v1/orders/1042/documents", {
method: "GET",
headers: {
Authorization: `Bearer ${process.env.NUCLEO_ACCESS_TOKEN}`,
Accept: "application/json",
},
});
const data = await res.json();
console.log(res.status, data);<?php
require 'vendor/autoload.php';
$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api-commerce.nucleoplatform.com/api/fulfillment/v1/orders/1042/documents', [
'headers' => [
'Authorization' => 'Bearer ' . getenv('NUCLEO_ACCESS_TOKEN'),
'Accept' => 'application/json',
],
'http_errors' => false,
]);
echo $response->getStatusCode(), PHP_EOL;
echo $response->getBody();{
"data": [
{
"id": "7d1c2b3a-4e5f-4a6b-9c8d-1e2f3a4b5c6d",
"name": "Invoice-2026-001042",
"kind": "order_document",
"position": "external",
"page_format": "A4",
"content_type": "application/pdf",
"content_base64": "JVBERi0xLjQKJcfsj6IKNSAwIG9iago8PC9MZW5ndGggNiAwIFI+PgpzdHJlYW0K"
}
]
}{
"error": {
"code": "unauthorized",
"message": "Missing or invalid API key.",
"request_id": "0b6c3e4f-1a2d-4c5b-8e7f-9a0b1c2d3e4f"
}
}{
"error": {
"code": "connection_paused",
"message": "This connection is paused: nothing was changed.",
"request_id": "3c2b1a0f-9e8d-4c7b-a6f5-4e3d2c1b0a9f"
}
}{
"error": {
"code": "order_not_found",
"message": "Order 1042 not found.",
"request_id": "6d5c4b3a-2f1e-4d0c-9b8a-7f6e5d4c3b2a"
}
}{
"error": {
"code": "order_not_accepted",
"message": "Accept order",
"request_id": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d"
}
}{
"error": {
"code": "rate_limited",
"message": "Too many requests: retry after the number of seconds in Retry-After.",
"request_id": "4f3e2d1c-0b9a-4f8e-8d7c-6b5a4f3e2d1c"
}
}Stock
Absolute stock levels per item, warehouse location code and classification. Send everything or only what changed: items you do not send keep their last level. Report stock net of the orders you have accepted; Nucleo subtracts the orders you have not accepted yet before publishing availability to the sales channels.
/stockUpdate stock levels
Absolute levels (not increments) per item, location code and classification, at most 500 items
per call (the merchant can set a different limit; above it nothing is processed and the answer is
422 too_many_items: split the update in batches).
- Identify each item by
skuorbarcode. location_codeis one of thestock_location_codesreturned by Ping. It can be omitted when your connection has a single code.classificationdefaults tosellable; onlysellablestock is published as available to the sales channels. Other classifications are stored and, if the merchant chooses so, published as damaged (not sellable) stock.counted_at: when the level was counted; without it, the time Nucleo receives the call. 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 late retries cannot roll stock back.
Unknown items are ignored (listed in ignored with reason unknown_item, and the merchant is
alerted); the others are applied and counted in accepted. A location code not linked to a Nucleo location yet is saved but not published, and listed
in warnings. Validation errors (400) reject the whole call.
Headers
Idempotency-KeystringAny unique string you generate (1–255 printable ASCII characters, no spaces), for example a UUID. For 48 hours, the same key with the same request — same method, same path written the same way (
/orders/1042and/orders/%231042differ) and same body — returns the stored answer without doing the work again (headerIdempotent-Replayed: true; the replayed body keeps the originalrequest_id, theX-Request-Idheader is the new call's). The same key with a different request answers409 idempotency_key_reused; while the first request is still running,409 idempotency_key_in_progress. A key left in progress for more than 2 minutes (an interrupted call) is free again. Keys are per connection. Server errors (5xx) and429are not stored: retry them with the same key.max length 255Example:2f0c9a1e-6b4d-4f3a-9e7c-5d1b8a2c4e6f
Request bodyapplication/json
itemsarray of ItemRef & objectrequiredmin items 1max items 500Attributes of each item
skustring | nullmax length 255barcodestring | nullmax length 255location_codestring | nullRequired when your connection has more than one stock location code.
max length 40quantityintegerrequiredAbsolute level, not an increment.
min 0classificationstringOne ofsellabledamagedquarantinereservedunsellabledefault sellablecounted_atstring (date-time) | null
Responses
200Levels applied.application/json
HeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
acceptedintegerItems applied.
ignoredarray of objectAttributes of each item
indexintegerPosition in
items, from 0.skustring | nullbarcodestring | nullreasonstringunknown_item: not in the catalog.stale:counted_atolder than the level already applied.One ofunknown_itemstale
warningsarray of objectAttributes of each item
location_codestringreasonstringOne oflocation_not_mappedmessagestring
400The request is not valid:
validation_failed(withdetailsper field),invalid_json,invalid_cursor. Nothing was changed. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
401Missing or invalid API key (
unauthorized).application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
403The connection is paused (
connection_paused) or not active yet (connection_not_active). Nothing was read or changed: retry later. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
409The request conflicts with the current state:
order_not_ready,order_not_accepted,order_already_accepted,order_cancelled,order_cancel_requested,order_already_shipped,invalid_state,documents_not_ready,labels_not_ready; or with anIdempotency-Key:idempotency_key_reused,idempotency_key_in_progress(withRetry-After). Read the order or return again before retrying. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.Retry-AfterSeconds to wait before retrying.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
413The body is larger than 5 MB (
payload_too_large). Nothing was read.application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
422Valid JSON that cannot be applied:
unknown_item(an item that is not on the order or not known, withdetailsper line),too_many_items,labels_not_enabled. Nothing was changed. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
429
rate_limited: more calls in a minute than the connection allows (600 by default, all endpoints together; the merchant can set another limit), or too many failed authentications from your IP. Wait the seconds inRetry-After. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.Retry-AfterSeconds to wait before retrying.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
curl -X PUT https://api-commerce.nucleoplatform.com/api/fulfillment/v1/stock \
-H "Authorization: Bearer $NUCLEO_ACCESS_TOKEN" \
-H 'Idempotency-Key: 2f0c9a1e-6b4d-4f3a-9e7c-5d1b8a2c4e6f' \
-H 'Content-Type: application/json' \
-d '{
"items": [
{
"sku": "TEE-BLK-M",
"quantity": 42,
"counted_at": "2026-10-13T06:00:00Z"
},
{
"barcode": "2000000000022",
"location_code": "VR1",
"quantity": 3,
"classification": "damaged"
},
{
"sku": "SOCK-WHT-S",
"quantity": 0
}
]
}'const res = await fetch("https://api-commerce.nucleoplatform.com/api/fulfillment/v1/stock", {
method: "PUT",
headers: {
Authorization: `Bearer ${process.env.NUCLEO_ACCESS_TOKEN}`,
"Idempotency-Key": "2f0c9a1e-6b4d-4f3a-9e7c-5d1b8a2c4e6f",
"Content-Type": "application/json",
},
body: JSON.stringify({
"items": [
{
"sku": "TEE-BLK-M",
"quantity": 42,
"counted_at": "2026-10-13T06:00:00Z"
},
{
"barcode": "2000000000022",
"location_code": "VR1",
"quantity": 3,
"classification": "damaged"
},
{
"sku": "SOCK-WHT-S",
"quantity": 0
}
]
}),
});
const data = await res.json();
console.log(res.status, data);<?php
require 'vendor/autoload.php';
$client = new GuzzleHttp\Client();
$response = $client->request('PUT', 'https://api-commerce.nucleoplatform.com/api/fulfillment/v1/stock', [
'headers' => [
'Authorization' => 'Bearer ' . getenv('NUCLEO_ACCESS_TOKEN'),
'Idempotency-Key' => '2f0c9a1e-6b4d-4f3a-9e7c-5d1b8a2c4e6f',
],
'json' => [
'items' => [
[
'sku' => 'TEE-BLK-M',
'quantity' => 42,
'counted_at' => '2026-10-13T06:00:00Z',
],
[
'barcode' => '2000000000022',
'location_code' => 'VR1',
'quantity' => 3,
'classification' => 'damaged',
],
[
'sku' => 'SOCK-WHT-S',
'quantity' => 0,
],
],
],
'http_errors' => false,
]);
echo $response->getStatusCode(), PHP_EOL;
echo $response->getBody();{
"accepted": 2,
"ignored": [
{
"index": 2,
"sku": "SOCK-WHT-S",
"barcode": null,
"reason": "unknown_item"
}
],
"warnings": []
}{
"error": {
"code": "validation_failed",
"message": "The request is not valid.",
"request_id": "1f7e3c2a-9b8d-4e6f-a5c4-3b2a1d0e9f8c",
"details": {
"lines.0.quantity": [
"The lines.0.quantity field must be at least 0."
],
"reason_code": [
"The reason code field is required."
]
}
}
}{
"error": {
"code": "unauthorized",
"message": "Missing or invalid API key.",
"request_id": "0b6c3e4f-1a2d-4c5b-8e7f-9a0b1c2d3e4f"
}
}{
"error": {
"code": "connection_paused",
"message": "This connection is paused: nothing was changed.",
"request_id": "3c2b1a0f-9e8d-4c7b-a6f5-4e3d2c1b0a9f"
}
}{
"error": {
"code": "order_not_accepted",
"message": "Accept order",
"request_id": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d"
}
}{
"error": {
"code": "validation_failed",
"message": "string",
"request_id": "9b2f4c1e-5d7a-4e8b-9c3d-2a1f0e6b7c8d",
"details": {}
}
}{
"error": {
"code": "unknown_item",
"message": "Some lines do not match an item of this order assigned to your warehouse. Nothing was changed.",
"request_id": "2e1d0c9b-8a7f-4e6d-9c5b-4a3f2e1d0c9b",
"details": {
"lines.1": [
"Not an item of this order assigned to your warehouse."
]
}
}
}{
"error": {
"code": "rate_limited",
"message": "Too many requests: retry after the number of seconds in Retry-After.",
"request_id": "4f3e2d1c-0b9a-4f8e-8d7c-6b5a4f3e2d1c"
}
}Returns
Returns the customer is sending back to your warehouse, the confirmation that you expect them, what actually arrived and in which condition, and parcels nobody announced.
A return is compliant when every expected item arrived in the expected quantity and in sellable
condition; otherwise it is not compliant and the merchant's customer service is alerted.
/returnsList returns
Returns coming to your warehouse: those whose return location is yours or, without a return location, those of orders your warehouse fulfilled. Sorted by last update, oldest first.
expected(default): announced and not received yet.accepted_attells whether you confirmed it.received: received, with the outcome.cancelled: cancelled by the customer or the merchant: do not wait for it.
Query parameters
statusstringWhich returns to list.
One ofexpectedreceivedcancelleddefault expectedExample:expectedupdated_sincestring (date-time)Only items updated at or after this time (ISO 8601).
Example:2026-10-13T06:00:00Zcursorstringnext_cursorof the previous page. A cursor only works with the samestatus.limitintegerItems per page.
min 1max 200default 50Example:50
Responses
200One page of returns.application/json
HeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
dataarray of ReturnrequiredAttributes of each item
idstring (uuid)numberstringstatusstringOne ofexpectedreceivedcancelledoutcomestring | nullOne ofcompliantnot_compliantnullunannouncedbooleanCreated by a warehouse from a parcel nobody announced.
order_numberstring | nullreasonobjectChild attributes
codestring | nulltextstring | null
customer_notestring | nullreturn_trackingobjectChild attributes
carrier_codestring | nulltracking_numberstring | null
created_atstring (date-time)updated_atstring (date-time)accepted_atstring (date-time) | nullreceived_atstring (date-time) | nullcancelled_atstring (date-time) | nulllinesarray of objectAttributes of each item
line_idstring (uuid)order_line_idstring (uuid) | nullskustring | nullbarcodestring | nullitem_keystring | nulltitlestring | nullquantity_expectedintegerquantity_receivedinteger | nullconditionstring | nullmixedwhen you reported the same item in more than one condition.One ofsellabledamageddefectiveusedwrong_itemmixednullreason_codestring | nullnotestring | null
next_cursorstring | nullrequired
400The request is not valid:
validation_failed(withdetailsper field),invalid_json,invalid_cursor. Nothing was changed. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
401Missing or invalid API key (
unauthorized).application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
403The connection is paused (
connection_paused) or not active yet (connection_not_active). Nothing was read or changed: retry later. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
429
rate_limited: more calls in a minute than the connection allows (600 by default, all endpoints together; the merchant can set another limit), or too many failed authentications from your IP. Wait the seconds inRetry-After. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.Retry-AfterSeconds to wait before retrying.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
curl -X GET 'https://api-commerce.nucleoplatform.com/api/fulfillment/v1/returns?status=expected&updated_since=2026-10-13T06%3A00%3A00Z&limit=50' \
-H "Authorization: Bearer $NUCLEO_ACCESS_TOKEN" \
-H 'Accept: application/json'const res = await fetch("https://api-commerce.nucleoplatform.com/api/fulfillment/v1/returns?status=expected&updated_since=2026-10-13T06%3A00%3A00Z&limit=50", {
method: "GET",
headers: {
Authorization: `Bearer ${process.env.NUCLEO_ACCESS_TOKEN}`,
Accept: "application/json",
},
});
const data = await res.json();
console.log(res.status, data);<?php
require 'vendor/autoload.php';
$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api-commerce.nucleoplatform.com/api/fulfillment/v1/returns?status=expected&updated_since=2026-10-13T06%3A00%3A00Z&limit=50', [
'headers' => [
'Authorization' => 'Bearer ' . getenv('NUCLEO_ACCESS_TOKEN'),
'Accept' => 'application/json',
],
'http_errors' => false,
]);
echo $response->getStatusCode(), PHP_EOL;
echo $response->getBody();{
"data": [
{
"id": "9e8d7c6b-5a4f-4e3d-8c2b-1a0f9e8d7c6b",
"number": "R1042-1",
"status": "expected",
"outcome": null,
"unannounced": false,
"order_number": "#1042",
"reason": {
"code": "size",
"text": "Too small"
},
"customer_note": null,
"return_tracking": {
"carrier_code": "EXAMPLE",
"tracking_number": "064152003399"
},
"created_at": "2026-10-18T16:20:03Z",
"updated_at": "2026-10-18T16:20:03Z",
"accepted_at": null,
"received_at": null,
"cancelled_at": null,
"lines": [
{
"line_id": "7a6b5c4d-3e2f-4a1b-9c0d-8e7f6a5b4c3d",
"order_line_id": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"sku": "HOOD-GRY-L",
"barcode": "2000000000022",
"item_key": "2000000000022",
"title": "Fleece Hoodie · Grey · L",
"quantity_expected": 1,
"quantity_received": null,
"condition": null,
"reason_code": "size",
"note": null
}
]
}
],
"next_cursor": null
}{
"error": {
"code": "validation_failed",
"message": "The request is not valid.",
"request_id": "1f7e3c2a-9b8d-4e6f-a5c4-3b2a1d0e9f8c",
"details": {
"lines.0.quantity": [
"The lines.0.quantity field must be at least 0."
],
"reason_code": [
"The reason code field is required."
]
}
}
}{
"error": {
"code": "unauthorized",
"message": "Missing or invalid API key.",
"request_id": "0b6c3e4f-1a2d-4c5b-8e7f-9a0b1c2d3e4f"
}
}{
"error": {
"code": "connection_paused",
"message": "This connection is paused: nothing was changed.",
"request_id": "3c2b1a0f-9e8d-4c7b-a6f5-4e3d2c1b0a9f"
}
}{
"error": {
"code": "rate_limited",
"message": "Too many requests: retry after the number of seconds in Retry-After.",
"request_id": "4f3e2d1c-0b9a-4f8e-8d7c-6b5a4f3e2d1c"
}
}/returns/{id}Get a return
One return of your warehouse, by return number or ID.
Path parameters
idstringrequiredReturn number (as in
number) or return ID.Example:R1042-1
Responses
200The return.application/json
HeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
idstring (uuid)numberstringstatusstringOne ofexpectedreceivedcancelledoutcomestring | nullOne ofcompliantnot_compliantnullunannouncedbooleanCreated by a warehouse from a parcel nobody announced.
order_numberstring | nullreasonobjectChild attributes
codestring | nulltextstring | null
customer_notestring | nullreturn_trackingobjectChild attributes
carrier_codestring | nulltracking_numberstring | null
created_atstring (date-time)updated_atstring (date-time)accepted_atstring (date-time) | nullreceived_atstring (date-time) | nullcancelled_atstring (date-time) | nulllinesarray of objectAttributes of each item
line_idstring (uuid)order_line_idstring (uuid) | nullskustring | nullbarcodestring | nullitem_keystring | nulltitlestring | nullquantity_expectedintegerquantity_receivedinteger | nullconditionstring | nullmixedwhen you reported the same item in more than one condition.One ofsellabledamageddefectiveusedwrong_itemmixednullreason_codestring | nullnotestring | null
401Missing or invalid API key (
unauthorized).application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
403The connection is paused (
connection_paused) or not active yet (connection_not_active). Nothing was read or changed: retry later. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
404
order_not_foundorreturn_not_found— it does not exist or it belongs to another warehouse;not_foundfor an unknown path. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
429
rate_limited: more calls in a minute than the connection allows (600 by default, all endpoints together; the merchant can set another limit), or too many failed authentications from your IP. Wait the seconds inRetry-After. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.Retry-AfterSeconds to wait before retrying.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
curl -X GET https://api-commerce.nucleoplatform.com/api/fulfillment/v1/returns/R1042-1 \
-H "Authorization: Bearer $NUCLEO_ACCESS_TOKEN" \
-H 'Accept: application/json'const res = await fetch("https://api-commerce.nucleoplatform.com/api/fulfillment/v1/returns/R1042-1", {
method: "GET",
headers: {
Authorization: `Bearer ${process.env.NUCLEO_ACCESS_TOKEN}`,
Accept: "application/json",
},
});
const data = await res.json();
console.log(res.status, data);<?php
require 'vendor/autoload.php';
$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api-commerce.nucleoplatform.com/api/fulfillment/v1/returns/R1042-1', [
'headers' => [
'Authorization' => 'Bearer ' . getenv('NUCLEO_ACCESS_TOKEN'),
'Accept' => 'application/json',
],
'http_errors' => false,
]);
echo $response->getStatusCode(), PHP_EOL;
echo $response->getBody();{
"id": "9e8d7c6b-5a4f-4e3d-8c2b-1a0f9e8d7c6b",
"number": "R1042-1",
"status": "expected",
"outcome": null,
"unannounced": false,
"order_number": "#1042",
"reason": {
"code": "size",
"text": "Too small"
},
"customer_note": null,
"return_tracking": {
"carrier_code": "EXAMPLE",
"tracking_number": "064152003399"
},
"created_at": "2026-10-18T16:20:03Z",
"updated_at": "2026-10-18T16:20:03Z",
"accepted_at": null,
"received_at": null,
"cancelled_at": null,
"lines": [
{
"line_id": "7a6b5c4d-3e2f-4a1b-9c0d-8e7f6a5b4c3d",
"order_line_id": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"sku": "HOOD-GRY-L",
"barcode": "2000000000022",
"item_key": "2000000000022",
"title": "Fleece Hoodie · Grey · L",
"quantity_expected": 1,
"quantity_received": null,
"condition": null,
"reason_code": "size",
"note": null
}
]
}{
"error": {
"code": "unauthorized",
"message": "Missing or invalid API key.",
"request_id": "0b6c3e4f-1a2d-4c5b-8e7f-9a0b1c2d3e4f"
}
}{
"error": {
"code": "connection_paused",
"message": "This connection is paused: nothing was changed.",
"request_id": "3c2b1a0f-9e8d-4c7b-a6f5-4e3d2c1b0a9f"
}
}{
"error": {
"code": "order_not_found",
"message": "Order 1042 not found.",
"request_id": "6d5c4b3a-2f1e-4d0c-9b8a-7f6e5d4c3b2a"
}
}{
"error": {
"code": "rate_limited",
"message": "Too many requests: retry after the number of seconds in Retry-After.",
"request_id": "4f3e2d1c-0b9a-4f8e-8d7c-6b5a4f3e2d1c"
}
}/returns/{id}/acceptConfirm an expected return
Confirms that your warehouse expects the return; the merchant sees it as awaited at warehouse.
Repeating it changes nothing. Only for expected returns (409 invalid_state otherwise).
Path parameters
idstringrequiredReturn number (as in
number) or return ID.Example:R1042-1
Headers
Idempotency-KeystringAny unique string you generate (1–255 printable ASCII characters, no spaces), for example a UUID. For 48 hours, the same key with the same request — same method, same path written the same way (
/orders/1042and/orders/%231042differ) and same body — returns the stored answer without doing the work again (headerIdempotent-Replayed: true; the replayed body keeps the originalrequest_id, theX-Request-Idheader is the new call's). The same key with a different request answers409 idempotency_key_reused; while the first request is still running,409 idempotency_key_in_progress. A key left in progress for more than 2 minutes (an interrupted call) is free again. Keys are per connection. Server errors (5xx) and429are not stored: retry them with the same key.max length 255Example:2f0c9a1e-6b4d-4f3a-9e7c-5d1b8a2c4e6f
Responses
200The return after the change.application/json
HeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.Idempotent-Replayedtruewhen the answer is the stored one of an earlier request with the sameIdempotency-Key.
idstring (uuid)numberstringstatusstringOne ofexpectedreceivedcancelledoutcomestring | nullOne ofcompliantnot_compliantnullunannouncedbooleanCreated by a warehouse from a parcel nobody announced.
order_numberstring | nullreasonobjectChild attributes
codestring | nulltextstring | null
customer_notestring | nullreturn_trackingobjectChild attributes
carrier_codestring | nulltracking_numberstring | null
created_atstring (date-time)updated_atstring (date-time)accepted_atstring (date-time) | nullreceived_atstring (date-time) | nullcancelled_atstring (date-time) | nulllinesarray of objectAttributes of each item
line_idstring (uuid)order_line_idstring (uuid) | nullskustring | nullbarcodestring | nullitem_keystring | nulltitlestring | nullquantity_expectedintegerquantity_receivedinteger | nullconditionstring | nullmixedwhen you reported the same item in more than one condition.One ofsellabledamageddefectiveusedwrong_itemmixednullreason_codestring | nullnotestring | null
401Missing or invalid API key (
unauthorized).application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
403The connection is paused (
connection_paused) or not active yet (connection_not_active). Nothing was read or changed: retry later. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
404
order_not_foundorreturn_not_found— it does not exist or it belongs to another warehouse;not_foundfor an unknown path. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
409The request conflicts with the current state:
order_not_ready,order_not_accepted,order_already_accepted,order_cancelled,order_cancel_requested,order_already_shipped,invalid_state,documents_not_ready,labels_not_ready; or with anIdempotency-Key:idempotency_key_reused,idempotency_key_in_progress(withRetry-After). Read the order or return again before retrying. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.Retry-AfterSeconds to wait before retrying.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
429
rate_limited: more calls in a minute than the connection allows (600 by default, all endpoints together; the merchant can set another limit), or too many failed authentications from your IP. Wait the seconds inRetry-After. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.Retry-AfterSeconds to wait before retrying.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
curl -X POST https://api-commerce.nucleoplatform.com/api/fulfillment/v1/returns/R1042-1/accept \
-H "Authorization: Bearer $NUCLEO_ACCESS_TOKEN" \
-H 'Idempotency-Key: 2f0c9a1e-6b4d-4f3a-9e7c-5d1b8a2c4e6f' \
-H 'Accept: application/json'const res = await fetch("https://api-commerce.nucleoplatform.com/api/fulfillment/v1/returns/R1042-1/accept", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.NUCLEO_ACCESS_TOKEN}`,
"Idempotency-Key": "2f0c9a1e-6b4d-4f3a-9e7c-5d1b8a2c4e6f",
Accept: "application/json",
},
});
const data = await res.json();
console.log(res.status, data);<?php
require 'vendor/autoload.php';
$client = new GuzzleHttp\Client();
$response = $client->request('POST', 'https://api-commerce.nucleoplatform.com/api/fulfillment/v1/returns/R1042-1/accept', [
'headers' => [
'Authorization' => 'Bearer ' . getenv('NUCLEO_ACCESS_TOKEN'),
'Idempotency-Key' => '2f0c9a1e-6b4d-4f3a-9e7c-5d1b8a2c4e6f',
'Accept' => 'application/json',
],
'http_errors' => false,
]);
echo $response->getStatusCode(), PHP_EOL;
echo $response->getBody();{
"id": "9e8d7c6b-5a4f-4e3d-8c2b-1a0f9e8d7c6b",
"number": "R1042-1",
"status": "received",
"outcome": "not_compliant",
"unannounced": false,
"order_number": "#1042",
"reason": {
"code": "size",
"text": "Too small"
},
"customer_note": null,
"return_tracking": {
"carrier_code": "EXAMPLE",
"tracking_number": "064152003399"
},
"created_at": "2026-10-18T16:20:03Z",
"updated_at": "2026-10-20T10:05:12Z",
"accepted_at": "2026-10-18T16:35:00Z",
"received_at": "2026-10-20T10:05:00Z",
"cancelled_at": null,
"lines": [
{
"line_id": "7a6b5c4d-3e2f-4a1b-9c0d-8e7f6a5b4c3d",
"order_line_id": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"sku": "HOOD-GRY-L",
"barcode": "2000000000022",
"item_key": "2000000000022",
"title": "Fleece Hoodie · Grey · L",
"quantity_expected": 1,
"quantity_received": 1,
"condition": "damaged",
"reason_code": "size",
"note": "Stain on the left sleeve."
}
]
}{
"error": {
"code": "unauthorized",
"message": "Missing or invalid API key.",
"request_id": "0b6c3e4f-1a2d-4c5b-8e7f-9a0b1c2d3e4f"
}
}{
"error": {
"code": "connection_paused",
"message": "This connection is paused: nothing was changed.",
"request_id": "3c2b1a0f-9e8d-4c7b-a6f5-4e3d2c1b0a9f"
}
}{
"error": {
"code": "order_not_found",
"message": "Order 1042 not found.",
"request_id": "6d5c4b3a-2f1e-4d0c-9b8a-7f6e5d4c3b2a"
}
}{
"error": {
"code": "order_not_accepted",
"message": "Accept order",
"request_id": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d"
}
}{
"error": {
"code": "rate_limited",
"message": "Too many requests: retry after the number of seconds in Retry-After.",
"request_id": "4f3e2d1c-0b9a-4f8e-8d7c-6b5a4f3e2d1c"
}
}/returns/{id}/receiptReport what arrived
What arrived, item by item, with its condition. On the first receipt, expected items you do not list count as received 0; items that were not expected are added and make the return not compliant. Several lines of the same item in different conditions are allowed. A later receipt updates only the items it lists (the others keep what you reported before): to correct, list every item again.
The return becomes received with an outcome: compliant when quantities match and everything
is sellable, not_compliant otherwise (the merchant's customer service is alerted). Sending a new
receipt re-evaluates the outcome. A receipt for a cancelled or closed return is recorded, its status
does not change and the merchant is alerted.
Path parameters
idstringrequiredReturn number (as in
number) or return ID.Example:R1042-1
Headers
Idempotency-KeystringAny unique string you generate (1–255 printable ASCII characters, no spaces), for example a UUID. For 48 hours, the same key with the same request — same method, same path written the same way (
/orders/1042and/orders/%231042differ) and same body — returns the stored answer without doing the work again (headerIdempotent-Replayed: true; the replayed body keeps the originalrequest_id, theX-Request-Idheader is the new call's). The same key with a different request answers409 idempotency_key_reused; while the first request is still running,409 idempotency_key_in_progress. A key left in progress for more than 2 minutes (an interrupted call) is free again. Keys are per connection. Server errors (5xx) and429are not stored: retry them with the same key.max length 255Example:2f0c9a1e-6b4d-4f3a-9e7c-5d1b8a2c4e6f
Request bodyapplication/json
received_atstring (date-time) | nulllinesarray of ItemRef & objectrequiredmin items 1max items 500Attributes of each item
skustring | nullmax length 255barcodestring | nullmax length 255quantityintegerrequiredmin 0conditionstringrequiredOne ofsellabledamageddefectiveusedwrong_itemnotestring | nullmax length 500
Responses
200The return after the change.application/json
HeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.Idempotent-Replayedtruewhen the answer is the stored one of an earlier request with the sameIdempotency-Key.
idstring (uuid)numberstringstatusstringOne ofexpectedreceivedcancelledoutcomestring | nullOne ofcompliantnot_compliantnullunannouncedbooleanCreated by a warehouse from a parcel nobody announced.
order_numberstring | nullreasonobjectChild attributes
codestring | nulltextstring | null
customer_notestring | nullreturn_trackingobjectChild attributes
carrier_codestring | nulltracking_numberstring | null
created_atstring (date-time)updated_atstring (date-time)accepted_atstring (date-time) | nullreceived_atstring (date-time) | nullcancelled_atstring (date-time) | nulllinesarray of objectAttributes of each item
line_idstring (uuid)order_line_idstring (uuid) | nullskustring | nullbarcodestring | nullitem_keystring | nulltitlestring | nullquantity_expectedintegerquantity_receivedinteger | nullconditionstring | nullmixedwhen you reported the same item in more than one condition.One ofsellabledamageddefectiveusedwrong_itemmixednullreason_codestring | nullnotestring | null
400The request is not valid:
validation_failed(withdetailsper field),invalid_json,invalid_cursor. Nothing was changed. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
401Missing or invalid API key (
unauthorized).application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
403The connection is paused (
connection_paused) or not active yet (connection_not_active). Nothing was read or changed: retry later. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
404
order_not_foundorreturn_not_found— it does not exist or it belongs to another warehouse;not_foundfor an unknown path. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
409The request conflicts with the current state:
order_not_ready,order_not_accepted,order_already_accepted,order_cancelled,order_cancel_requested,order_already_shipped,invalid_state,documents_not_ready,labels_not_ready; or with anIdempotency-Key:idempotency_key_reused,idempotency_key_in_progress(withRetry-After). Read the order or return again before retrying. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.Retry-AfterSeconds to wait before retrying.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
422Valid JSON that cannot be applied:
unknown_item(an item that is not on the order or not known, withdetailsper line),too_many_items,labels_not_enabled. Nothing was changed. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
429
rate_limited: more calls in a minute than the connection allows (600 by default, all endpoints together; the merchant can set another limit), or too many failed authentications from your IP. Wait the seconds inRetry-After. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.Retry-AfterSeconds to wait before retrying.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
curl -X POST https://api-commerce.nucleoplatform.com/api/fulfillment/v1/returns/R1042-1/receipt \
-H "Authorization: Bearer $NUCLEO_ACCESS_TOKEN" \
-H 'Idempotency-Key: 2f0c9a1e-6b4d-4f3a-9e7c-5d1b8a2c4e6f' \
-H 'Content-Type: application/json' \
-d '{
"received_at": "2026-10-20T10:05:00Z",
"lines": [
{
"sku": "TEE-BLK-M",
"quantity": 1,
"condition": "sellable"
},
{
"sku": "HOOD-GRY-L",
"quantity": 1,
"condition": "damaged",
"note": "Stain on the left sleeve."
}
]
}'const res = await fetch("https://api-commerce.nucleoplatform.com/api/fulfillment/v1/returns/R1042-1/receipt", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.NUCLEO_ACCESS_TOKEN}`,
"Idempotency-Key": "2f0c9a1e-6b4d-4f3a-9e7c-5d1b8a2c4e6f",
"Content-Type": "application/json",
},
body: JSON.stringify({
"received_at": "2026-10-20T10:05:00Z",
"lines": [
{
"sku": "TEE-BLK-M",
"quantity": 1,
"condition": "sellable"
},
{
"sku": "HOOD-GRY-L",
"quantity": 1,
"condition": "damaged",
"note": "Stain on the left sleeve."
}
]
}),
});
const data = await res.json();
console.log(res.status, data);<?php
require 'vendor/autoload.php';
$client = new GuzzleHttp\Client();
$response = $client->request('POST', 'https://api-commerce.nucleoplatform.com/api/fulfillment/v1/returns/R1042-1/receipt', [
'headers' => [
'Authorization' => 'Bearer ' . getenv('NUCLEO_ACCESS_TOKEN'),
'Idempotency-Key' => '2f0c9a1e-6b4d-4f3a-9e7c-5d1b8a2c4e6f',
],
'json' => [
'received_at' => '2026-10-20T10:05:00Z',
'lines' => [
[
'sku' => 'TEE-BLK-M',
'quantity' => 1,
'condition' => 'sellable',
],
[
'sku' => 'HOOD-GRY-L',
'quantity' => 1,
'condition' => 'damaged',
'note' => 'Stain on the left sleeve.',
],
],
],
'http_errors' => false,
]);
echo $response->getStatusCode(), PHP_EOL;
echo $response->getBody();{
"id": "9e8d7c6b-5a4f-4e3d-8c2b-1a0f9e8d7c6b",
"number": "R1042-1",
"status": "received",
"outcome": "not_compliant",
"unannounced": false,
"order_number": "#1042",
"reason": {
"code": "size",
"text": "Too small"
},
"customer_note": null,
"return_tracking": {
"carrier_code": "EXAMPLE",
"tracking_number": "064152003399"
},
"created_at": "2026-10-18T16:20:03Z",
"updated_at": "2026-10-20T10:05:12Z",
"accepted_at": "2026-10-18T16:35:00Z",
"received_at": "2026-10-20T10:05:00Z",
"cancelled_at": null,
"lines": [
{
"line_id": "7a6b5c4d-3e2f-4a1b-9c0d-8e7f6a5b4c3d",
"order_line_id": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"sku": "HOOD-GRY-L",
"barcode": "2000000000022",
"item_key": "2000000000022",
"title": "Fleece Hoodie · Grey · L",
"quantity_expected": 1,
"quantity_received": 1,
"condition": "damaged",
"reason_code": "size",
"note": "Stain on the left sleeve."
}
]
}{
"error": {
"code": "validation_failed",
"message": "The request is not valid.",
"request_id": "1f7e3c2a-9b8d-4e6f-a5c4-3b2a1d0e9f8c",
"details": {
"lines.0.quantity": [
"The lines.0.quantity field must be at least 0."
],
"reason_code": [
"The reason code field is required."
]
}
}
}{
"error": {
"code": "unauthorized",
"message": "Missing or invalid API key.",
"request_id": "0b6c3e4f-1a2d-4c5b-8e7f-9a0b1c2d3e4f"
}
}{
"error": {
"code": "connection_paused",
"message": "This connection is paused: nothing was changed.",
"request_id": "3c2b1a0f-9e8d-4c7b-a6f5-4e3d2c1b0a9f"
}
}{
"error": {
"code": "order_not_found",
"message": "Order 1042 not found.",
"request_id": "6d5c4b3a-2f1e-4d0c-9b8a-7f6e5d4c3b2a"
}
}{
"error": {
"code": "order_not_accepted",
"message": "Accept order",
"request_id": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d"
}
}{
"error": {
"code": "unknown_item",
"message": "Some lines do not match an item of this order assigned to your warehouse. Nothing was changed.",
"request_id": "2e1d0c9b-8a7f-4e6d-9c5b-4a3f2e1d0c9b",
"details": {
"lines.1": [
"Not an item of this order assigned to your warehouse."
]
}
}
}{
"error": {
"code": "rate_limited",
"message": "Too many requests: retry after the number of seconds in Retry-After.",
"request_id": "4f3e2d1c-0b9a-4f8e-8d7c-6b5a4f3e2d1c"
}
}/returns/unannouncedReport an unannounced return
A parcel arrived for an order but nobody announced a return. Nucleo creates the return on the order, records what arrived (as in Report what arrived) and alerts the merchant.
Only for orders your warehouse fulfilled or expects returns of: any other order answers 404 (and
the merchant is alerted that goods are in the wrong warehouse). Sending the same content again —
same order, reference and lines — returns the return already created (200) instead of a new one.
reference (for example the number written on the parcel) becomes the return number when it is
free.
Headers
Idempotency-KeystringAny unique string you generate (1–255 printable ASCII characters, no spaces), for example a UUID. For 48 hours, the same key with the same request — same method, same path written the same way (
/orders/1042and/orders/%231042differ) and same body — returns the stored answer without doing the work again (headerIdempotent-Replayed: true; the replayed body keeps the originalrequest_id, theX-Request-Idheader is the new call's). The same key with a different request answers409 idempotency_key_reused; while the first request is still running,409 idempotency_key_in_progress. A key left in progress for more than 2 minutes (an interrupted call) is free again. Keys are per connection. Server errors (5xx) and429are not stored: retry them with the same key.max length 255Example:2f0c9a1e-6b4d-4f3a-9e7c-5d1b8a2c4e6f
Request bodyapplication/json
order_numberstringrequiredThe order the goods belong to (the
#can be omitted).referencestring | nullYour reference for the parcel.
max length 120received_atstring (date-time) | nulllinesarray of ItemRef & objectrequiredmin items 1max items 500Attributes of each item
skustring | nullmax length 255barcodestring | nullmax length 255quantityintegerrequiredmin 0conditionstringrequiredOne ofsellabledamageddefectiveusedwrong_itemnotestring | nullmax length 500
Responses
200The return after the change.application/json
HeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.Idempotent-Replayedtruewhen the answer is the stored one of an earlier request with the sameIdempotency-Key.
idstring (uuid)numberstringstatusstringOne ofexpectedreceivedcancelledoutcomestring | nullOne ofcompliantnot_compliantnullunannouncedbooleanCreated by a warehouse from a parcel nobody announced.
order_numberstring | nullreasonobjectChild attributes
codestring | nulltextstring | null
customer_notestring | nullreturn_trackingobjectChild attributes
carrier_codestring | nulltracking_numberstring | null
created_atstring (date-time)updated_atstring (date-time)accepted_atstring (date-time) | nullreceived_atstring (date-time) | nullcancelled_atstring (date-time) | nulllinesarray of objectAttributes of each item
line_idstring (uuid)order_line_idstring (uuid) | nullskustring | nullbarcodestring | nullitem_keystring | nulltitlestring | nullquantity_expectedintegerquantity_receivedinteger | nullconditionstring | nullmixedwhen you reported the same item in more than one condition.One ofsellabledamageddefectiveusedwrong_itemmixednullreason_codestring | nullnotestring | null
201Return created and received.application/json
HeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
idstring (uuid)numberstringstatusstringOne ofexpectedreceivedcancelledoutcomestring | nullOne ofcompliantnot_compliantnullunannouncedbooleanCreated by a warehouse from a parcel nobody announced.
order_numberstring | nullreasonobjectChild attributes
codestring | nulltextstring | null
customer_notestring | nullreturn_trackingobjectChild attributes
carrier_codestring | nulltracking_numberstring | null
created_atstring (date-time)updated_atstring (date-time)accepted_atstring (date-time) | nullreceived_atstring (date-time) | nullcancelled_atstring (date-time) | nulllinesarray of objectAttributes of each item
line_idstring (uuid)order_line_idstring (uuid) | nullskustring | nullbarcodestring | nullitem_keystring | nulltitlestring | nullquantity_expectedintegerquantity_receivedinteger | nullconditionstring | nullmixedwhen you reported the same item in more than one condition.One ofsellabledamageddefectiveusedwrong_itemmixednullreason_codestring | nullnotestring | null
400The request is not valid:
validation_failed(withdetailsper field),invalid_json,invalid_cursor. Nothing was changed. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
401Missing or invalid API key (
unauthorized).application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
403The connection is paused (
connection_paused) or not active yet (connection_not_active). Nothing was read or changed: retry later. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
404
order_not_foundorreturn_not_found— it does not exist or it belongs to another warehouse;not_foundfor an unknown path. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
409The request conflicts with the current state:
order_not_ready,order_not_accepted,order_already_accepted,order_cancelled,order_cancel_requested,order_already_shipped,invalid_state,documents_not_ready,labels_not_ready; or with anIdempotency-Key:idempotency_key_reused,idempotency_key_in_progress(withRetry-After). Read the order or return again before retrying. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.Retry-AfterSeconds to wait before retrying.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
422Valid JSON that cannot be applied:
unknown_item(an item that is not on the order or not known, withdetailsper line),too_many_items,labels_not_enabled. Nothing was changed. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
429
rate_limited: more calls in a minute than the connection allows (600 by default, all endpoints together; the merchant can set another limit), or too many failed authentications from your IP. Wait the seconds inRetry-After. application/jsonHeadersX-Request-IdIdentifier of the call. Quote it when you contact support; it is alsoerror.request_id.Retry-AfterSeconds to wait before retrying.
errorobjectrequiredChild attributes
codestringrequiredStable, machine-readable code. Branch on it, not on
message.One ofvalidation_failedinvalid_jsoninvalid_cursorunauthorizedconnection_pausedconnection_not_activenot_foundmethod_not_allowedorder_not_foundreturn_not_foundorder_not_readyorder_not_acceptedorder_already_acceptedorder_cancelledorder_cancel_requestedorder_already_shippedinvalid_statedocuments_not_readylabels_not_readyidempotency_key_reusedidempotency_key_in_progresspayload_too_largeunknown_itemtoo_many_itemslabels_not_enabledrate_limitedinternal_errormessagestringrequiredExplanation in English for people. It can change; never parse it.
request_idstring (uuid)requiredSame as the
X-Request-Idheader.detailsobjectValidation and item errors per field:
{"lines.0.quantity": ["…"]}.
curl -X POST https://api-commerce.nucleoplatform.com/api/fulfillment/v1/returns/unannounced \
-H "Authorization: Bearer $NUCLEO_ACCESS_TOKEN" \
-H 'Idempotency-Key: 2f0c9a1e-6b4d-4f3a-9e7c-5d1b8a2c4e6f' \
-H 'Content-Type: application/json' \
-d '{
"order_number": "1042",
"reference": "PKG-55120",
"lines": [
{
"sku": "TEE-BLK-M",
"quantity": 1,
"condition": "sellable"
}
]
}'const res = await fetch("https://api-commerce.nucleoplatform.com/api/fulfillment/v1/returns/unannounced", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.NUCLEO_ACCESS_TOKEN}`,
"Idempotency-Key": "2f0c9a1e-6b4d-4f3a-9e7c-5d1b8a2c4e6f",
"Content-Type": "application/json",
},
body: JSON.stringify({
"order_number": "1042",
"reference": "PKG-55120",
"lines": [
{
"sku": "TEE-BLK-M",
"quantity": 1,
"condition": "sellable"
}
]
}),
});
const data = await res.json();
console.log(res.status, data);<?php
require 'vendor/autoload.php';
$client = new GuzzleHttp\Client();
$response = $client->request('POST', 'https://api-commerce.nucleoplatform.com/api/fulfillment/v1/returns/unannounced', [
'headers' => [
'Authorization' => 'Bearer ' . getenv('NUCLEO_ACCESS_TOKEN'),
'Idempotency-Key' => '2f0c9a1e-6b4d-4f3a-9e7c-5d1b8a2c4e6f',
],
'json' => [
'order_number' => '1042',
'reference' => 'PKG-55120',
'lines' => [
[
'sku' => 'TEE-BLK-M',
'quantity' => 1,
'condition' => 'sellable',
],
],
],
'http_errors' => false,
]);
echo $response->getStatusCode(), PHP_EOL;
echo $response->getBody();{
"id": "9e8d7c6b-5a4f-4e3d-8c2b-1a0f9e8d7c6b",
"number": "R1042-1",
"status": "received",
"outcome": "not_compliant",
"unannounced": false,
"order_number": "#1042",
"reason": {
"code": "size",
"text": "Too small"
},
"customer_note": null,
"return_tracking": {
"carrier_code": "EXAMPLE",
"tracking_number": "064152003399"
},
"created_at": "2026-10-18T16:20:03Z",
"updated_at": "2026-10-20T10:05:12Z",
"accepted_at": "2026-10-18T16:35:00Z",
"received_at": "2026-10-20T10:05:00Z",
"cancelled_at": null,
"lines": [
{
"line_id": "7a6b5c4d-3e2f-4a1b-9c0d-8e7f6a5b4c3d",
"order_line_id": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"sku": "HOOD-GRY-L",
"barcode": "2000000000022",
"item_key": "2000000000022",
"title": "Fleece Hoodie · Grey · L",
"quantity_expected": 1,
"quantity_received": 1,
"condition": "damaged",
"reason_code": "size",
"note": "Stain on the left sleeve."
}
]
}{
"id": "9b2f4c1e-5d7a-4e8b-9c3d-2a1f0e6b7c8d",
"number": "string",
"status": "expected",
"outcome": "compliant",
"unannounced": true,
"order_number": "string",
"reason": {
"code": "string",
"text": "string"
},
"customer_note": "string",
"return_tracking": {
"carrier_code": "string",
"tracking_number": "string"
},
"created_at": "2026-10-01T09:30:00Z",
"updated_at": "2026-10-01T09:30:00Z",
"accepted_at": "2026-10-01T09:30:00Z",
"received_at": "2026-10-01T09:30:00Z",
"cancelled_at": "2026-10-01T09:30:00Z",
"lines": [
{
"line_id": "9b2f4c1e-5d7a-4e8b-9c3d-2a1f0e6b7c8d",
"order_line_id": "9b2f4c1e-5d7a-4e8b-9c3d-2a1f0e6b7c8d",
"sku": "string",
"barcode": "string",
"item_key": "string",
"title": "string",
"quantity_expected": 1,
"quantity_received": 1,
"condition": "sellable",
"reason_code": "string",
"note": "string"
}
]
}{
"error": {
"code": "validation_failed",
"message": "The request is not valid.",
"request_id": "1f7e3c2a-9b8d-4e6f-a5c4-3b2a1d0e9f8c",
"details": {
"lines.0.quantity": [
"The lines.0.quantity field must be at least 0."
],
"reason_code": [
"The reason code field is required."
]
}
}
}{
"error": {
"code": "unauthorized",
"message": "Missing or invalid API key.",
"request_id": "0b6c3e4f-1a2d-4c5b-8e7f-9a0b1c2d3e4f"
}
}{
"error": {
"code": "connection_paused",
"message": "This connection is paused: nothing was changed.",
"request_id": "3c2b1a0f-9e8d-4c7b-a6f5-4e3d2c1b0a9f"
}
}{
"error": {
"code": "order_not_found",
"message": "Order 1042 not found.",
"request_id": "6d5c4b3a-2f1e-4d0c-9b8a-7f6e5d4c3b2a"
}
}{
"error": {
"code": "order_not_accepted",
"message": "Accept order",
"request_id": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d"
}
}{
"error": {
"code": "unknown_item",
"message": "Some lines do not match an item of this order assigned to your warehouse. Nothing was changed.",
"request_id": "2e1d0c9b-8a7f-4e6d-9c5b-4a3f2e1d0c9b",
"details": {
"lines.1": [
"Not an item of this order assigned to your warehouse."
]
}
}
}{
"error": {
"code": "rate_limited",
"message": "Too many requests: retry after the number of seconds in Retry-After.",
"request_id": "4f3e2d1c-0b9a-4f8e-8d7c-6b5a4f3e2d1c"
}
}return.expectedA return is coming to your warehouse
Sent when a customer return addressed to your warehouse is approved. Read it with Get a return and confirm it with Confirm an expected return.
Request Nucleo sendsapplication/json
idstring (uuid)requiredUnique per event and the same on every retry. Skip an
idyou already handled.typestringrequiredOne oforder.readyorder.cancelledreturn.expectedcreated_atstring (date-time)requireddataobjectrequiredorder.ready:order_id,order_number.order.cancelled:order_id,order_number,status(cancelledorcancel_requested).return.expected:return_id,return_number,order_number.
Expected response
200Answer with any
2xxwithin 10 seconds; the body is ignored. Any other answer, a redirect or a timeout is retried with exponential backoff (after about 30 seconds, then 1, 2, 4, 8, 16 and 32 minutes): 8 attempts in about an hour, then Nucleo gives up and alerts the merchant. Every attempt carries the sameid(also inX-Nucleo-Webhook-Id) and its number inX-Nucleo-Attempt. While the connection is paused or still a draft no webhook is sent, and the events of that time are not sent later: catch up by polling.
{
"id": "0a1b2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d",
"type": "return.expected",
"created_at": "2026-10-18T16:20:03Z",
"data": {
"return_id": "9e8d7c6b-5a4f-4e3d-8c2b-1a0f9e8d7c6b",
"return_number": "R1042-1",
"order_number": "#1042"
}
}HTTP 200 — Answer with any `2xx` within 10 seconds; the body is ignored. Any other answer, a redirect or a
timeout is retried with exponential backoff (after about 30 seconds, then 1, 2, 4, 8, 16 and 32
minutes): 8 attempts in about an hour, then Nucleo gives up and alerts the merchant. Every attempt
carries the same `id` (also in `X-Nucleo-Webhook-Id`) and its number in `X-Nucleo-Attempt`.
While the connection is paused or still a draft no webhook is sent, and the events of that time are
not sent later: catch up by polling.