Contents
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.
Base URL, authentication and conventions of this API are on the Fulfillment API page.
- get
/ordersList orders - get
/orders/{number}Get an order - post
/orders/{number}/acceptAccept an order - post
/orders/{number}/rejectReject an order - post
/orders/{number}/pickedReport the picking - post
/orders/{number}/shipmentsReport a shipment - post
/orders/{number}/cancelCancel an order - hook
order.readyAn order is ready for your warehouse - hook
order.cancelledAn order was cancelled
/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.