Skip to main content

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.

EndpointAuth
POST /api/v1/shipmentsBearer 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

FieldTypeLengthRequiredDescription
invoicingNumberString1–20MandatoryCustomer billing number
numberOfParcelsInteger1–2 digitsMandatoryTotal parcels
customerReferenceNumber1String0–35OptionalCustomer reference 1. Truncated, not rejected
customerReferenceNumber2String0–35OptionalCustomer reference 2. Truncated, not rejected
customerReferenceNumber3String0–35OptionalCustomer reference 3. Truncated, not rejected
customerReferenceNumber4String0–35OptionalCustomer reference 4. Truncated, not rejected
shipmentNoteStringOptionalShipment note
parcelShopIdStringConditionalRequired for ParcelShop delivery services
clientSoftwareString1–30MandatoryClient application name
clientVersionString1–10MandatoryClient application version
identificationNumberString0–100OptionalYour own identifier for this shipment, echoed back in failed[]
Some limits are not enforced

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, clientVersion and identificationNumber are checked before the batch is processed. An over-long value rejects the whole request with 400.
  • Every other limit is checked per shipment. An over-long value fails that shipment with a fieldErrors[] entry and the request returns 207 (or 400 if every shipment failed).
  • Fields marked truncated in the tables are the exception: they are shortened, not rejected.
  • Parcel weight is checked against a per-product maximum, see the weight table below.

Address fields (sender / receiver / return)

FieldTypeLengthRequiredNotes
nameString1–35MandatoryCompany or person name. Truncated, not rejected
name2String0–35OptionalAdditional name line. Truncated, not rejected
contactString0–35OptionalContact person. Truncated, not rejected
countryCodeString2MandatoryISO 3166-1 alpha-2
stateCodeStringConditionalRequired for US/CA
zipCodeString1–9MandatoryPostal code
cityString1–35MandatoryCity. Truncated, not rejected
streetString1–35MandatoryStreet name and number. Truncated, not rejected
street2String0–35OptionalAdditional address line. Truncated, not rejected
houseNumberString0–8ConditionalHouse Number. Truncated, not rejected
phoneString0–35ConditionalRequired for GB — international format
emailString0–100ConditionalRequired for non-CH/LI countries (except GB)
eoriStringConditionalRequired for GB/NO international.
vatStringConditionalRequired for GB/NO international (non-CH)
languageStringOptionalISO 639-1 (DE, EN, FR, IT)
referenceStringOptionalAddress reference
noteString0–70OptionalDelivery instructions
glnStringOptionalGlobal Location Number

Parcel info (parcelInfo[])

Array of parcel objects — one entry per physical parcel. The number of entries should match numberOfParcels.

FieldTypeLengthRequiredDescription
serviceCodeStringMandatoryParcel-level service code — see Services and Options
optionCodesArray<String>OptionalAdditional service option codes — see Services and Options
contentStringOptionalParcel content description (PCONTENT)
weightIntegerMandatoryParcel weight in grams — maximum depends on the product, see below
reference1String0–35OptionalParcel reference 1. Truncated, not rejected
reference2String0–35OptionalParcel reference 2. Truncated, not rejected
reference3String0–35OptionalParcel reference 3. Truncated, not rejected
reference4String0–35OptionalParcel reference 4. Truncated, not rejected
higherInsuranceObjectOptionalHigher-insurance additional service (see below)
limitedQuantitiesObjectOptionalLimited-quantities dangerous-goods data (see below)

Maximum parcel weightweight is sent in grams, and a parcel above these limits is rejected with a weight field error:

ProductDomesticInternational
PSD35 kg20 kg
PL2 kg2 kg
PBOX5 kg5 kg
All other products35 kg31.5 kg

higherInsurance fields:

FieldTypeLengthRequiredDescription
amountNumberMandatoryInsured amount
currencyStringMandatoryISO 4217 currency code

limitedQuantities fields:

FieldTypeLengthRequiredDescription
unNumberString0–4ConditionalUN dangerous-goods number (e.g. 1234). Mandatory for international shipments with the LQ option
codeString0–5OptionalPacking code (e.g. C1)
packagingGroupStringConditionalPackaging group (e.g. I, II, III). Mandatory for international shipments with the LQ option
klassString0–6OptionalDangerous-goods class (e.g. 8)
subWeightInteger0–6OptionalSubstance weight

Notes:

  • No field has a default value — omitted fields stay empty.
  • For international (non-domestic) shipments carrying the LQ service option, unNumber and packagingGroup are mandatory; otherwise all fields are optional.
  • Allowed characters for unNumber, code, klass, subWeight: letters, digits, space and . ( ) / _ | -. packagingGroup has 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 — identificationUnNounNumber, identificationClassklass, packingGrouppackagingGroup, packingCodecode, hazardousWeightsubWeight.

Customs data (customsData)

Required for international (non-domestic customs) shipments.

FieldTypeLengthRequiredDescription
shipmentTypeString1–2MandatoryParcel type (PARCELTYPE) — see values below
valueNumberMandatoryCustoms value of goods (CAMOUNT)
currencyStringOptionalISO 4217 currency for value
valueExNumberOptionalAdditional customs value (CAMOUNTEX)
currencyExStringOptionalISO 4217 currency for valueEx
reasonForExportString1–35MandatoryReason-for-export code — see values below
termsOfDeliveryString1–35MandatoryIncoterms / terms of delivery (CTERMS) — see values below
clearanceClearedString1–35MandatoryClearance-cleared flag — see values below
opCodeStringOptionalOperation code
preAlertStatusStringOptionalPre-alert status
contentStringOptionalCustoms content description (CCONTENT)
paperStringOptionalPaperwork flag (CPAPER)
highLowValueStringOptionalHigh/low value indicator
invoiceNumberString0–35OptionalCommercial invoice number (CINVOICE)
dateDate (yyyy-MM-dd)MandatoryInvoice date (CINVOICEDATE)
exportMRNString0–209OptionalExport Movement Reference Number (SHIPMRN)
documentTypesArray<String>OptionalCustoms document types
commentStringOptionalCustoms comment (CCOMMENT)
comment2StringOptionalDestination country registration (DESTCOUNTRYREG)
senderHMRCString0–209OptionalSender HMRC registration
senderInvoicingAddressObjectOptionalSender invoice address (address object)
receiverInvoicingAddressObjectOptionalRecipient invoice address (address object)
numberOfInvoiceLinesIntegerOptionalNumber of invoice lines (NUMBEROFARTICLE)
invoiceLinesArray<Object>ConditionalInvoice line items (see below). Count between number of parcels and number of parcels + 20

shipmentType values:

ValueDescription
DDocument
PNon-document

reasonForExport values:

ValueDescription
01Sale (default)
02Return / replacement
03Gift

termsOfDelivery values:

ValueDescription
01DAP, not cleared
02DDP, delivered duty paid (incl. duties, excl. taxes)
03DDP, delivered duty paid (incl. duties and taxes)
05Ex Works (EXW)
06DAP
07DAP enhanced — duties and taxes pre-paid by the receiver

clearanceCleared values:

ValueDescription
NNo
FFree
EExport cleared
TTransit cleared
IImport cleared
HHybrid

invoiceLines[] fields:

FieldTypeLengthRequiredDescription
natureOfGoodsString0–200OptionalNature of goods (CCONTENT)
hsCodeString6 or 8 digitsOptionalHS tariff code
productCodeStringOptionalProduct code (CPRODCODE)
amountNumber13 digits + 2 decimalsOptionalLine amount (CAMOUNTLINE)
grossWeightIntegerup to 5 digitsOptionalGross weight (CGROSSWEIGHT)
qItemsIntegerup to 5 digitsMandatoryQuantity of items
countryOfOriginString0–3OptionalISO country of origin (CORIGIN)
FieldTypeRequiredDescription
paperSizeStringOptionalLabel size: A4 or A6 (default: A6)
printerLanguageStringOptionalOutput format: PDF, ZPL, or EPL (default: PDF)
printerResolutionIntegerOptionalPrint resolution in dpi for ZPL/EPL output — 150, 200/203, 300, or 600 (default 200; other values in 72600 are accepted but fall back to 200 dpi; ignored for PDF)
startPositionStringOptionalLabel position on A4 sheet: UPPER_LEFT, UPPER_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT
dropOffTypeStringOptionalLabel content: FULL_LABEL (default, full shipping label), QR_CODE (digital PNG QR label), or BOTH
splitLabelsBooleanOptionalWhen 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)
includeBarcodeBooleanOptionalWhen 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.

FieldLocationTypeDescription
serviceNameshipment rootStringHuman-readable name of the resolved service. Set by DPD; ignored on input
persReceivershipment rootAddressDTOFor PUDO/parcel-shop shipments, the original recipient when receiver has been replaced by the shop address
routingInfoshipment root, parcelInfo[]ObjectRouting data resolved by DPD (destinationBu, dsort, osort, csort, ssort). Set by DPD; ignored on input
returnRoutingInfoshipment root, parcelInfo[]ObjectSame structure as routingInfo, for the return leg
pickupRequestshipment rootObjectPickup attached to the shipment (pickupDate, note, state)
soCodeparcelInfo[]ObjectSorting/service code resolved by DPD (code, asCode, serviceText, specialText, specialMark)
urladdressStringOptional 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:

CodeDescription
201 CreatedAll shipments created successfully
207 Multi-StatusSome succeeded, some failed
400 Bad RequestInvalid request payload, or every item in the batch failed (whatever the cause, including a routing-engine outage)
401 UnauthorizedMissing 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: A4 each 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-level label, no label field inside parcelNumbers[].

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:

PartLengthContent
Identification tag1Always %
Postal code7Receiver postal code, uppercased and left-padded with 0
Parcel number14The parcel number of this entry
SO code3Routing service code of this parcel
Country3ISO 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 barcode field 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, and dropOffType.
  • Without the flag (or with includeBarcode: false) the barcode field is omitted entirely.
  • The barcode requires a routed shipment. If the routing data of a parcel is incomplete, that entry is returned without a barcode rather 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"
}
}
]'