Contents
WMS FFW API
FFW / Smart Shop compatible XML web services that a warehouse management system calls to fulfil Nucleo Commerce orders and returns.
The WMS FFW facade lets a warehouse or 3PL management system (WMS) fulfil the orders of a Nucleo Commerce merchant
with the FFW / Smart Shop web services: same paths, same query parameters, same XML envelopes (doc_ordini,
doc_giacenze, doc_resi, doc_gestione_etichette_corrieri, doc_recupero_documenti). A WMS that already speaks FFW
only changes the base URL and the credentials.
The warehouse is always the caller. Nucleo never calls the WMS: the WMS polls for orders and returns and pushes stock, shipments and return outcomes.
Authentication. HTTP Basic on every call, with the username and password of one warehouse connection. The credentials alone identify the merchant and the warehouse; there is no store identifier in the path.
Integration flow
- Download orders –
GET /api/admin/ws/ws_orders?last_upd=…every 1–5 minutes, with state codes 17 (to fulfil), 2 (cancelled) and 31 (shipped). There is no explicit acknowledgement: an order returned with state 17 is taken over by the warehouse, as in FFW. - Follow changes – the same call returns again an order the merchant changed (address, notes, cancelled lines) with state 17 and fresh data, and an order cancelled after you downloaded it with state 2: stop picking it.
- Stock –
POST /api/aggiorna-giacenze-impegniwith absolute levels, at most 500 items per call. - Shipment –
POST /api/admin/spedizioni/notify-spedizionewith carrier, tracking and parcels (Nucleo extension, not part of the original FFW services). Nucleo creates the fulfilment on the sales channel and the order comes back inws_orderswith state 31. When the merchant has Nucleo generate courier labels instead, useget-etichette-corriere→ (del-etichette-corriere) →ws-close-bordero; these are switched off by default. - Returns –
GET /api/admin/resi/list?last_upd=…for expected returns, thenPOST /api/admin/resi/notify-resowith the items actually received. - Documents –
GET /api/admin/documenti/get-order-docsfor invoices and receipts of an order, as base64 PDF.
Conventions
- XML out:
<?xml version="1.0" encoding="iso-8859-1"?>, HTTP headerContent-Type: text/xml; charset=iso-8859-1, pretty-printed. Characters outside ISO-8859-1 are written as numeric entities (ŁforŁ); free text is inCDATA. - XML in: every POST accepts the XML either as the form field
xml(application/x-www-form-urlencodedor multipart) or as the raw request body, in ISO-8859-1 or UTF-8. Documents containing<!DOCTYPE>or entity declarations, or another encoding, are rejected with the endpoint'sKOenvelope. - Paths are exactly FFW's, case-sensitive. The leading double slash written in the FFW spec
(
//api/admin/spedizioni/ws-close-bordero) is accepted on every path. - Dates are Italian local time (Europe/Rome), in FFW's per-service formats:
ws_ordersdata_dal/data_aldd/mm/yyyy HH:MM:SS;ws_orderslast_updandord_DataUltimaModificaYYYYMMDDHHMMSS;resi/listdata_dal/data_alyyyy-mm-dd;resi/listlast_upddd/mm/yyyy hh:mm:ss;ord_data,reso_datadd/mm/yyyy;ord_datetime,reso_datetime,resi_data_ultima_modifica,data_spedizioneyyyy-mm-dd HH:MM:SS. URL-encode spaces and slashes in query strings. - Amounts: dot decimal, two digits (
147.54). Line prices are net of VAT,importo_totale_rigais gross. - Item code:
barcodeandIDArtCodare the variant barcode (EAN). - Keys:
ord_IDandreso_IDare numeric ids assigned by Nucleo, progressive per merchant (a merchant migrating from FFW continues after the last FFW id).ord_num_docis the channel order name (#1042). - Codes (
documenti_stati_ID,resi_stati_ID,resi_causali_ID,nazioni_ID) are the FFW defaults listed per operation; the merchant can remap them per connection. - Errors keep FFW's envelopes, different per service, and validation errors are answered with HTTP 200 and a
KOenvelope, as in FFW. Always readack/ACK/result, not only the HTTP status.
Errors common to every service
| HTTP | Message in the endpoint envelope | When |
|---|---|---|
| 401 | Unauthorized | missing or wrong credentials (no WWW-Authenticate header is sent) |
| 403 | Forbidden | caller IP not in the connection allowlist (only when the merchant set one) |
| 429 | Too many requests | rate limit exceeded |
| 200 | service paused / service not active | connection paused by the merchant, or still a draft: KO, nothing read or written, retry later |
| 500 | Internal error (ref <uuid>) | unexpected error; quote the ref to support |
Limits and monitoring
- 600 calls per minute per connection (all services together; the merchant can change it). No
Retry-AfterorX-RateLimit-*headers are sent: on429back off for at least 60 seconds. - 30 failed authentications within 5 minutes from one IP block that IP for the rest of the window, valid credentials included.
- Every call is logged in full (request and response) before Nucleo answers, so support can find any call by time, service or
ord_ID. - If the WMS stays silent for more than 30 minutes while orders are waiting, Nucleo flags the connection as Error and alerts the merchant; the next successful call clears it.
Credentials
The merchant creates a warehouse connection of type FFW in Commerce › Orders › Channels and logistics. Nucleo shows the
endpoint, username and password once; the merchant shares them with you over a separate channel. Rotate credentials
on the same page invalidates the old ones immediately. A new connection starts as a draft and answers service not active
until the merchant activates it.
Authentication
basicAuthHTTP basicUsername and password of the warehouse connection, issued once by the merchant in Commerce › Orders › Channels and logistics. Send them preemptively on every call.
- Base URL
- https://{host}Production. Use the endpoint shown when the credentials were issued.
- Who calls it
- Warehouses
- Endpoints
- 10
- OpenAPI 3.1 specification
- wms-ffw.yaml
{host} — Commerce API host. If the merchant sets a dedicated host on the connection, the connection answers only on that host; paths do not change. (examples use api-commerce.nucleoplatform.com; full URL https://api-commerce.nucleoplatform.com)Orders
Download orders (implicit acknowledgement) and order documents.
/api/admin/ws/ws_ordersDownload orders
Orders allocated to this warehouse, in FFW details=medium format. At least one of last_upd, data_dal, data_al
is required.
States (documenti_stati_ID, FFW defaults): 17 confirmed, to fulfil (Nucleo states ready, exported, label
created); 2 cancelled; 31 shipped (shipped, delivered). Without a filter all three are returned. documenti_tipo_ID
13 (web order) is the only type served here; any other type returns an empty <ordini/>.
Implicit acknowledgement: an order returned with state 17 is taken over by the warehouse (moves to Exported). Until then Nucleo keeps subtracting it from your stock before publishing availability.
Incremental reading with last_upd (> filter on the last change): use as next last_upd either the last
ord_DataUltimaModifica received or the time of your previous call. Nucleo stamps every change a few seconds in the future
and returns only changes already in the past, so no change ever falls before a last_upd you already used. last_upd
cannot be older than one month.
Date range (data_dal/data_al, on the order date): at most one month; without data_dal it is one month before
data_al; without data_al it is now. Both filters can be combined.
- At most 500 orders per call (merchant-configurable), ordered by last change then
ord_ID; the limit never splits a second, so a page can be slightly larger. If you receive a full page, call again at once withlast_upd= the lastord_DataUltimaModifica. - An order the merchant changes after you read it (address, notes, cancelled lines) comes back with state 17 and the new
data: update it in the WMS by
ord_ID. - Cancelled before you read it: never returned. Cancelled after: returned with state 2; Nucleo considers the cancellation done once you have read it with state 2.
- Only orders allocated to this warehouse's locations, and for split orders only your lines.
- Re-reading the same window returns the same orders without further effects.
- The tag list of
details=mediumfollows the FFW naming;detailsis accepted and ignored (alwaysmedium).
Errors: validation errors answer HTTP 200 with <result><ack>KO</ack><error_message>.
Rate limit: shared 600 calls/minute per connection.
Query parameters
last_updstringOrders changed strictly after this instant,
YYYYMMDDHHMMSS, Italian time, not older than one month.pattern ^\d{14}$Example:20261005100000data_dalstringOrder date from,
dd/mm/yyyy HH:MM:SS, Italian time.Example:01/10/2026 00:00:00data_alstringOrder date to,
dd/mm/yyyy HH:MM:SS, Italian time. At most one month afterdata_dal.Example:05/10/2026 23:59:59documenti_stati_IDstringA single state code (
17,2or31). For several, usedocumenti_stati_ID[].One of17231Example:17documenti_stati_ID[]array of stringSeveral state codes, repeated (
documenti_stati_ID[]=17&documenti_stati_ID[]=2).One of17231documenti_tipo_IDstringDocument type.
13= web order (also the default). Other types return an empty list.documenti_tipo_ID[]is accepted too.Example:13detailsstringAccepted for compatibility; the answer is always
medium.One ofmediumExample:medium
Responses
200Orders (
<ordini>), possibly empty (<ordini/>), or aKOenvelope for validation errors and for a paused or draft connection. application/xmlOne of the following shapes:
Orders
ordinearray of OrderAttributes of each item
ord_IDintegerNucleo order id; key for every later call.
ord_num_docstringChannel order name.
Example:#1042ord_datastringOrder date dd/mm/yyyy.
ord_datetimestringOrder date yyyy-mm-dd HH:MM:SS.
ord_DataUltimaModificastringLast change YYYYMMDDHHMMSS; reusable as last_upd.
documenti_tipo_IDstringExample:13documenti_stati_IDstringOne of17231stato_descrstringState label (CDATA).
order_b2bintegerOne of01IDMagazzinostringWarehouse code of the location the order is allocated to.
valutastringISO 4217 currency.
Example:EURcambiostringExchange rate to EUR.
clienteCustomerChild attributes
nomestringcognomestringemailstringtelefonostring
spedizioneBillingAddress & objectChild attributes
nomestringcognomestringaziendastringindirizzostringindirizzo2stringcapstringcittastringprovinciastringnazione_isostringISO 3166-1 alpha-2.
nazioni_IDstringFFW country code; empty when the merchant has not mapped that country.
telefonostring
fatturazioneBillingAddressChild attributes
nomestringcognomestringaziendastringindirizzostringindirizzo2stringcapstringcittastringprovinciastringnazione_isostringISO 3166-1 alpha-2.
nazioni_IDstringFFW country code; empty when the merchant has not mapped that country.
metodo_spedizionestringShipping method title (CDATA).
corrierestringCarrier chosen by the merchant's carrier rules.
servizio_corrierestringnotestringNotes for the warehouse (CDATA).
articoliobjectChild attributes
articoloarray of OrderLineAttributes of each item
barcodestringEAN.
skustringdescrizionestringqtaintegerQuantity allocated to this warehouse and still active.
art_prezzo_listinostringList price net of VAT.
art_prezzo_internetstringSame as the list price.
art_prezzo_finale_scontatostringFinal unit price net of VAT.
iva_aliquotastringVAT rate.
documenti_dettaglio_totale_ivastringVAT amount of the line.
importo_totale_rigastringGross line total.
ord_totale_mercestringord_scontistringord_spese_spedizionestringord_totale_ivastringord_totalestringord_totale_merce_eurostringord_sconti_eurostringord_spese_spedizione_eurostringord_totale_iva_eurostringord_totale_eurostring
ResultErrorMessage
ack"KO"error_messagestringMessage in CDATA.
500Unexpected error, with a reference to quote to support.application/xml
ack"KO"error_messagestringMessage in CDATA.
4XXAuthentication, IP allowlist or rate limit (401, 403, 429), in the
<result>/<error_message>envelope.application/xmlack"KO"error_messagestringMessage in CDATA.
curl -X GET 'https://api-commerce.nucleoplatform.com/api/admin/ws/ws_orders?last_upd=20261005100000&data_dal=01%2F10%2F2026%2000%3A00%3A00&data_al=05%2F10%2F2026%2023%3A59%3A59&documenti_stati_ID=17&documenti_stati_ID%5B%5D=17&documenti_stati_ID%5B%5D=2&documenti_tipo_ID=13&details=medium' \
-u "$NUCLEO_USERNAME:$NUCLEO_PASSWORD" \
-H 'Accept: application/xml'const res = await fetch("https://api-commerce.nucleoplatform.com/api/admin/ws/ws_orders?last_upd=20261005100000&data_dal=01%2F10%2F2026%2000%3A00%3A00&data_al=05%2F10%2F2026%2023%3A59%3A59&documenti_stati_ID=17&documenti_stati_ID%5B%5D=17&documenti_stati_ID%5B%5D=2&documenti_tipo_ID=13&details=medium", {
method: "GET",
headers: {
Authorization: `Basic ${btoa(`${process.env.NUCLEO_USERNAME}:${process.env.NUCLEO_PASSWORD}`)}`,
Accept: "application/xml",
},
});
const data = await res.text();
console.log(res.status, data);<?php
require 'vendor/autoload.php';
$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api-commerce.nucleoplatform.com/api/admin/ws/ws_orders?last_upd=20261005100000&data_dal=01%2F10%2F2026%2000%3A00%3A00&data_al=05%2F10%2F2026%2023%3A59%3A59&documenti_stati_ID=17&documenti_stati_ID%5B%5D=17&documenti_stati_ID%5B%5D=2&documenti_tipo_ID=13&details=medium', [
'auth' => [getenv('NUCLEO_USERNAME'), getenv('NUCLEO_PASSWORD')],
'headers' => [
'Accept' => 'application/xml',
],
'http_errors' => false,
]);
echo $response->getStatusCode(), PHP_EOL;
echo $response->getBody();<?xml version="1.0" encoding="iso-8859-1"?>
<ordini>
<ordine>
<ord_ID>51042</ord_ID>
<ord_num_doc>#1042</ord_num_doc>
<ord_data>05/10/2026</ord_data>
<ord_datetime>2026-10-05 10:12:30</ord_datetime>
<ord_DataUltimaModifica>20261005101534</ord_DataUltimaModifica>
<documenti_tipo_ID>13</documenti_tipo_ID>
<documenti_stati_ID>17</documenti_stati_ID>
<stato_descr><![CDATA[Confermato]]></stato_descr>
<order_b2b>0</order_b2b>
<IDMagazzino>10</IDMagazzino>
<valuta>EUR</valuta>
<cambio>1.00000000</cambio>
<cliente>
<nome><![CDATA[Giulia]]></nome>
<cognome><![CDATA[Bianchi]]></cognome>
<email>giulia.bianchi@example.com</email>
<telefono>+39 333 0000000</telefono>
</cliente>
<spedizione>
<nome><![CDATA[Giulia]]></nome>
<cognome><![CDATA[Bianchi]]></cognome>
<azienda><![CDATA[Acme Apparel Srl]]></azienda>
<indirizzo><![CDATA[Via Roma 1]]></indirizzo>
<indirizzo2><![CDATA[Scala B]]></indirizzo2>
<cap>20121</cap>
<citta><![CDATA[Milano]]></citta>
<provincia>MI</provincia>
<nazione_iso>IT</nazione_iso>
<nazioni_ID>1</nazioni_ID>
<telefono>+39 333 0000000</telefono>
</spedizione>
<fatturazione>
<nome><![CDATA[Giulia]]></nome>
<cognome><![CDATA[Bianchi]]></cognome>
<azienda><![CDATA[]]></azienda>
<indirizzo><![CDATA[Via Roma 1]]></indirizzo>
<indirizzo2><![CDATA[]]></indirizzo2>
<cap>20121</cap>
<citta><![CDATA[Milano]]></citta>
<provincia>MI</provincia>
<nazione_iso>IT</nazione_iso>
<nazioni_ID>1</nazioni_ID>
</fatturazione>
<metodo_spedizione><![CDATA[Standard]]></metodo_spedizione>
<corriere>BRT</corriere>
<servizio_corriere></servizio_corriere>
<note><![CDATA[Leave with the concierge]]></note>
<articoli>
<articolo>
<barcode>8000000000017</barcode>
<sku>TEE-BLK-M</sku>
<descrizione><![CDATA[T-shirt Black M]]></descrizione>
<qta>1</qta>
<art_prezzo_listino>24.59</art_prezzo_listino>
<art_prezzo_internet>24.59</art_prezzo_internet>
<art_prezzo_finale_scontato>24.59</art_prezzo_finale_scontato>
<iva_aliquota>22.00</iva_aliquota>
<documenti_dettaglio_totale_iva>5.41</documenti_dettaglio_totale_iva>
<importo_totale_riga>30.00</importo_totale_riga>
</articolo>
</articoli>
<ord_totale_merce>30.00</ord_totale_merce>
<ord_sconti>0.00</ord_sconti>
<ord_spese_spedizione>5.00</ord_spese_spedizione>
<ord_totale_iva>6.31</ord_totale_iva>
<ord_totale>35.00</ord_totale>
<ord_totale_merce_euro>30.00</ord_totale_merce_euro>
<ord_sconti_euro>0.00</ord_sconti_euro>
<ord_spese_spedizione_euro>5.00</ord_spese_spedizione_euro>
<ord_totale_iva_euro>6.31</ord_totale_iva_euro>
<ord_totale_euro>35.00</ord_totale_euro>
</ordine>
</ordini><?xml version="1.0" encoding="iso-8859-1"?>
<ordini/><?xml version="1.0" encoding="iso-8859-1"?>
<result>
<ack>KO</ack>
<error_message><![CDATA[E' obbligatorio passare almeno uno dei parametri data_dal / data_al o last_upd.]]></error_message>
</result><?xml version="1.0" encoding="iso-8859-1"?>
<result>
<ack>KO</ack>
<error_message><![CDATA[L'intervallo data_dal / data_al non può essere maggiore di un mese.]]></error_message>
</result><?xml version="1.0" encoding="iso-8859-1"?>
<result>
<ack>KO</ack>
<error_message><![CDATA[last upd deve essere una data successiva al 2026-09-05 10:00:00.]]></error_message>
</result><?xml version="1.0" encoding="iso-8859-1"?>
<result>
<ack>KO</ack>
<error_message><![CDATA[service paused]]></error_message>
</result><?xml version="1.0" encoding="iso-8859-1"?>
<result>
<ack>KO</ack>
<error_message><![CDATA[Internal error (ref 3f2b8c1e-5a7d-4e2f-9b61-0c8d4a2e7f10)]]></error_message>
</result><?xml version="1.0" encoding="iso-8859-1"?>
<result>
<ack>KO</ack>
<error_message><![CDATA[Unauthorized]]></error_message>
</result><?xml version="1.0" encoding="iso-8859-1"?>
<result>
<ack>KO</ack>
<error_message><![CDATA[Forbidden]]></error_message>
</result><?xml version="1.0" encoding="iso-8859-1"?>
<result>
<ack>KO</ack>
<error_message><![CDATA[Too many requests]]></error_message>
</result>/api/admin/documenti/get-order-docsDownload order documents
Fiscal documents of an order (invoice, receipt, credit note) as base64 PDF. Alias: GET /api/documenti/admin/get-order-docs.
typeFFW codes in<type>(defaults):3invoice,5credit note,31receipt,32receipt variation.- No documents, unknown order or invalid id:
<ACK>ERROR</ACK>with an empty<documents/>, HTTP 200. - Every error of this service (including authentication) uses the same envelope without a message: rely on the HTTP status.
Rate limit: shared 600 calls/minute per connection.
Query parameters
documenti_testa_IDstringrequiredThe order's
ord_ID.pattern ^\d+$Example:51042typestringsell(sale documents),return(return documents), empty = all.One ofsellreturnExample:sell
Responses
200Documents, or
ERRORwith no documents.application/xmlACKstringOne ofOKERRORdocumentsobjectChild attributes
documentarray of objectAttributes of each item
idstringtypestringFFW document type code.
numberstringrefstringcontentstringPDF in CDATA.
500Unexpected error. Same envelope as "no documents"; check the HTTP status.application/xml
ACKstringOne ofOKERRORdocumentsobjectChild attributes
documentarray of objectAttributes of each item
idstringtypestringFFW document type code.
numberstringrefstringcontentstringPDF in CDATA.
4XXAuthentication, IP allowlist or rate limit (401, 403, 429). Same envelope as "no documents"; check the HTTP status.application/xml
ACKstringOne ofOKERRORdocumentsobjectChild attributes
documentarray of objectAttributes of each item
idstringtypestringFFW document type code.
numberstringrefstringcontentstringPDF in CDATA.
curl -X GET 'https://api-commerce.nucleoplatform.com/api/admin/documenti/get-order-docs?documenti_testa_ID=51042&type=sell' \
-u "$NUCLEO_USERNAME:$NUCLEO_PASSWORD" \
-H 'Accept: application/xml'const res = await fetch("https://api-commerce.nucleoplatform.com/api/admin/documenti/get-order-docs?documenti_testa_ID=51042&type=sell", {
method: "GET",
headers: {
Authorization: `Basic ${btoa(`${process.env.NUCLEO_USERNAME}:${process.env.NUCLEO_PASSWORD}`)}`,
Accept: "application/xml",
},
});
const data = await res.text();
console.log(res.status, data);<?php
require 'vendor/autoload.php';
$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api-commerce.nucleoplatform.com/api/admin/documenti/get-order-docs?documenti_testa_ID=51042&type=sell', [
'auth' => [getenv('NUCLEO_USERNAME'), getenv('NUCLEO_PASSWORD')],
'headers' => [
'Accept' => 'application/xml',
],
'http_errors' => false,
]);
echo $response->getStatusCode(), PHP_EOL;
echo $response->getBody();<?xml version="1.0" encoding="iso-8859-1"?>
<response>
<ACK>OK</ACK>
<documents>
<document>
<id>5</id>
<type>31</type>
<number>1</number>
<ref>R0002</ref>
<content><![CDATA[JVBERi0xLjQKJcfsj6IK...]]></content>
</document>
</documents>
</response><?xml version="1.0" encoding="iso-8859-1"?>
<response>
<ACK>ERROR</ACK>
<documents/>
</response><?xml version="1.0" encoding="iso-8859-1"?>
<response>
<ACK>ERROR</ACK>
<documents/>
</response><?xml version="1.0" encoding="iso-8859-1"?>
<response>
<ACK>ERROR</ACK>
<documents/>
</response>/api/documenti/admin/get-order-docsDownload order documents (alias)
Alias of GET /api/admin/documenti/get-order-docs, same parameters, behaviour and responses.
Rate limit: shared 600 calls/minute per connection.
Query parameters
documenti_testa_IDstringrequiredThe order's
ord_ID.pattern ^\d+$Example:51042typestringsell(sale documents),return(return documents), empty = all.One ofsellreturnExample:sell
Responses
200Documents, or
ERRORwith no documents.application/xmlACKstringOne ofOKERRORdocumentsobjectChild attributes
documentarray of objectAttributes of each item
idstringtypestringFFW document type code.
numberstringrefstringcontentstringPDF in CDATA.
500Unexpected error. Same envelope as "no documents"; check the HTTP status.application/xml
ACKstringOne ofOKERRORdocumentsobjectChild attributes
documentarray of objectAttributes of each item
idstringtypestringFFW document type code.
numberstringrefstringcontentstringPDF in CDATA.
4XXAuthentication, IP allowlist or rate limit (401, 403, 429). Same envelope as "no documents"; check the HTTP status.application/xml
ACKstringOne ofOKERRORdocumentsobjectChild attributes
documentarray of objectAttributes of each item
idstringtypestringFFW document type code.
numberstringrefstringcontentstringPDF in CDATA.
curl -X GET 'https://api-commerce.nucleoplatform.com/api/documenti/admin/get-order-docs?documenti_testa_ID=51042&type=sell' \
-u "$NUCLEO_USERNAME:$NUCLEO_PASSWORD" \
-H 'Accept: application/xml'const res = await fetch("https://api-commerce.nucleoplatform.com/api/documenti/admin/get-order-docs?documenti_testa_ID=51042&type=sell", {
method: "GET",
headers: {
Authorization: `Basic ${btoa(`${process.env.NUCLEO_USERNAME}:${process.env.NUCLEO_PASSWORD}`)}`,
Accept: "application/xml",
},
});
const data = await res.text();
console.log(res.status, data);<?php
require 'vendor/autoload.php';
$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api-commerce.nucleoplatform.com/api/documenti/admin/get-order-docs?documenti_testa_ID=51042&type=sell', [
'auth' => [getenv('NUCLEO_USERNAME'), getenv('NUCLEO_PASSWORD')],
'headers' => [
'Accept' => 'application/xml',
],
'http_errors' => false,
]);
echo $response->getStatusCode(), PHP_EOL;
echo $response->getBody();<?xml version="1.0" encoding="iso-8859-1"?>
<response>
<ACK>OK</ACK>
<documents>
<document>
<id>5</id>
<type>31</type>
<number>1</number>
<ref>R0002</ref>
<content><![CDATA[JVBERi0xLjQKJcfsj6IK...]]></content>
</document>
</documents>
</response><?xml version="1.0" encoding="iso-8859-1"?>
<response>
<ACK>ERROR</ACK>
<documents/>
</response><?xml version="1.0" encoding="iso-8859-1"?>
<response>
<ACK>ERROR</ACK>
<documents/>
</response><?xml version="1.0" encoding="iso-8859-1"?>
<response>
<ACK>ERROR</ACK>
<documents/>
</response>Stock
Push stock levels.
/api/aggiorna-giacenze-impegniPush stock levels
Absolute stock per item and warehouse code, already net of the warehouse's commitments (orders already downloaded).
- Root
<giacenze>, one<articolo>per item and warehouse:IDArtCod(EAN) andgiacenza(integer) required,IDMagazzinooptional (defaults to the code configured on the connection,1unless the merchant changed it). - The same EAN on several warehouse codes mapped to the same Nucleo location is summed.
- Nucleo subtracts the paid orders you have not downloaded yet, then publishes availability to the sales channels.
- At most 500
<articolo>per call (merchant-configurable): above the limit the call isKOand nothing is processed. Send batches of 500. - A malformed item makes the whole call
KO(nothing processed). - An unknown EAN is skipped and the merchant is alerted; the rest is processed and the answer is
OK. A warehouse code not mapped to a Nucleo location is stored but not published, and the merchant is alerted. - Items not sent are not zeroed: send
giacenza0 to zero an item. - Optional query
?full=1marks a full snapshot: Nucleo republishes every item received, even unchanged ones. OKmeans the levels are stored; publication to the channels follows asynchronously.
Official input is the form field xml; the raw body is accepted too.
Idempotent: repeating the call re-applies the same values.
Rate limit: shared 600 calls/minute per connection.
Query parameters
fullstringAny non-empty value marks a full snapshot and forces republication of all items received.
Example:1
Request bodyapplication/x-www-form-urlencoded, multipart/form-data, application/xml
xmlstringrequiredThe
<giacenze>document.
Responses
200
OK, orKOwith the reason (nothing processed). AlsoKOwhen the connection is paused or a draft.application/xmlackstringOne ofOKKOerrorstring
500Unexpected error, with a reference to quote to support.application/xml
ackstringOne ofOKKOerrorstring
4XXAuthentication, IP allowlist or rate limit (401, 403, 429), in the
<giacenze>envelope.application/xmlackstringOne ofOKKOerrorstring
curl -X POST 'https://api-commerce.nucleoplatform.com/api/aggiorna-giacenze-impegni?full=1' \
-u "$NUCLEO_USERNAME:$NUCLEO_PASSWORD" \
-H 'Content-Type: application/x-www-form-urlencoded' \
-H 'Accept: application/xml' \
--data-urlencode 'xml=<giacenze><articolo><IDArtCod>8000000000017</IDArtCod><giacenza>10</giacenza><IDMagazzino>10</IDMagazzino></articolo></giacenze>'const res = await fetch("https://api-commerce.nucleoplatform.com/api/aggiorna-giacenze-impegni?full=1", {
method: "POST",
headers: {
Authorization: `Basic ${btoa(`${process.env.NUCLEO_USERNAME}:${process.env.NUCLEO_PASSWORD}`)}`,
"Content-Type": "application/x-www-form-urlencoded",
Accept: "application/xml",
},
body: new URLSearchParams({
xml: "<giacenze><articolo><IDArtCod>8000000000017</IDArtCod><giacenza>10</giacenza><IDMagazzino>10</IDMagazzino></articolo></giacenze>",
}),
});
const data = await res.text();
console.log(res.status, data);<?php
require 'vendor/autoload.php';
$client = new GuzzleHttp\Client();
$response = $client->request('POST', 'https://api-commerce.nucleoplatform.com/api/aggiorna-giacenze-impegni?full=1', [
'auth' => [getenv('NUCLEO_USERNAME'), getenv('NUCLEO_PASSWORD')],
'headers' => [
'Accept' => 'application/xml',
],
'form_params' => [
'xml' => '<giacenze><articolo><IDArtCod>8000000000017</IDArtCod><giacenza>10</giacenza><IDMagazzino>10</IDMagazzino></articolo></giacenze>',
],
'http_errors' => false,
]);
echo $response->getStatusCode(), PHP_EOL;
echo $response->getBody();<?xml version="1.0" encoding="iso-8859-1"?>
<giacenze>
<ack>OK</ack>
</giacenze><?xml version="1.0" encoding="iso-8859-1"?>
<giacenze>
<ack>KO</ack>
<error>Numero massimo di articoli per chiamata superato (612 > 500).</error>
</giacenze><?xml version="1.0" encoding="iso-8859-1"?>
<giacenze>
<ack>KO</ack>
<error>xml parameter malformed</error>
</giacenze><?xml version="1.0" encoding="iso-8859-1"?>
<giacenze>
<ack>KO</ack>
<error>Articolo 3 non valido: IDArtCod e giacenza intera obbligatori.</error>
</giacenze><?xml version="1.0" encoding="iso-8859-1"?>
<giacenze>
<ack>KO</ack>
<error>Internal error (ref 3f2b8c1e-5a7d-4e2f-9b61-0c8d4a2e7f10)</error>
</giacenze><?xml version="1.0" encoding="iso-8859-1"?>
<giacenze>
<ack>KO</ack>
<error>Unauthorized</error>
</giacenze><?xml version="1.0" encoding="iso-8859-1"?>
<giacenze>
<ack>KO</ack>
<error>Too many requests</error>
</giacenze>Shipping
Shipment notification, and the optional Nucleo-generated courier labels and bordereau.
/api/admin/spedizioni/notify-spedizioneReport shipment with carrier and tracking
Nucleo extension (not part of the original FFW services, beta): tells Nucleo that orders left the warehouse, with
carrier, tracking and parcels, so Nucleo can create the fulfilment on the sales channel and the customer receives the
tracking. One or more <spedizione>.
ord_IDrequired; the order must be allocated to this warehouse and already downloaded (state 17), otherwiseInvalid order status: <status>.data_spedizioneyyyy-mm-dd HH:MM:SSItalian time; missing or unreadable = now.corriere,servizio: default to the order's carrier and service.tracking_urlempty = Nucleo builds the link from the carrier when it can.colli/collo: onetrackingper parcel, weight in grams.articoli/articolo: shipped items; when missing, everything allocated to this warehouse is shipped. Items not declared stay open for the merchant's customer service.- The order moves to Shipped and comes back in
ws_orderswith state 31. If it was being cancelled, the shipment is recorded and the merchant is alerted. - All or nothing: an unknown order rejects the whole call.
JSON alternative: with Content-Type: application/json (or a body starting with {), the call takes the fields of
the T-Data Orders/Shipped contract (OmsOrderNumber = order name or ord_ID, EventDateTime, CourierCode,
CourierWaybill, TrackingUrl, ShipmentTotalWeightGr, ShipmentTotalVolumeCm3) and answers in T-Data JSON. Authentication
and rate-limit errors keep the XML envelope.
Idempotent: the same notification repeated with the same first tracking creates no second shipment and no second email.
Rate limit: shared 600 calls/minute per connection.
Request bodyapplication/xml, application/x-www-form-urlencoded, application/json
spedizionearray of objectAttributes of each item
ord_IDintegerrequireddata_spedizionestringyyyy-mm-dd HH:MM:SS Italian time.
corrierestringserviziostringtracking_urlstringcolliobjectChild attributes
colloarray of objectAttributes of each item
trackingstringpeso_grinteger
articoliobjectChild attributes
articoloarray of objectAttributes of each item
barcodestringqtainteger
Responses
200
OKorKO(XML), or T-Data JSON success for a JSON request.application/xmlackstringOne ofOKKOmessagestring
400JSON request only, invalid body or unknown order.application/json
ErrorCode"Exception"Messagestring
500Unexpected error, with a reference to quote to support.application/xml
ackstringOne ofOKKOmessagestring
4XXAuthentication, IP allowlist or rate limit (401, 403, 429), in the
<result>/<message>envelope.application/xmlackstringOne ofOKKOmessagestring
curl -X POST https://api-commerce.nucleoplatform.com/api/admin/spedizioni/notify-spedizione \
-u "$NUCLEO_USERNAME:$NUCLEO_PASSWORD" \
-H 'Content-Type: application/xml' \
-H 'Accept: application/xml' \
--data-binary @- <<'EOF'
<spedizioni>
<spedizione>
<ord_ID>51042</ord_ID>
<data_spedizione>2026-10-05 16:30:00</data_spedizione>
<corriere>BRT</corriere>
<servizio>STANDARD</servizio>
<tracking_url></tracking_url>
<colli>
<collo><tracking>BRT0000000000001</tracking><peso_gr>1200</peso_gr></collo>
<collo><tracking>BRT0000000000002</tracking><peso_gr>800</peso_gr></collo>
</colli>
<articoli>
<articolo><barcode>8000000000017</barcode><qta>1</qta></articolo>
</articoli>
</spedizione>
</spedizioni>
EOFconst body = `<spedizioni>
<spedizione>
<ord_ID>51042</ord_ID>
<data_spedizione>2026-10-05 16:30:00</data_spedizione>
<corriere>BRT</corriere>
<servizio>STANDARD</servizio>
<tracking_url></tracking_url>
<colli>
<collo><tracking>BRT0000000000001</tracking><peso_gr>1200</peso_gr></collo>
<collo><tracking>BRT0000000000002</tracking><peso_gr>800</peso_gr></collo>
</colli>
<articoli>
<articolo><barcode>8000000000017</barcode><qta>1</qta></articolo>
</articoli>
</spedizione>
</spedizioni>`;
const res = await fetch("https://api-commerce.nucleoplatform.com/api/admin/spedizioni/notify-spedizione", {
method: "POST",
headers: {
Authorization: `Basic ${btoa(`${process.env.NUCLEO_USERNAME}:${process.env.NUCLEO_PASSWORD}`)}`,
"Content-Type": "application/xml",
Accept: "application/xml",
},
body,
});
const data = await res.text();
console.log(res.status, data);<?php
require 'vendor/autoload.php';
$client = new GuzzleHttp\Client();
$body = <<<'XML'
<spedizioni>
<spedizione>
<ord_ID>51042</ord_ID>
<data_spedizione>2026-10-05 16:30:00</data_spedizione>
<corriere>BRT</corriere>
<servizio>STANDARD</servizio>
<tracking_url></tracking_url>
<colli>
<collo><tracking>BRT0000000000001</tracking><peso_gr>1200</peso_gr></collo>
<collo><tracking>BRT0000000000002</tracking><peso_gr>800</peso_gr></collo>
</colli>
<articoli>
<articolo><barcode>8000000000017</barcode><qta>1</qta></articolo>
</articoli>
</spedizione>
</spedizioni>
XML;
$response = $client->request('POST', 'https://api-commerce.nucleoplatform.com/api/admin/spedizioni/notify-spedizione', [
'auth' => [getenv('NUCLEO_USERNAME'), getenv('NUCLEO_PASSWORD')],
'headers' => [
'Content-Type' => 'application/xml',
'Accept' => 'application/xml',
],
'body' => $body,
'http_errors' => false,
]);
echo $response->getStatusCode(), PHP_EOL;
echo $response->getBody();<?xml version="1.0" encoding="iso-8859-1"?>
<result>
<ack>OK</ack>
<message></message>
</result><?xml version="1.0" encoding="iso-8859-1"?>
<result>
<ack>KO</ack>
<message>Order not found: 59999</message>
</result><?xml version="1.0" encoding="iso-8859-1"?>
<result>
<ack>KO</ack>
<message>XML is wrong or malformed</message>
</result>{
"ErrorCode": "Exception",
"Message": "Order not found: 59999"
}{
"ErrorCode": "Exception",
"Message": "Invalid JSON body"
}<?xml version="1.0" encoding="iso-8859-1"?>
<result>
<ack>KO</ack>
<message>Internal error (ref 3f2b8c1e-5a7d-4e2f-9b61-0c8d4a2e7f10)</message>
</result><?xml version="1.0" encoding="iso-8859-1"?>
<result>
<ack>KO</ack>
<message>Unauthorized</message>
</result><?xml version="1.0" encoding="iso-8859-1"?>
<result>
<ack>KO</ack>
<message>Too many requests</message>
</result>/api/admin/spedizioni/get-etichette-corriereGet courier labels generated by Nucleo
Optional, off by default. Only when the merchant has Nucleo generate courier labels; otherwise HTTP 404
<etichette><result>courier labels are managed by the warehouse</result></etichette>.
For each <order> (id = ord_ID, colli = number of parcels, default 1) Nucleo creates the shipment with the
order's carrier and returns one PDF label per parcel, base64 in CDATA. The order must have been downloaded (state 17);
it moves to Label created. Per-order problems are reported in that order's <error> (Order not found,
Invalid order status: <status>, or the carrier's message) while <result> stays OK.
Official input is the form field xml; the raw body is accepted too.
Idempotent: while a shipment with labels is active for the order, the same labels are returned and no new shipment
is created. Use del-etichette-corriere to start over.
Rate limit: shared 600 calls/minute per connection.
Request bodyapplication/x-www-form-urlencoded, application/xml
xmlstringrequiredThe
<spedizioni>document.
Responses
200Labels per order, or
xml parameter malformed.application/xmlOne of the following shapes:
Labels
result"OK"orderarray of objectAttributes of each item
idstringerrorstringEmpty on success.
shipperstringCarrier display name.
typestringOne ofPDFlabelsobjectChild attributes
labelarray of string
LabelsError
resultstring
404Courier labels are managed by the warehouse for this connection (default).application/xml
resultstring
500Unexpected error, with a reference to quote to support.application/xml
resultstring
4XXAuthentication, IP allowlist or rate limit (401, 403, 429), in the
<etichette>envelope.application/xmlresultstring
curl -X POST https://api-commerce.nucleoplatform.com/api/admin/spedizioni/get-etichette-corriere \
-u "$NUCLEO_USERNAME:$NUCLEO_PASSWORD" \
-H 'Content-Type: application/x-www-form-urlencoded' \
-H 'Accept: application/xml' \
--data-urlencode 'xml=<spedizioni><order><id>51042</id><colli>2</colli></order></spedizioni>'const res = await fetch("https://api-commerce.nucleoplatform.com/api/admin/spedizioni/get-etichette-corriere", {
method: "POST",
headers: {
Authorization: `Basic ${btoa(`${process.env.NUCLEO_USERNAME}:${process.env.NUCLEO_PASSWORD}`)}`,
"Content-Type": "application/x-www-form-urlencoded",
Accept: "application/xml",
},
body: new URLSearchParams({
xml: "<spedizioni><order><id>51042</id><colli>2</colli></order></spedizioni>",
}),
});
const data = await res.text();
console.log(res.status, data);<?php
require 'vendor/autoload.php';
$client = new GuzzleHttp\Client();
$response = $client->request('POST', 'https://api-commerce.nucleoplatform.com/api/admin/spedizioni/get-etichette-corriere', [
'auth' => [getenv('NUCLEO_USERNAME'), getenv('NUCLEO_PASSWORD')],
'headers' => [
'Accept' => 'application/xml',
],
'form_params' => [
'xml' => '<spedizioni><order><id>51042</id><colli>2</colli></order></spedizioni>',
],
'http_errors' => false,
]);
echo $response->getStatusCode(), PHP_EOL;
echo $response->getBody();<?xml version="1.0" encoding="iso-8859-1"?>
<etichette>
<result>OK</result>
<order>
<id>51042</id>
<error></error>
<shipper>BRT</shipper>
<type>PDF</type>
<labels>
<label><![CDATA[JVBERi0xLjQKJcfsj6IK...]]></label>
<label><![CDATA[JVBERi0xLjQKJcfsj6IK...]]></label>
</labels>
</order>
<order>
<id>59999</id>
<error>Order not found</error>
<shipper></shipper>
<type></type>
<labels></labels>
</order>
</etichette><?xml version="1.0" encoding="iso-8859-1"?>
<etichette>
<result>xml parameter malformed</result>
</etichette><?xml version="1.0" encoding="iso-8859-1"?>
<etichette>
<result>courier labels are managed by the warehouse</result>
</etichette><?xml version="1.0" encoding="iso-8859-1"?>
<etichette>
<result>Internal error (ref 3f2b8c1e-5a7d-4e2f-9b61-0c8d4a2e7f10)</result>
</etichette><?xml version="1.0" encoding="iso-8859-1"?>
<etichette>
<result>Unauthorized</result>
</etichette><?xml version="1.0" encoding="iso-8859-1"?>
<etichette>
<result>Too many requests</result>
</etichette>/api/admin/spedizioni/del-etichette-corriereVoid courier labels generated by Nucleo
Optional, off by default (see get-etichette-corriere). For each <order> (id = ord_ID) voids the active
shipment at the carrier and puts the order back to Exported, ready for new labels. Per-order problems are reported in
<error> (Order not found when there is no active shipment, or the carrier's message).
Idempotent: a second call finds no active shipment and answers Order not found for that order.
Rate limit: shared 600 calls/minute per connection.
Request bodyapplication/x-www-form-urlencoded, application/xml
xmlstringrequiredThe
<spedizioni>document.
Responses
200Outcome per order, or
xml parameter malformed.application/xmlOne of the following shapes:
LabelsVoided
result"OK"orderarray of objectAttributes of each item
idstringerrorstring
LabelsError
resultstring
404Courier labels are managed by the warehouse for this connection (default).application/xml
resultstring
500Unexpected error, with a reference to quote to support.application/xml
resultstring
4XXAuthentication, IP allowlist or rate limit (401, 403, 429), in the
<etichette>envelope.application/xmlresultstring
curl -X POST https://api-commerce.nucleoplatform.com/api/admin/spedizioni/del-etichette-corriere \
-u "$NUCLEO_USERNAME:$NUCLEO_PASSWORD" \
-H 'Content-Type: application/x-www-form-urlencoded' \
-H 'Accept: application/xml' \
--data-urlencode 'xml=<spedizioni><order><id>51042</id><colli>2</colli></order></spedizioni>'const res = await fetch("https://api-commerce.nucleoplatform.com/api/admin/spedizioni/del-etichette-corriere", {
method: "POST",
headers: {
Authorization: `Basic ${btoa(`${process.env.NUCLEO_USERNAME}:${process.env.NUCLEO_PASSWORD}`)}`,
"Content-Type": "application/x-www-form-urlencoded",
Accept: "application/xml",
},
body: new URLSearchParams({
xml: "<spedizioni><order><id>51042</id><colli>2</colli></order></spedizioni>",
}),
});
const data = await res.text();
console.log(res.status, data);<?php
require 'vendor/autoload.php';
$client = new GuzzleHttp\Client();
$response = $client->request('POST', 'https://api-commerce.nucleoplatform.com/api/admin/spedizioni/del-etichette-corriere', [
'auth' => [getenv('NUCLEO_USERNAME'), getenv('NUCLEO_PASSWORD')],
'headers' => [
'Accept' => 'application/xml',
],
'form_params' => [
'xml' => '<spedizioni><order><id>51042</id><colli>2</colli></order></spedizioni>',
],
'http_errors' => false,
]);
echo $response->getStatusCode(), PHP_EOL;
echo $response->getBody();<?xml version="1.0" encoding="iso-8859-1"?>
<etichette>
<result>OK</result>
<order>
<id>51042</id>
<error></error>
</order>
<order>
<id>59999</id>
<error>Order not found</error>
</order>
</etichette><?xml version="1.0" encoding="iso-8859-1"?>
<etichette>
<result>courier labels are managed by the warehouse</result>
</etichette><?xml version="1.0" encoding="iso-8859-1"?>
<etichette>
<result>Internal error (ref 3f2b8c1e-5a7d-4e2f-9b61-0c8d4a2e7f10)</result>
</etichette><?xml version="1.0" encoding="iso-8859-1"?>
<etichette>
<result>Unauthorized</result>
</etichette><?xml version="1.0" encoding="iso-8859-1"?>
<etichette>
<result>Too many requests</result>
</etichette>/api/admin/spedizioni/ws-close-borderoClose the bordereau of the day
Optional, off by default (see get-etichette-corriere); otherwise HTTP 404
<result><ack>KO</ack><error>courier labels are managed by the warehouse</error></result>.
Confirms to the carriers every shipment of this connection with labels created and not yet confirmed (one manifest per
carrier). Each order moves to Shipped, Nucleo creates the fulfilment on the sales channel and the order comes back in
ws_orders with state 31. No body is needed. The FFW spelling //api/admin/spedizioni/ws-close-bordero is accepted.
With nothing to confirm the answer is KO No shipping to be confirmed (HTTP 200), which also makes a repeated call harmless.
Rate limit: shared 600 calls/minute per connection.
Responses
200
OK, orKOwhen there is nothing to confirm.application/xmlackstringOne ofOKKOerrorstring
404Courier labels are managed by the warehouse for this connection (default).application/xml
ackstringOne ofOKKOerrorstring
500Unexpected error, with a reference to quote to support.application/xml
ackstringOne ofOKKOerrorstring
4XXAuthentication, IP allowlist or rate limit (401, 403, 429).application/xml
ackstringOne ofOKKOerrorstring
curl -X POST https://api-commerce.nucleoplatform.com/api/admin/spedizioni/ws-close-bordero \
-u "$NUCLEO_USERNAME:$NUCLEO_PASSWORD" \
-H 'Accept: application/xml'const res = await fetch("https://api-commerce.nucleoplatform.com/api/admin/spedizioni/ws-close-bordero", {
method: "POST",
headers: {
Authorization: `Basic ${btoa(`${process.env.NUCLEO_USERNAME}:${process.env.NUCLEO_PASSWORD}`)}`,
Accept: "application/xml",
},
});
const data = await res.text();
console.log(res.status, data);<?php
require 'vendor/autoload.php';
$client = new GuzzleHttp\Client();
$response = $client->request('POST', 'https://api-commerce.nucleoplatform.com/api/admin/spedizioni/ws-close-bordero', [
'auth' => [getenv('NUCLEO_USERNAME'), getenv('NUCLEO_PASSWORD')],
'headers' => [
'Accept' => 'application/xml',
],
'http_errors' => false,
]);
echo $response->getStatusCode(), PHP_EOL;
echo $response->getBody();<?xml version="1.0" encoding="iso-8859-1"?>
<result>
<ack>OK</ack>
<error></error>
</result><?xml version="1.0" encoding="iso-8859-1"?>
<result>
<ack>KO</ack>
<error>No shipping to be confirmed</error>
</result><?xml version="1.0" encoding="iso-8859-1"?>
<result>
<ack>KO</ack>
<error>courier labels are managed by the warehouse</error>
</result><?xml version="1.0" encoding="iso-8859-1"?>
<result>
<ack>KO</ack>
<error>Internal error (ref 3f2b8c1e-5a7d-4e2f-9b61-0c8d4a2e7f10)</error>
</result><?xml version="1.0" encoding="iso-8859-1"?>
<result>
<ack>KO</ack>
<error>Unauthorized</error>
</result><?xml version="1.0" encoding="iso-8859-1"?>
<result>
<ack>KO</ack>
<error>Too many requests</error>
</result>Returns
Download expected returns and report what was received.
/api/admin/resi/listDownload returns
Returns of orders fulfilled by this warehouse, or routed to one of its locations. Returns created by the warehouse itself
(parcels that arrived unannounced) are not listed. At least one of data_dal, data_al, last_upd, resi_ID is required.
States (resi_stati_ID, FFW defaults): 1 in progress (RESO IN CORSO), 2 confirmed (RESO CONFERMATO),
3 anomalous (RESO ANOMALO), 4 cancelled (RESO ANNULLATO).
Reasons (resi_causali_ID, FFW defaults): 1 wrong size · 2 not as pictured · 3 fit · 4 defective · 5 wrong item ·
6 other · 7 arrived late · 8 changed mind · 9 claim · 10 return to sender · 11 manual return. The description
(stato_descr) is in Italian, as in FFW.
last_updis a>=filter on the last change: a return can come back twice, update it byreso_ID.- Date range on the creation date, at most one month; without
data_dalit is one month beforedata_al. resi_stati_IDorresi_causali_IDrequiredata_dalorlimit.- At most 1000 returns without
limit. Default order: creation date descending (ASCfor ascending);orderBy=resi_idsorts byreso_IDascending. scontototreproduces the FFW sample: the VAT of the returned lines, negative.- Always XML (
type=csvis not supported). Reading has no side effect.
Errors: validation errors answer HTTP 200 with <result><ack>KO</ack><error_message>.
Rate limit: shared 600 calls/minute per connection.
Query parameters
data_dalstring (date)Creation date from,
yyyy-mm-dd.Example:2026-10-01data_alstring (date)Creation date to,
yyyy-mm-dd. Defaults to today.Example:2026-10-07last_updstringReturns changed from this instant (
>=),dd/mm/yyyy hh:mm:ss, Italian time, not older than one month.Example:07/10/2026 09:00:00resi_IDintegerOne return by id.
Example:7014resi_stati_IDstringState filter. Requires
data_dalorlimit.One of1234Example:1resi_causali_IDstringReason filter. Requires
data_dalorlimit.One of1234567891011Example:1magazzini_ID_webstringOnly returns routed to the location with this warehouse code.
Example:10limitintegerMaximum number of returns. Default 1000.
min 0Example:50orderBystringresi_idsorts byreso_IDascending; otherwise by creation date.One ofresi_idExample:resi_idASCstringWhen present (any value), the creation-date order is ascending.
Responses
200Returns (
<resi>), possibly empty (<resi/>), or aKOenvelope.application/xmlOne of the following shapes:
Returns
resoarray of ReturnAttributes of each item
reso_IDintegerreso_datastringdd/mm/yyyy.
reso_datetimestringyyyy-mm-dd HH:MM:SS.
resi_data_ultima_modificastringyyyy-mm-dd HH:MM:SS.
ord_IDintegerord_num_docstringnazioni_IDstringresi_stati_IDstringOne of1234stato_descrstringresi_causali_IDstringreso_descrstringCustomer reason text (CDATA).
reso_prezzototstringreso_prezzototale_eurostringscontototstringVAT of the returned lines with negative sign.
articoliobjectChild attributes
articoloarray of objectAttributes of each item
barcodestringqtaintegerart_prezzo_listinostringart_prezzo_internetstringart_prezzo_finale_scontatostringdocumenti_dettaglio_totale_ivastringiva_aliquotastringimporto_totale_rigastring
ResultErrorMessage
ack"KO"error_messagestringMessage in CDATA.
500Unexpected error, with a reference to quote to support.application/xml
ack"KO"error_messagestringMessage in CDATA.
4XXAuthentication, IP allowlist or rate limit (401, 403, 429), in the
<result>/<error_message>envelope.application/xmlack"KO"error_messagestringMessage in CDATA.
curl -X GET 'https://api-commerce.nucleoplatform.com/api/admin/resi/list?data_dal=2026-10-01&data_al=2026-10-07&last_upd=07%2F10%2F2026%2009%3A00%3A00&resi_ID=7014&resi_stati_ID=1&resi_causali_ID=1&magazzini_ID_web=10&limit=50&orderBy=resi_id' \
-u "$NUCLEO_USERNAME:$NUCLEO_PASSWORD" \
-H 'Accept: application/xml'const res = await fetch("https://api-commerce.nucleoplatform.com/api/admin/resi/list?data_dal=2026-10-01&data_al=2026-10-07&last_upd=07%2F10%2F2026%2009%3A00%3A00&resi_ID=7014&resi_stati_ID=1&resi_causali_ID=1&magazzini_ID_web=10&limit=50&orderBy=resi_id", {
method: "GET",
headers: {
Authorization: `Basic ${btoa(`${process.env.NUCLEO_USERNAME}:${process.env.NUCLEO_PASSWORD}`)}`,
Accept: "application/xml",
},
});
const data = await res.text();
console.log(res.status, data);<?php
require 'vendor/autoload.php';
$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'https://api-commerce.nucleoplatform.com/api/admin/resi/list?data_dal=2026-10-01&data_al=2026-10-07&last_upd=07%2F10%2F2026%2009%3A00%3A00&resi_ID=7014&resi_stati_ID=1&resi_causali_ID=1&magazzini_ID_web=10&limit=50&orderBy=resi_id', [
'auth' => [getenv('NUCLEO_USERNAME'), getenv('NUCLEO_PASSWORD')],
'headers' => [
'Accept' => 'application/xml',
],
'http_errors' => false,
]);
echo $response->getStatusCode(), PHP_EOL;
echo $response->getBody();<?xml version="1.0" encoding="iso-8859-1"?>
<resi>
<reso>
<reso_ID>7014</reso_ID>
<reso_data>07/10/2026</reso_data>
<reso_datetime>2026-10-07 09:41:02</reso_datetime>
<resi_data_ultima_modifica>2026-10-07 09:41:02</resi_data_ultima_modifica>
<ord_ID>51042</ord_ID>
<ord_num_doc>#1042</ord_num_doc>
<nazioni_ID>1</nazioni_ID>
<resi_stati_ID>1</resi_stati_ID>
<stato_descr><![CDATA[RESO IN CORSO]]></stato_descr>
<resi_causali_ID>1</resi_causali_ID>
<reso_descr><![CDATA[Too small]]></reso_descr>
<reso_prezzotot>30.00</reso_prezzotot>
<reso_prezzototale_euro>30.00</reso_prezzototale_euro>
<scontotot>-5.41</scontotot>
<articoli>
<articolo>
<barcode>8000000000017</barcode>
<qta>1</qta>
<art_prezzo_listino>24.59</art_prezzo_listino>
<art_prezzo_internet>24.59</art_prezzo_internet>
<art_prezzo_finale_scontato>24.59</art_prezzo_finale_scontato>
<documenti_dettaglio_totale_iva>5.41</documenti_dettaglio_totale_iva>
<iva_aliquota>22.00</iva_aliquota>
<importo_totale_riga>30.00</importo_totale_riga>
</articolo>
</articoli>
</reso>
</resi><?xml version="1.0" encoding="iso-8859-1"?>
<result>
<ack>KO</ack>
<error_message><![CDATA[Con resi_stati_ID o resi_causali_ID è obbligatorio impostare data_dal o limit.]]></error_message>
</result><?xml version="1.0" encoding="iso-8859-1"?>
<result>
<ack>KO</ack>
<error_message><![CDATA[Internal error (ref 3f2b8c1e-5a7d-4e2f-9b61-0c8d4a2e7f10)]]></error_message>
</result><?xml version="1.0" encoding="iso-8859-1"?>
<result>
<ack>KO</ack>
<error_message><![CDATA[Unauthorized]]></error_message>
</result><?xml version="1.0" encoding="iso-8859-1"?>
<result>
<ack>KO</ack>
<error_message><![CDATA[Forbidden]]></error_message>
</result><?xml version="1.0" encoding="iso-8859-1"?>
<result>
<ack>KO</ack>
<error_message><![CDATA[Too many requests]]></error_message>
</result>/api/admin/resi/notify-resoReport items received for returns
Items and quantities actually received for one or more returns (<reso> repeated).
- All or nothing: the whole call is validated first; an unknown
reso_IDor a malformed item rejects it and no return is updated. - The return is confirmed (state 2) when exactly the expected items and quantities arrived; otherwise it is anomalous (state 3) and goes to the merchant's customer service. An item not in the return makes it anomalous.
- If the return had been cancelled (or already closed) and the parcel arrives anyway, the goods are recorded, the merchant
is alerted and the answer is
OK.
Official input is the raw body; the form field xml is accepted too.
Idempotent: a second call on the same return recomputes the outcome.
Rate limit: shared 600 calls/minute per connection.
Request bodyapplication/xml, application/x-www-form-urlencoded
resoarray of objectAttributes of each item
reso_IDintegerrequiredarticoliobjectChild attributes
articoloarray of objectAttributes of each item
barcodestringrequiredqtaintegerrequiredmin 0notestring
Responses
200
OK, orKOwith the reason (nothing applied). AlsoKOwhen the connection is paused or a draft.application/xmlackstringOne ofOKKOmessagestring
500Unexpected error, with a reference to quote to support.application/xml
ackstringOne ofOKKOmessagestring
4XXAuthentication, IP allowlist or rate limit (401, 403, 429), in the
<result>/<message>envelope.application/xmlackstringOne ofOKKOmessagestring
curl -X POST https://api-commerce.nucleoplatform.com/api/admin/resi/notify-reso \
-u "$NUCLEO_USERNAME:$NUCLEO_PASSWORD" \
-H 'Content-Type: application/xml' \
-H 'Accept: application/xml' \
--data-binary @- <<'EOF'
<resi>
<reso>
<reso_ID>7014</reso_ID>
<articoli>
<articolo><barcode>8000000000017</barcode><qta>1</qta><note>intact</note></articolo>
</articoli>
</reso>
</resi>
EOFconst body = `<resi>
<reso>
<reso_ID>7014</reso_ID>
<articoli>
<articolo><barcode>8000000000017</barcode><qta>1</qta><note>intact</note></articolo>
</articoli>
</reso>
</resi>`;
const res = await fetch("https://api-commerce.nucleoplatform.com/api/admin/resi/notify-reso", {
method: "POST",
headers: {
Authorization: `Basic ${btoa(`${process.env.NUCLEO_USERNAME}:${process.env.NUCLEO_PASSWORD}`)}`,
"Content-Type": "application/xml",
Accept: "application/xml",
},
body,
});
const data = await res.text();
console.log(res.status, data);<?php
require 'vendor/autoload.php';
$client = new GuzzleHttp\Client();
$body = <<<'XML'
<resi>
<reso>
<reso_ID>7014</reso_ID>
<articoli>
<articolo><barcode>8000000000017</barcode><qta>1</qta><note>intact</note></articolo>
</articoli>
</reso>
</resi>
XML;
$response = $client->request('POST', 'https://api-commerce.nucleoplatform.com/api/admin/resi/notify-reso', [
'auth' => [getenv('NUCLEO_USERNAME'), getenv('NUCLEO_PASSWORD')],
'headers' => [
'Content-Type' => 'application/xml',
'Accept' => 'application/xml',
],
'body' => $body,
'http_errors' => false,
]);
echo $response->getStatusCode(), PHP_EOL;
echo $response->getBody();<?xml version="1.0" encoding="iso-8859-1"?>
<result>
<ack>OK</ack>
<message></message>
</result><?xml version="1.0" encoding="iso-8859-1"?>
<result>
<ack>KO</ack>
<message>XML is wrong or malformed</message>
</result><?xml version="1.0" encoding="iso-8859-1"?>
<result>
<ack>KO</ack>
<message>Reso 9999 non trovato</message>
</result><?xml version="1.0" encoding="iso-8859-1"?>
<result>
<ack>KO</ack>
<message>Internal error (ref 3f2b8c1e-5a7d-4e2f-9b61-0c8d4a2e7f10)</message>
</result><?xml version="1.0" encoding="iso-8859-1"?>
<result>
<ack>KO</ack>
<message>Unauthorized</message>
</result><?xml version="1.0" encoding="iso-8859-1"?>
<result>
<ack>KO</ack>
<message>Too many requests</message>
</result>