Skip to main content

Parcel Shops

Search for DPD pickup points (parcel shops, lockers, service points) by address or GPS coordinates.

Base PathAuth
/api/v1/parcel-shopBearer JWT token required

Endpoints summary

MethodEndpointDescription
GET/api/v1/parcel-shop/{parcelShopId}Get a specific parcel shop by ID
POST/api/v1/parcel-shop/addressSearch parcel shops by address
POST/api/v1/parcel-shop/coordinatesSearch parcel shops by GPS coordinates

GET /api/v1/parcel-shop/{parcelShopId}

Retrieve details for a specific parcel shop.

Path parameter: parcelShopId — e.g. FR64548. The numeric form returned as parcelShopId in responses (e.g. 70825452535256) is accepted as well.

Query parameter: lang (optional) — en, de, fr or it. Controls weekDay and services[].description. Falls back to Accept-Language, then to the business unit default.

curl -X GET "https://label-print-shipments.dpd.ch/api/v1/parcel-shop/FR64548?lang=en" \
-H "Authorization: Bearer <jwt_token>"

Response 200 OK (opening hours abridged to two days):

{
"id": "FR64548",
"parcelShopId": 70825452535256,
"name": "Chris’music",
"order": 1,
"distance": 0,
"type": 100,
"countryNum": "250",
"address": {
"countryCode": "FR",
"zipCode": "71500",
"city": "LOUHANS",
"street": "RUE DES BORDES",
"street2": "",
"street3": "",
"houseNumber": "57",
"language": "FR"
},
"locationHint": "",
"mapUrl": "",
"available": "partial",
"latitude": 46.624802,
"longitude": 5.224876,
"openingHours": [
{
"weekDay": "Monday",
"openMorning": "09:30",
"closeMorning": "12:00",
"openAfternoon": "14:00",
"closeAfternoon": "19:00"
},
{
"weekDay": "Friday",
"openMorning": "09:30",
"closeMorning": "12:00"
}
],
"holidays": [
{ "start": "15/08/2026", "end": "29/08/2026" }
],
"services": [
{ "code": "100", "available": true, "description": "Pickup by consignee" },
{ "code": "200", "available": true, "description": "Parcels paid online are accepted" },
{ "code": "991", "available": true, "description": "Returns are accepted" }
]
}

Notes on the response shape:

  • Fields with no value are omitted, never returned as null. In the example the Friday entry has no openAfternoon or closeAfternoon because that day has a single opening block. Do not rely on a key being present.
  • holidays dates use dd/MM/yyyy, not ISO 8601. The rest of the API uses ISO dates.
  • parcelShopId is the numeric encoding of id; both identify the same shop.
  • weekDay and services[].description are localised according to lang.

Status codes: 200 OK | 401 Unauthorized | 404 Not Found


POST /api/v1/parcel-shop/address

Search for parcel shops near an address. Results sorted by distance (closest first).

Request body:

FieldTypeRequiredDescriptionDefault
countryString (2)MandatoryISO country code
zipCodeStringMandatoryPostal code
cityStringOptionalCity name
streetStringOptionalStreet name
destCountryCodeStringOptionalDestination country for service filtering
weightStringOptionalParcel weight in kg
servicesStringOptionalComma-separated service codes
typeStringOptionalParcel shop type filter
limitIntegerOptionalMax results25
availabilityDateStringOptionalCheck availability on date (yyyy-MM-dd)
hideClosedBooleanOptionalExclude currently closed shopsfalse
curl -X POST "https://label-print-shipments.dpd.ch/api/v1/parcel-shop/address?lang=de_CH" \
-H "Authorization: Bearer <jwt_token>" \
-H "Content-Type: application/json" \
-d '{
"country": "CH",
"zipCode": "8000",
"city": "Zürich",
"limit": 10
}'

Status codes: 200 OK (may return empty list) | 400 Bad Request | 401 Unauthorized


POST /api/v1/parcel-shop/coordinates

Search for parcel shops near GPS coordinates. Same filtering and response format as address search.

Request body:

FieldTypeRequiredDescription
latitudeDoubleMandatoryGPS latitude (−90 to 90)
longitudeDoubleMandatoryGPS longitude (−180 to 180)
destCountryCodeStringOptionalDestination country
limitIntegerOptionalMax results (default: 25)
hideClosedBooleanOptionalExclude closed shops (default: false)
availabilityDateStringOptionalCheck availability on date
curl -X POST "https://label-print-shipments.dpd.ch/api/v1/parcel-shop/coordinates" \
-H "Authorization: Bearer <jwt_token>" \
-H "Content-Type: application/json" \
-d '{
"latitude": 47.3769,
"longitude": 8.5417,
"limit": 10,
"hideClosed": true
}'

Status codes: 200 OK | 400 Bad Request | 401 Unauthorized


Parcel shop types

type is not defined by this API. The value is passed straight through from the upstream DPD PUDO service, both in the response and in the optional type request filter, so the two always use the same value space.

TypeDescription
100DPD Pickup Point
200DPD Locker
300Partner Shop (e.g., Post Office)
400Service Point

Treat the list as incomplete rather than closed: the upstream service owns these values, so do not reject a value you do not recognise.

type is a different field from services[].code, even though both use three-digit numbers. A shop with "type": 100 can carry any combination of service codes.

To filter by shop type, use a value you have seen in a response for the same region rather than a guessed one.


Search field notes

  • No length limits are enforced. The API applies no maximum length to any search field; the upstream service decides what it accepts. country is expected to be a 2-character ISO country code, but a longer value is forwarded rather than rejected.
  • destCountryCode is a destination country code used to filter shops by the services available for that destination. It is forwarded to the upstream service without validation, so an unrecognised value yields no matches rather than an error.

Code examples

Parcel shop selector in a shipment form:

async function searchParcelShops(zipCode, city) {
const response = await fetch(
'https://label-print-shipments.dpd.ch/api/v1/parcel-shop/address',
{
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ country: 'CH', zipCode, city, limit: 10 })
}
);
return response.json();
}

Map-based finder:

function findNearby(lat, lng) {
return fetch('https://label-print-shipments.dpd.ch/api/v1/parcel-shop/coordinates', {
method: 'POST',
headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' },
body: JSON.stringify({ latitude: lat, longitude: lng, limit: 20, hideClosed: true })
}).then(r => r.json());
}