Orders
Orders are what the platform ships from the orders page: the ones imported from your connected shops and marketplaces (Amazon, eBay, Shopify, WooCommerce, …) and the ones your own system pushes through the API. Both kinds are read from the same list.
| Method | Endpoint | Description | Rate limit |
|---|---|---|---|
POST | /orders | Push up to 100 orders, as a CSV import would | 30 / min |
GET | /orders | List orders (paginated, filters, sort) | |
GET | /orders/{id} | Order detail with items, parcels and shipments | |
GET | /orders/summary | Counters, overall and per shop |
Orders carry the buyer’s data, which the API does not return to integrations: recipient holds only the destination city, province and country, and the buyer’s notes and the shipping error text are replaced by flags. See Recipient personal data. Editing, archiving, grouping and shipping orders are done from the platform.
Push orders
POST /orders — rate limit 30 / min
Sends up to 100 orders per call from your own system (ERP, shop, WMS). The orders appear in the platform under Import orders → Orders from API, exactly as if they had been imported from a CSV file, and are shipped from there by your operators. The endpoint carries the same data as the CSV import and applies the same defaults.
Use this endpoint when the people who ship work on the platform’s orders page. If your system creates the shipment itself and needs the label back, use POST /shipments instead.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
orders[] | Order[] | Yes | 1 to 100 orders |
saveToAddressBook | boolean | No | Also save each recipient in the address book (default false) |
Order object
| Field | Type | Required | Description |
|---|---|---|---|
orderNumber | string (50) | No | Order number in your system. Unique per account: an order number already sent is not imported again (see idempotency). Must be distinct within the call |
orderDate | date | No | YYYY-MM-DD. Default: today |
recipient.name | string (100) | Yes | |
recipient.address.street | string (150) | Yes | |
recipient.address.city | string (80) | Yes | |
recipient.address.province | string (50) | No | For Italy, the 2-letter code or the full name (Roma becomes RM) |
recipient.address.postalCode | string (15) | Yes | An Italian postal code sent without leading zeros (185) is completed (00185) |
recipient.address.countryCode | string (2) | No | ISO 3166-1 alpha-2. Default IT |
recipient.phone | string (30) | No | |
recipient.email | string | No | |
recipient.reference | string (50) | No | Recipient reference printed on the label |
senderReference | string (50) | No | Sender reference printed on the label. Default: the company name of the account |
parcels | integer | No | 1 to 50. Default 1 |
weight | Weight | No | { "value", "units": "KG"|"G" }. Default 1 kg |
cod | Money | No | Cash on delivery amount |
insurance | Money | No | Insured value |
total | number | No | Total of the order |
contentDescription | string (255) | No | |
notes | string (255) | No | Notes for the carrier |
items[] | object[] | No | Up to 200 lines: sku (required), quantity (required, ≥ 1), name, unitPrice. A line without name takes the title of the product with the same SKU in your catalog |
Example
Request
{
"saveToAddressBook": false,
"orders": [
{
"orderNumber": "ERP-1002",
"orderDate": "2026-09-20",
"recipient": {
"name": "Giulia Russo",
"address": { "street": "Via Appia 10", "city": "Roma", "province": "RM", "postalCode": "00183", "countryCode": "IT" },
"phone": "+39 333 1234567",
"email": "giulia@example.com",
"reference": "CLI-77"
},
"senderReference": "MAG-A",
"parcels": 1,
"weight": { "value": 1.2, "units": "KG" },
"cod": { "amount": 49.90 },
"total": 49.90,
"contentDescription": "Abbigliamento",
"notes": "Citofonare Russo",
"items": [
{ "sku": "TS-001", "quantity": 2, "unitPrice": 19.95 },
{ "sku": "BAG-9", "quantity": 1, "name": "Tote bag" }
]
},
{
"orderNumber": "ERP-1001",
"recipient": {
"name": "Marco Verdi",
"address": { "street": "Corso Italia 5", "city": "Milano", "province": "Milano", "postalCode": "20122" }
}
}
]
}Response
201 Created when at least one order was created, 200 OK when every order in the call had already been sent.
| Field | Type | Description |
|---|---|---|
created[] | Order[] | The orders created, in the order of the request — see the Order object |
skipped[] | object[] | Orders not imported because their orderNumber was already sent: index (position in the request orders[]), orderNumber, id (the existing order) |
Rules
- Only
recipient.name,recipient.address.street,cityandpostalCodeare required. Everything else takes the CSV import defaults: countryIT, 1 parcel, 1 kg, today’s date, the company name assenderReference. - The batch is validated as a whole: one invalid order rejects the entire call with
422 validation_failed, and nothing is saved. The keys oferror.detailsname the order by its position:orders.1.recipient.address.postalCode. - Two orders with the same
orderNumberin the same call are a validation error. - The batch is saved in one transaction: either all the valid orders are created or none is. You never have to work out which half of a batch went through.
- The recipient you send is stored and printed on the label, but is not returned by the API:
created[].recipientholds only the destination.
Idempotency
orderNumber makes the call repeatable. An order number already sent by your account is not imported a second time: it is listed in skipped with the id of the existing order and the rest of the batch is processed normally. A call that timed out can simply be retried with the same payload.
Orders sent without orderNumber cannot be recognised on a retry and would be created again. Always send it when your system has one.
| HTTP | code | When |
|---|---|---|
422 | validation_failed | Invalid payload; details names the order and field (orders.<index>.<field>) |
429 | rate_limited | More than 30 calls per minute |
List orders
GET /orders — paginated
| Query parameter | Type | Description |
|---|---|---|
from, to | date | Order date range. Without from: the last 30 days |
toShip | boolean | Only orders not shipped and not archived, without date limit |
storeId | integer | Shop the order was imported from (null for orders pushed through the API) |
sourceId | integer | Source of the order; 99 for orders pushed through the API |
marketplaceId | string | Marketplace identifier (e.g. the Amazon marketplace id) |
shipped, confirmed | boolean | |
archived | boolean | Default false: archived orders are not listed unless asked for |
hasError | boolean | Orders whose last shipping attempt failed |
trackingNumber | string | LDV of the shipment created for the order |
countryCode | string (2) | Destination country |
isPrime, isBusiness | boolean | Amazon Prime / Amazon Business orders |
sku | string | Orders containing an item whose SKU starts with the value |
q | string | Searches the order number, the shop order id and the tracking number |
sort | string | orderDate, latestShipDate, createdAt, id; prefix with - for descending. Default -orderDate |
per_page, page | integer | Pagination |
curl "https://<subdomain>.spedisci.online/api/2026-09/orders?toShip=true&sort=-latestShipDate&per_page=100" \
-H "Authorization: Bearer <access_token>" \
-H "Accept: application/json"Order object
{
"id": 5120,
"storeOrderId": "403-1111",
"orderNumber": "403-1111",
"reference": null,
"storeId": 3,
"sourceId": 4,
"marketplaceId": "APJ6JRA9NG5V4",
"recipient": { "address": { "city": "Milano", "province": "MI", "countryCode": "IT" } },
"senderReference": "MAG-A",
"parcels": 1,
"weight": { "value": 1.5, "units": "KG" },
"cod": null,
"insurance": null,
"total": 59.9,
"subtotal": 49.9,
"shippingCost": 10,
"contentDescription": "Abbigliamento",
"sku": "TS-001",
"tags": ["urgent"],
"paymentStatus": "paid",
"paymentGateway": "amazon",
"fulfillmentStatus": null,
"isPrime": true,
"isBusiness": false,
"shipped": false,
"confirmed": true,
"archived": false,
"trackingNumber": null,
"hasError": false,
"group": null,
"itemsCount": 3,
"firstItem": { "sku": "TS-001", "name": "Cotton T-shirt", "quantity": 2, "imageUrl": "https://..." },
"orderDate": "2026-10-12T10:15:00+02:00",
"latestShipDate": "2026-10-14T00:00:00+02:00",
"createdAt": "2026-10-12T10:20:03+02:00"
}| Field | Type | Description |
|---|---|---|
id | integer | Order id on the platform |
storeOrderId | string|null | Order id in the shop; your orderNumber for pushed orders |
orderNumber, reference | string|null | Order number and reference as imported |
storeId, sourceId, marketplaceId | Shop, source (99 = API) and marketplace | |
recipient | Destination | { "address": { "city", "province", "countryCode" } } only |
senderReference | string|null | Sender reference printed on the label |
parcels, weight | integer, Weight | |
cod, insurance | Money|null | |
total, subtotal, shippingCost | number|null | Order totals; shippingCost is what the buyer paid for shipping |
contentDescription, sku | string|null | |
tags | string[] | Tags from the shop |
paymentStatus, paymentGateway, fulfillmentStatus | string|null | As reported by the shop |
isPrime, isBusiness | boolean | Amazon Prime / Business |
shipped, confirmed, archived | boolean | State |
trackingNumber | string|null | LDV of the shipment created for the order |
hasError | boolean | The last shipping attempt failed |
group | object|null | { id, isPrimary } when the order is grouped with others into one shipment; the detail adds orderIds[] |
itemsCount | integer | Sum of the item quantities |
firstItem | object|null | First line: sku, name, quantity, imageUrl |
orderDate, latestShipDate, createdAt | datetime|null |
Order detail
GET /orders/{id}
The Order object plus:
| Field | Type | Description |
|---|---|---|
items[] | object[] | id, itemId, sku, asin, name, quantity, unitPrice, total, imageUrl, variants |
packs[] | object[] | Parcels declared by the shop: number, weight, dimensions |
group.orderIds[] | integer[] | The orders grouped together, when the order is part of a group |
shipments[] | object[] | Shipments already created for the order, most recent first: id, trackingNumber, status, manifestId, cost, createdAt |
{
"id": 5120,
"...": "...",
"items": [
{ "id": 90011, "itemId": "12345678", "sku": "TS-001", "asin": "B000000001", "name": "Cotton T-shirt", "quantity": 2, "unitPrice": 19.95, "total": 39.9, "imageUrl": "https://...", "variants": null }
],
"packs": [
{ "number": 1, "weight": { "value": 1.5, "units": "KG" }, "dimensions": { "length": 30, "width": 20, "height": 10, "units": "CM" } }
],
"shipments": [
{ "id": 4454058, "trackingNumber": "DEMO05407027", "status": { "code": 3, "key": "in_transit", "label": "In transito" }, "manifestId": 88213, "cost": { "amount": 7.0, "currency": "EUR" }, "createdAt": "2026-10-13T10:26:54+02:00" }
]
}404 not_found when the order does not exist or belongs to another client.
Orders summary
GET /orders/summary?storeId=&from=&to=
Counters of the orders, overall and per shop. Without from / to every order is counted.
{
"total": 412,
"toShip": 37,
"withError": 2,
"shipped": 360,
"archived": 15,
"prime": 9,
"stores": [
{ "storeId": 3, "sourceId": 4, "total": 300, "toShip": 30, "withError": 2, "shipped": 260, "archived": 10, "prime": 9 },
{ "storeId": null, "sourceId": 99, "total": 112, "toShip": 7, "withError": 0, "shipped": 100, "archived": 5, "prime": 0 }
]
}| Counter | Description |
|---|---|
total | All orders |
toShip | Not shipped and not archived |
withError | To ship, with the last shipping attempt failed |
shipped | Shipped and not archived |
archived | Archived |
prime | To ship with Amazon Prime |
Once an order is shipped from the platform, its shipment is a regular Shipment and the shipment.created and tracking.update webhook events carry the order number as order_id.