Customs Declaration
Shipments that cross the EU customs border need a customs declaration. In the Client API it is the customsDetail object of POST /shipments: it is stored on the shipment, returned in customsDetail and transmitted to the carrier.
When it is required
customsDetail is mandatory when shipper and recipient are on different sides of the EU customs territory:
- destinations outside the EU (United Kingdom, Switzerland, USA, …);
- special territories of EU member states that are outside the customs territory: Canary Islands, Ceuta, Melilla (
ES), Livigno and Campione d’Italia (IT), Helgoland and Büsingen (DE), Åland (FI), Mount Athos (GR) — matched by postal code.
Monaco, San Marino and Andorra are inside the customs territory and do not require it. For every other destination customsDetail is optional.
A missing declaration answers 422 validation_failed with a customsDetail error.
customsDetail object
| Field | Type | Required | Description |
|---|---|---|---|
customsValue | Money | Yes | Total declared value. Must equal the sum of the commodity values (tolerance: 1 % or 1 currency unit) |
incoterm | string | No | EXW, FCA, CPT, CIP, DAP (default), DPU, DDP, FOB, CFR, CIF |
dutiesPayment | string | No | Who pays duties and taxes: SENDER, RECIPIENT (default), THIRD_PARTY |
contentType | string | No | MERCHANDISE (default), GIFT, SAMPLE, DOCUMENTS, RETURN, REPAIR, PERSONAL_EFFECTS |
exportReason | string | No | SALE (default), GIFT, SAMPLE, RETURN, REPAIR, PERSONAL |
invoiceNumber | string (50) | No | Commercial invoice number |
invoiceDate | date | No | YYYY-MM-DD |
exporter | object | No | eori, vatNumber, taxId of the sender |
importer | object | No | eori, vatNumber, taxId of the recipient |
commodities[] | Commodity[] | Yes | 1 to 99 items |
Commodity object
| Field | Type | Required | Description |
|---|---|---|---|
description | string (255) | Yes | Description of the goods, in English where possible |
harmonizedCode | string | No | HS / TARIC code, 6 to 10 digits (see search below) |
quantity | integer | Yes | ≥ 1 |
quantityUnits | string | No | PCS (default), PR, DOZ, KG, L, M, M2, M3, SET |
unitValue | Money | Yes | Value per unit |
totalValue | Money | No | Default: unitValue × quantity |
weight | Weight | Yes | Weight of the line |
countryOfManufacture | string (2) | Yes | Country of origin, ISO 3166-1 alpha-2 |
midCode | string (30) | No | Manufacturer identification code (USA) |
sku | string (100) | No | Your article code |
Example
A shipment from Italy to Switzerland with two commodity lines:
{
"reference": "ORD-1234",
"serviceType": "fedex-international",
"recipient": {
"name": "John Doe",
"address": { "street": "Bahnhofstrasse 1", "street2": "2. OG", "city": "Zürich", "province": "ZH", "postalCode": "8001", "countryCode": "CH" },
"phone": "+41 44 000 00 00",
"email": "john@example.com"
},
"packages": [
{ "weight": { "value": 1.5, "units": "KG" }, "dimensions": { "length": 30, "width": 20, "height": 10, "units": "CM" } }
],
"options": { "contentDescription": "Clothing", "labelFormat": "PDF" },
"customsDetail": {
"customsValue": { "amount": 120.00, "currency": "EUR" },
"incoterm": "DAP",
"dutiesPayment": "RECIPIENT",
"contentType": "MERCHANDISE",
"exportReason": "SALE",
"invoiceNumber": "FT-2026-001",
"invoiceDate": "2026-09-01",
"exporter": { "eori": "IT01234567890", "vatNumber": "IT01234567890" },
"importer": { "eori": null, "vatNumber": "CHE-123.456.789", "taxId": null },
"commodities": [
{
"description": "Cotton T-shirt",
"harmonizedCode": "610910",
"quantity": 2,
"quantityUnits": "PCS",
"unitValue": { "amount": 25.00, "currency": "EUR" },
"totalValue": { "amount": 50.00, "currency": "EUR" },
"weight": { "value": 0.4, "units": "KG" },
"countryOfManufacture": "CN",
"sku": "TS-001"
},
{
"description": "Leather belt",
"harmonizedCode": "420330",
"quantity": 1,
"unitValue": { "amount": 70.00, "currency": "EUR" },
"weight": { "value": 0.3, "units": "KG" },
"countryOfManufacture": "IT"
}
]
}
}customsValue.amount (120) equals 2 × 25 + 1 × 70. The 201 response returns the declaration as stored in customsDetail.
Searching HS / TARIC codes
GET /taric?q=<term>&limit=25 — rate limit 60 / min
Searches the TARIC nomenclature by Italian or English description, or by code prefix. q needs at least 3 characters; limit defaults to 25 (max 100).
Request
curl "https://<subdomain>.spedisci.online/api/2026-09/taric?q=t-shirt" \
-H "Authorization: Bearer <access_token>" \
-H "Accept: application/json"What reaches the carriers
| Carrier | Data transmitted |
|---|---|
| FedEx | One commodity per line (description, HS code, origin, quantity, unit and total value, weight, SKU), totalCustomsValue, dutiesPayment (SENDER with the contract account, RECIPIENT; THIRD_PARTY falls back to RECIPIENT), commercial invoice (incoterm, purpose from exportReason), recipient customs id and sender TIN from EORI / VAT number, document-only flag for DOCUMENTS |
| DHL Express | Export declaration with one line item per commodity (HS code, origin, price, quantity, weight, export reason, taxes-paid flag for DDP), invoice (invoiceNumber / invoiceDate, otherwise the order reference and today’s date), incoterm, declared value, EORI / VAT registration numbers of shipper and receiver |
| Poste Delivery Business | One item per commodity (TARIC, origin, quantity, value in cents, weight in grams), content code from contentType, total waybill value |
| Spring GDS | One product per commodity (description, HS code, quantity, value, origin, SKU), declared value of the shipment |
| UPS | International forms (commercial invoice: number / date, reason for export, incoterm, currency, sold-to = recipient, one product per commodity with HS code, origin, quantity and unit value) |
Shipments created without customsDetail from the web interface or from marketplace orders to non-EU destinations get an automatic declaration built from the order lines, enriched with the customs defaults of your product catalog (customs description, HS code, country of origin, MID code, declared value) as configured in the web interface. Keeping the catalog complete avoids customs holds.