Shipments
Create one or multiple shipments in a single request. The API validates all fields, generates parcel numbers, enriches routing data, and returns PDF labels.
| Endpoint | Auth |
|---|---|
POST /api/v1/shipments | Bearer JWT token required |
Create Shipment
Request
Content-Type: application/json
Body: array of shipment objects
[
{
"invoicingNumber": "12345678",
"serviceCode": "PSD",
"sender": { },
"receiver": { },
"parcelInfo": [ ],
"customsData": { },
"printOptions": { }
}
]
Shipment root fields
| Field | Type | Length | Required | Description |
|---|---|---|---|---|
invoicingNumber | String | 1–20 | Mandatory | Customer billing number |
numberOfParcels | Integer | 1–2 digits | Mandatory | Total parcels |
customerReferenceNumber1 | String | 0–35 | Optional | Customer reference 1. Truncated, not rejected |
customerReferenceNumber2 | String | 0–35 | Optional | Customer reference 2. Truncated, not rejected |
customerReferenceNumber3 | String | 0–35 | Optional | Customer reference 3. Truncated, not rejected |
customerReferenceNumber4 | String | 0–35 | Optional | Customer reference 4. Truncated, not rejected |
shipmentNote | String | — | Optional | Shipment note |
parcelShopId | String | — | Conditional | Required for ParcelShop delivery services |
clientSoftware | String | 1–30 | Mandatory | Client application name |
clientVersion | String | 1–10 | Mandatory | Client application version |
identificationNumber | String | 0–100 | Optional | Your own identifier for this shipment, echoed back in failed[] |
Address names, street lines, house number, and the parcel and customer references are not rejected when too long. The value is silently cut to the limit and no error is reported. If the request has other problems you get those errors instead, which can look unrelated to the field that was too long. Enforce these lengths in your own code.
How field lengths are checked
The Length column shows the limit the API applies. A dash means the length is not checked.
invoicingNumber,clientSoftware,clientVersionandidentificationNumberare checked before the batch is processed. An over-long value rejects the whole request with400.- Every other limit is checked per shipment. An over-long value fails that shipment with a
fieldErrors[]entry and the request returns207(or400if every shipment failed). - Fields marked truncated in the tables are the exception: they are shortened, not rejected.
- Parcel
weightis checked against a per-product maximum, see the weight table below.
Address fields (sender / receiver / return)
| Field | Type | Length | Required | Notes |
|---|---|---|---|---|
name | String | 1–35 | Mandatory | Company or person name. Truncated, not rejected |
name2 | String | 0–35 | Optional | Additional name line. Truncated, not rejected |
contact | String | 0–35 | Optional | Contact person. Truncated, not rejected |
countryCode | String | 2 | Mandatory | ISO 3166-1 alpha-2 |
stateCode | String | — | Conditional | Required for US/CA |
zipCode | String | 1–9 | Mandatory | Postal code |
city | String | 1–35 | Mandatory | City. Truncated, not rejected |
street | String | 1–35 | Mandatory | Street name and number. Truncated, not rejected |
street2 | String | 0–35 | Optional | Additional address line. Truncated, not rejected |
houseNumber | String | 0–8 | Conditional | House Number. Truncated, not rejected |
phone | String | 0–35 | Conditional | Required for GB — international format |
email | String | 0–100 | Conditional | Required for non-CH/LI countries (except GB) |
eori | String | — | Conditional | Required for GB/NO international. |
vat | String | — | Conditional | Required for GB/NO international (non-CH) |
language | String | — | Optional | ISO 639-1 (DE, EN, FR, IT) |
reference | String | — | Optional | Address reference |
note | String | 0–70 | Optional | Delivery instructions |
gln | String | — | Optional | Global Location Number |
Parcel info (parcelInfo[])
Array of parcel objects — one entry per physical parcel. The number of entries should match numberOfParcels.
| Field | Type | Length | Required | Description |
|---|---|---|---|---|
serviceCode | String | — | Mandatory | Parcel-level service code — see Services and Options |
optionCodes | Array<String> | — | Optional | Additional service option codes — see Services and Options |
content | String | — | Optional | Parcel content description (PCONTENT) |
weight | Integer | — | Mandatory | Parcel weight in grams — maximum depends on the product, see below |
reference1 | String | 0–35 | Optional | Parcel reference 1. Truncated, not rejected |
reference2 | String | 0–35 | Optional | Parcel reference 2. Truncated, not rejected |
reference3 | String | 0–35 | Optional | Parcel reference 3. Truncated, not rejected |
reference4 | String | 0–35 | Optional | Parcel reference 4. Truncated, not rejected |
higherInsurance | Object | — | Optional | Higher-insurance additional service (see below) |
limitedQuantities | Object | — | Optional | Limited-quantities dangerous-goods data (see below) |
Maximum parcel weight — weight is sent in grams, and a parcel above these limits is
rejected with a weight field error:
| Product | Domestic | International |
|---|---|---|
PSD | 35 kg | 20 kg |
PL | 2 kg | 2 kg |
PBOX | 5 kg | 5 kg |
| All other products | 35 kg | 31.5 kg |
higherInsurance fields:
| Field | Type | Length | Required | Description |
|---|---|---|---|---|
amount | Number | — | Mandatory | Insured amount |
currency | String | — | Mandatory | ISO 4217 currency code |
limitedQuantities fields:
| Field | Type | Length | Required | Description |
|---|---|---|---|---|
unNumber | String | 0–4 | Conditional | UN dangerous-goods number (e.g. 1234). Mandatory for international shipments with the LQ option |
code | String | 0–5 | Optional | Packing code (e.g. C1) |
packagingGroup | String | — | Conditional | Packaging group (e.g. I, II, III). Mandatory for international shipments with the LQ option |
klass | String | 0–6 | Optional | Dangerous-goods class (e.g. 8) |
subWeight | Integer | 0–6 | Optional | Substance weight |
Notes:
- No field has a default value — omitted fields stay empty.
- For international (non-domestic) shipments carrying the
LQservice option,unNumberandpackagingGroupare mandatory; otherwise all fields are optional. - Allowed characters for
unNumber,code,klass,subWeight: letters, digits, space and. ( ) / _ | -.packagingGrouphas no length or character restriction. - Integration guidance (field correspondence, not validated by this API): when migrating from the Shivah WS
<hazardous>block, the fields correspond as follows —identificationUnNo→unNumber,identificationClass→klass,packingGroup→packagingGroup,packingCode→code,hazardousWeight→subWeight.
Customs data (customsData)
Required for international (non-domestic customs) shipments.
| Field | Type | Length | Required | Description |
|---|---|---|---|---|
shipmentType | String | 1–2 | Mandatory | Parcel type (PARCELTYPE) — see values below |
value | Number | — | Mandatory | Customs value of goods (CAMOUNT) |
currency | String | — | Optional | ISO 4217 currency for value |
valueEx | Number | — | Optional | Additional customs value (CAMOUNTEX) |
currencyEx | String | — | Optional | ISO 4217 currency for valueEx |
reasonForExport | String | 1–35 | Mandatory | Reason-for-export code — see values below |
termsOfDelivery | String | 1–35 | Mandatory | Incoterms / terms of delivery (CTERMS) — see values below |
clearanceCleared | String | 1–35 | Mandatory | Clearance-cleared flag — see values below |
opCode | String | — | Optional | Operation code |
preAlertStatus | String | — | Optional | Pre-alert status |
content | String | — | Optional | Customs content description (CCONTENT) |
paper | String | — | Optional | Paperwork flag (CPAPER) |
highLowValue | String | — | Optional | High/low value indicator |
invoiceNumber | String | 0–35 | Optional | Commercial invoice number (CINVOICE) |
date | Date (yyyy-MM-dd) | — | Mandatory | Invoice date (CINVOICEDATE) |
exportMRN | String | 0–209 | Optional | Export Movement Reference Number (SHIPMRN) |
documentTypes | Array<String> | — | Optional | Customs document types |
comment | String | — | Optional | Customs comment (CCOMMENT) |
comment2 | String | — | Optional | Destination country registration (DESTCOUNTRYREG) |
senderHMRC | String | 0–209 | Optional | Sender HMRC registration |
senderInvoicingAddress | Object | — | Optional | Sender invoice address (address object) |
receiverInvoicingAddress | Object | — | Optional | Recipient invoice address (address object) |
numberOfInvoiceLines | Integer | — | Optional | Number of invoice lines (NUMBEROFARTICLE) |
invoiceLines | Array<Object> | — | Conditional | Invoice line items (see below). Count between number of parcels and number of parcels + 20 |
shipmentType values:
| Value | Description |
|---|---|
D | Document |
P | Non-document |
reasonForExport values:
| Value | Description |
|---|---|
01 | Sale (default) |
02 | Return / replacement |
03 | Gift |
termsOfDelivery values:
| Value | Description |
|---|---|
01 | DAP, not cleared |
02 | DDP, delivered duty paid (incl. duties, excl. taxes) |
03 | DDP, delivered duty paid (incl. duties and taxes) |
05 | Ex Works (EXW) |
06 | DAP |
07 | DAP enhanced — duties and taxes pre-paid by the receiver |
clearanceCleared values:
| Value | Description |
|---|---|
N | No |
F | Free |
E | Export cleared |
T | Transit cleared |
I | Import cleared |
H | Hybrid |
invoiceLines[] fields:
| Field | Type | Length | Required | Description |
|---|---|---|---|---|
natureOfGoods | String | 0–200 | Optional | Nature of goods (CCONTENT) |
hsCode | String | 6 or 8 digits | Optional | HS tariff code |
productCode | String | — | Optional | Product code (CPRODCODE) |
amount | Number | 13 digits + 2 decimals | Optional | Line amount (CAMOUNTLINE) |
grossWeight | Integer | up to 5 digits | Optional | Gross weight (CGROSSWEIGHT) |
qItems | Integer | up to 5 digits | Mandatory | Quantity of items |
countryOfOrigin | String | 0–3 | Optional | ISO country of origin (CORIGIN) |
Print options
| Field | Type | Required | Description |
|---|---|---|---|
paperSize | String | Optional | Label size: A4 or A6 (default: A6) |
printerLanguage | String | Optional | Output format: PDF, ZPL, or EPL (default: PDF) |
printerResolution | Integer | Optional | Print resolution in dpi for ZPL/EPL output — 150, 200/203, 300, or 600 (default 200; other values in 72–600 are accepted but fall back to 200 dpi; ignored for PDF) |
startPosition | String | Optional | Label position on A4 sheet: UPPER_LEFT, UPPER_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT |
dropOffType | String | Optional | Label content: FULL_LABEL (default, full shipping label), QR_CODE (digital PNG QR label), or BOTH |
splitLabels | Boolean | Optional | When true, the response returns one label per parcel number on each parcelNumbers[] item instead of a single merged label (default: false, see Split labels per parcel number) |
includeBarcode | Boolean | Optional | When true, every parcelNumbers[] item also carries the barcode printed on that parcel's label (default: false, see Routing barcode in the response) |
Note: print options apply to the whole request — the first shipment in the batch that has printOptions set wins.
Label format & size: the terms labelFormat/labelSize map to printerLanguage (format) and paperSize (size). Supported formats are PDF (default), ZPL, and EPL; supported sizes are A4 and A6. A QR_CODE/BOTH dropOffType returns a digital PNG QR label. The equivalent Shivah WS fields are printerLanguage (PDF/ZPL) and paperFormat — see ShipmentService.
Additional fields
These fields exist on the request and response and are accepted, but are normally populated by DPD rather than by you. They are listed for completeness — if you are reading them out of an API log or a Swagger example, this is what they are.
| Field | Location | Type | Description |
|---|---|---|---|
serviceName | shipment root | String | Human-readable name of the resolved service. Set by DPD; ignored on input |
persReceiver | shipment root | AddressDTO | For PUDO/parcel-shop shipments, the original recipient when receiver has been replaced by the shop address |
routingInfo | shipment root, parcelInfo[] | Object | Routing data resolved by DPD (destinationBu, dsort, osort, csort, ssort). Set by DPD; ignored on input |
returnRoutingInfo | shipment root, parcelInfo[] | Object | Same structure as routingInfo, for the return leg |
pickupRequest | shipment root | Object | Pickup attached to the shipment (pickupDate, note, state) |
soCode | parcelInfo[] | Object | Sorting/service code resolved by DPD (code, asCode, serviceText, specialText, specialMark) |
url | address | String | Optional URL carried on an address |
Do not send elementCodes. It is not part of this API's contract, and unknown fields are ignored
(see below), so sending it has no effect.
Request and response handling
- Unknown fields are ignored. A property the API does not recognise does not cause an error; it is silently dropped. A misspelled field name therefore behaves exactly like an omitted one.
- A single value is accepted where an array is expected, and wrapped automatically.
- Null fields are omitted from responses. Any field with no value is absent from the JSON
rather than present as
null, so response objects vary in shape depending on what was populated.
Response
201 Created — all shipments created. By default all labels are merged into the single top-level label (base64):
{
"tracingId": "TRACE-123",
"label": "base64-encoded-labels...",
"success": [
{
"tracingId": "05305000123456",
"parcelNumbers": [
{ "serviceCode": "B2B", "number": "05305000123456" },
{ "serviceCode": "B2B", "number": "05305000123457" }
]
}
],
"failed": []
}
207 Multi-Status — partial success. Each failed[] item has an identificationNumber (echoes the client-supplied value, when the request item had one — use it to map a failure back to the input item) and an errorCode; field-level violations appear as a flat fieldErrors[] array, each entry carrying its own path — the same code can appear at more than one path (e.g. both sender.email and receiver.email):
{
"tracingId": "TRACE-456",
"label": "base64-encoded-labels...",
"success": [
{
"tracingId": "05305000123456",
"parcelNumbers": [ { "serviceCode": "B2B", "number": "05305000123456" } ]
}
],
"failed": [
{
"identificationNumber": "client-supplied-id-9",
"errorCode": "SYS-VALIDATION-FAILURE",
"fieldErrors": [
{
"path": "receiver.countryCode",
"code": "SHP-VAL-COUNTRYCODE-ALLOWED-CHARACTERS",
"message": "Country code contains invalid characters."
},
{
"path": "receiver.email",
"code": "SHP-VAL-EMAIL-REQUIRED",
"message": "Email address is required."
}
]
}
]
}
A transient failure (no fieldErrors — an outage is not a field problem) looks like this instead:
{
"identificationNumber": "client-supplied-id-11",
"errorCode": "SHP-ROUTING-ENGINE-UNAVAILABLE",
"reason": "SHP-ROUTING-ENGINE-UNAVAILABLE: Routing engine is temporarily unavailable. Please try again."
}
Status codes:
| Code | Description |
|---|---|
201 Created | All shipments created successfully |
207 Multi-Status | Some succeeded, some failed |
400 Bad Request | Invalid request payload, or every item in the batch failed (whatever the cause, including a routing-engine outage) |
401 Unauthorized | Missing or invalid token |
Split labels per parcel number
With "printOptions": { "splitLabels": true } the top-level label is left out and every entry
in parcelNumbers[] carries its own base64 label containing only the label(s) generated for
that parcel number:
{
"tracingId": "TRACE-123",
"success": [
{
"tracingId": "05305000123456",
"parcelNumbers": [
{
"serviceCode": "B2B",
"number": "05305000123456",
"label": "base64-encoded-label..."
},
{
"serviceCode": "B2B",
"number": "05305000123457",
"label": "base64-encoded-label..."
}
]
}
],
"failed": []
}
- Works for all label formats and paper sizes. With PDF output and
paperSize: A4each parcel number gets its own A4 document instead of several labels placed on one sheet. - Return and swap parcel numbers appear as their own
parcelNumbers[]entries and carry their own labels. - Without the flag (or with
splitLabels: false) the response is unchanged: one merged top-levellabel, nolabelfield insideparcelNumbers[].
Routing barcode in the response
With "printOptions": { "includeBarcode": true } every entry in parcelNumbers[] also carries
the barcode field — the exact Code128 content of the routing barcode printed on that parcel's
label, i.e. what a scanner reads off the label:
{
"tracingId": "TRACE-123",
"label": "base64-encoded-labels...",
"success": [
{
"tracingId": "05305000123456",
"parcelNumbers": [
{
"serviceCode": "B2B",
"number": "05305000123456",
"barcode": "%000815305305000123456420756"
}
]
}
],
"failed": []
}
The value is the identification tag % followed by 27 characters:
| Part | Length | Content |
|---|---|---|
| Identification tag | 1 | Always % |
| Postal code | 7 | Receiver postal code, uppercased and left-padded with 0 |
| Parcel number | 14 | The parcel number of this entry |
| SO code | 3 | Routing service code of this parcel |
| Country | 3 | ISO 3166 numeric code of the delivery country |
- The human-readable line under the barcode on the label adds a check digit (IEC 7064 mod 37,36)
and groups the digits in blocks of four; the
barcodefield contains neither. - Return and swap parcel numbers carry the barcode of their own label, which routes on a different SO code and on the return receiver's postal code — not on the forward parcel's values.
- Independent of
printerLanguage,paperSize,splitLabels, anddropOffType. - Without the flag (or with
includeBarcode: false) thebarcodefield is omitted entirely. - The barcode requires a routed shipment. If the routing data of a parcel is incomplete, that
entry is returned without a
barcoderather than failing the request.
Example
curl -X POST "https://label-print-shipments.dpd.ch/api/v1/shipments" \
-H "Authorization: Bearer <jwt_token>" \
-H "Content-Type: application/json" \
-d '[
{
"invoicingNumber": "12345678",
"serviceCode": "PSD",
"numberOfParcels": 1,
"sender": {
"name": "Sender AG",
"countryCode": "CH",
"zipCode": "8000",
"city": "Zürich",
"street": "Industriestrasse 25"
},
"receiver": {
"name": "Receiver GmbH",
"countryCode": "DE",
"zipCode": "10115",
"city": "Berlin",
"street": "Alexanderplatz 1",
"email": "info@receiver.de"
},
"parcelInfo": [
{ "weight": 2500 }
],
"printOptions": {
"paperSize": "A6"
}
}
]'