SendLabel API Docs
SendLabel API Docs for ERP / WMS
A cleaner docs layout for integrators: decide the integration path first, then move through core endpoints, execution modes, compatibility routes, and sample requests.
Integration mode
Unified + compat API
Execution
validate / dry_run / production
Delivery
PDF + tracking + cancel
Target systems
ERP / WMS / OMS
Overview
Confirm the base URL, auth method, and compatibility paths first to reduce implementation back-and-forth.
Base URL
https://www.sendlabel.de
All API paths are based on this domain.
OpenAPI
https://www.sendlabel.de/openapi.json
Machine-readable spec for Postman, Insomnia, and code generation tools.
Unified API
https://www.sendlabel.de/api/v1
Recommended for new integrations.
DHL compat base
https://www.sendlabel.de/api/compat/dhl-parcel-de
Includes both native-like `/orders /labels /manifests /pickup` mirrors and `/v1/*` resource aliases.
UPS compat base
https://www.sendlabel.de/api/compat/ups
Includes native-style `/security /shipments /track /rating /pickup` mirrors and `/v1/*` resource aliases.
- - Auth supported: Authorization: Bearer <API_KEY> / X-API-Key / Basic(base64(prefix:key)) / dhl-api-key / x-ibm-client-id + x-ibm-client-secret
- - Each API key also accepts virtual client_id aliases such as sendlabel_<API_KEY_PREFIX>, ups_<API_KEY_PREFIX>, and dhl_<API_KEY_PREFIX>.
- - If you already have a native DHL / UPS client, start with compat routes; for new projects, start with /api/v1.
- - Compatibility error responses now use a dual-track contract: they keep DHL / UPS style fields and also add a normalized `sendlabelError` block for ERP / WMS parsers.
Pick the integration path first
This is the most important orientation block in the redesigned page.
New project / new API
Prefer /api/v1. The fields and error contract are more consistent and easier to maintain.
Existing ERP / WMS native DHL / UPS flow
Prefer /api/compat/{provider}/v1 and keep changes close to the original integration.
Quickstart
Follow this order to complete the first dry run with minimal friction.
- 1. Create the API key in /admin/api-keys and assign the correct scopes.
- 2. Optional: create a sender and set it as the default sender.
- 3. Test /api/v1/shipments/import with validate_only or dry_run first.
- 4. Then poll /api/v1/jobs or read /api/v1/orders/{orderId}.
Customer API self-test
After login, customers can test their own JSON directly in `/profile/api` before wiring a full client. The validator now supports SendLabel Unified, DHL Compat, and UPS Compat.
- - SendLabel Unified: best for testing our own generic API by pasting the `/api/v1/shipments/import` JSON directly.
- - DHL / UPS Compat: best for customers with native carrier clients. You can keep the default sample or replace it with the real payload.
- - For SendLabel Unified, use `validate_only` or `dry_run` for self-testing; controlled live tests remain limited to DHL / UPS compat.
Unified API self-test request example
POST /api/profile/api-validator
Content-Type: application/json
{
"token": "slk_xxx",
"suite": "sendlabel_unified_v1",
"scenario": "import_address_review",
"executionMode": "dry_run",
"requestPayload": {
"carrier": "DHL_PARCEL_DE",
"labelPrintFormat": "A4",
"buyerType": "b2c",
"sender": {
"name": "SendLabel Demo GmbH",
"street1": "Lindenstr. 5",
"postalCode": "70173",
"city": "Stuttgart",
"countryCode": "DE"
},
"shipments": [
{
"reference": "ERP-SELF-TEST-001",
"recipient": {
"name": "Max Mustermann",
"street1": "Lindenstr. 5, 1.OG links, c/o Mann",
"postalCode": "70173",
"city": "Stuttgart",
"countryCode": "DE"
},
"parcel": { "weightKg": 1.2, "lengthCm": 30, "widthCm": 20, "heightCm": 10 }
}
]
}
}Execution modes and safety
Enterprise clients should treat validate_only, dry_run, and production as three explicit integration stages.
validate_only
Validate only. No order, payment, or queue job.
dry_run
Return estimated action and price without creating real side effects.
production
Live execution with real order, payment, and label workflow.
- - Execution mode can be sent via X-SendLabel-Execution-Mode or body.executionMode.
- - Send Idempotency-Key on import / cancel POST requests.
- - Within 24 hours, the same API key + same idempotency key + same body returns the original response.
- - Unified import and UPS compat import are currently limited to 300 requests per 60 seconds per API key; over-limit calls return 429 with a Retry-After header.
- - A single request can carry up to 1000 shipments, but 50-200 shipments per batch is the better operating range for retries, debugging, and smoother latency.
- - Poll /api/v1/jobs every 2-5 seconds; this endpoint also returns 429 + Retry-After, so back off with 2s -> 5s -> 10s when throttled.
Unified error contract
{
"ok": false,
"error": {
"code": "rate_limited",
"message": "Too many requests. Please retry later.",
"details": {
"retryAfterSeconds": 31,
"limit": 300,
"windowSeconds": 60
}
}
}Unified API endpoints
The unified API is product-style and best for new customers, new projects, and custom middleware.
Address book and setup
GET
/api/v1/senders
List sender addresses.
POST
/api/v1/senders
Create a sender address.
POST
/api/v1/senders/default
Set the default sender.
Core shipment flow
POST
/api/v1/shipments/import
Import shipments, validate them, and trigger label creation.
GET
/api/v1/jobs?ids=job_1,job_2
Poll async job status.
GET
/api/v1/orders/{orderId}
Read order details, label summary, and tracking snapshot.
GET
/api/v1/labels?orderId={orderId}
Download the label PDF directly.
GET
/api/v1/orders/{orderId}/tracking
Read tracking data; DHL supports ?refresh=now.
POST
/api/v1/orders/{orderId}/cancel
Request remote cancellation; requires cancel:write.
Compatibility routes
The long route list is regrouped by carrier so implementers can find the right endpoints faster.
DHL Parcel DE / Pickup compatibility
https://www.sendlabel.de/api/compat/dhl-parcel-de/v1/*
Resource aliases for senders / shipments/import / jobs / orders / tracking / cancel / labels, useful when older systems migrate gradually toward the unified resource model.
https://www.sendlabel.de/api/compat/dhl-parcel-de/orders
Accepts native DHL POST /orders payloads.
https://www.sendlabel.de/api/compat/dhl-parcel-de/orders?validate=true
Validates address/data only and creates no real shipment.
https://www.sendlabel.de/api/compat/dhl-parcel-de/labels?shipment={shipmentNumber}
Returns the PDF directly by shipment number.
https://www.sendlabel.de/api/compat/dhl-parcel-de/manifests
Supports manifest / closeout creation and lookup.
https://www.sendlabel.de/api/compat/dhl-parcel-de/pickup/v3/orders
Create pickup orders and auto-map internal orders.
https://www.sendlabel.de/api/compat/dhl-parcel-de/pickup/v3/orders/{pickupId}
Cancel pickup and close the refund loop.
UPS compatibility
https://www.sendlabel.de/api/compat/ups/v1/*
Resource aliases for senders / shipments/import / jobs / orders / tracking / cancel / labels, suitable for gradual migration toward the unified resource model.
https://www.sendlabel.de/api/compat/ups/security/v1/oauth/token
Exchange API key prefix + full key for an access token.
https://www.sendlabel.de/api/compat/ups/v1/shipments/import
Import UPS shipments with the normalized JSON contract and return label/tracking immediately on success.
https://www.sendlabel.de/api/compat/ups/shipments/v1/ship
Accepts native ShipmentRequest payloads and creates the shipment synchronously.
https://www.sendlabel.de/api/compat/ups/shipments/v1/labels/{shipmentIdentificationNumber}
Return the PDF directly by tracking number.
https://www.sendlabel.de/api/compat/ups/shipments/v1/void/cancel/{shipmentIdentificationNumber}
Void the UPS shipment directly by tracking number.
https://www.sendlabel.de/api/compat/ups/track/v1/details/{inquiryNumber}
UPS-style tracking lookup.
https://www.sendlabel.de/api/compat/ups/rating/v1/Shop
Return multi-service rate results.
UPS label API integration
If the goal is to create live UPS labels through our API, use one of the two paths below: unified API for new systems, UPS compat for existing native UPS clients.
Recommended UPS path
- - New integrations: prefer `/api/v1/shipments/import` for a cleaner payload and a more stable error contract.
- - Existing UPS native integrations: prefer `/api/compat/ups/...`; in most cases you only replace the base URL and authentication.
- - Before going live, validate with `validate_only` or `dry_run` so address normalization, service code, and scopes are confirmed.
- - Live execution requires `shipments:import` and `mode:production`; add `cancel:write` if remote cancel is needed.
- - If the client plans high-frequency batch traffic, shape the client at 300 requests per minute per API key and honor Retry-After for backoff.
Option 1: create UPS labels via the unified API
This is the recommended path for new customers. After creation, continue with `results[].orderId / jobId` to query the order, job, and label.
curl -X POST "https://www.sendlabel.de/api/v1/shipments/import" \
-H "Authorization: Bearer <API_KEY>" \
-H "X-SendLabel-Execution-Mode: production" \
-H "Idempotency-Key: ups-erp-2026-0001" \
-H "Content-Type: application/json" \
-d '{
"carrier": "UPS",
"labelPrintFormat": "A4",
"senderId": "addr_sender_default",
"shipments": [
{
"reference": "UPS-ERP-0001",
"recipient": {
"name": "Erika Mustermann",
"company": "Muster GmbH",
"street1": "Lindenstr. 5",
"postalCode": "70173",
"city": "Stuttgart",
"countryCode": "DE",
"email": "erika@example.com",
"phone": "+49 151 23456789"
},
"parcel": {
"weightKg": 1.5,
"lengthCm": 30,
"widthCm": 20,
"heightCm": 10
}
}
]
}'Option 2: UPS compat auth example
If the customer already has a UPS OAuth-style client, exchange credentials on the mirror token route first to obtain a short-lived bearer token. Use `ups_<API_KEY_PREFIX>` as `client_id` and the full API key as `client_secret`.
curl -X POST "https://www.sendlabel.de/api/compat/ups/security/v1/oauth/token" \
-u "ups_<API_KEY_PREFIX>:<API_KEY>" \
-H "Content-Type: application/x-www-form-urlencoded" \
--data "grant_type=client_credentials"Option 2: UPS compat import example
If the customer already uses our UPS compat import JSON contract, this route now also returns label / tracking immediately after UPS succeeds and settles billing asynchronously afterwards.
curl -X POST "https://www.sendlabel.de/api/compat/ups/v1/shipments/import" \
-H "Authorization: Bearer <API_KEY>" \
-H "X-SendLabel-Execution-Mode: production" \
-H "Idempotency-Key: ups-compat-import-2026-0001" \
-H "Content-Type: application/json" \
-d '{
"carrier": "UPS",
"labelPrintFormat": "A4",
"senderId": "addr_sender_default",
"shipments": [
{
"reference": "UPS-COMPAT-0001",
"recipient": {
"name": "Erika Mustermann",
"company": "Muster GmbH",
"street1": "Lindenstr. 5",
"postalCode": "70173",
"city": "Stuttgart",
"countryCode": "DE",
"email": "erika@example.com",
"phone": "+49 151 23456789"
},
"parcel": {
"weightKg": 1.5,
"lengthCm": 30,
"widthCm": 20,
"heightCm": 10
}
}
]
}'UPS compat shipment example
This route accepts UPS-style `ShipmentRequest` payloads and appends `ShipmentResponse.Compatibility` so you can read back the internal `orderId`, `labelUrl`, and address review info.
curl -X POST "https://www.sendlabel.de/api/compat/ups/shipments/v1/ship" \
-H "Authorization: Bearer <UPS_COMPAT_ACCESS_TOKEN>" \
-H "X-SendLabel-Execution-Mode: production" \
-H "Idempotency-Key: ups-native-2026-0001" \
-H "Content-Type: application/json" \
-d '{
"ShipmentRequest": {
"Shipment": {
"Shipper": {
"Name": "SendLabel Demo GmbH",
"AttentionName": "Warehouse Team",
"Phone": { "Number": "+497111234567" },
"Address": {
"AddressLine": ["Lindenstr. 5"],
"PostalCode": "70173",
"City": "Stuttgart",
"CountryCode": "DE"
}
},
"ShipFrom": {
"Name": "SendLabel Demo GmbH",
"AttentionName": "Warehouse Team",
"Phone": { "Number": "+497111234567" },
"Address": {
"AddressLine": ["Lindenstr. 5"],
"PostalCode": "70173",
"City": "Stuttgart",
"CountryCode": "DE"
}
},
"ShipTo": {
"Name": "Erika Mustermann",
"AttentionName": "Erika Mustermann",
"Phone": { "Number": "+4915123456789" },
"Address": {
"AddressLine": ["Lindenstr. 5"],
"PostalCode": "70173",
"City": "Stuttgart",
"CountryCode": "DE"
}
},
"Service": { "Code": "11" },
"Package": [{
"PackagingType": { "Code": "02" },
"PackageWeight": { "Weight": "1.5" },
"Dimensions": { "Length": "30", "Width": "20", "Height": "10" }
}]
},
"LabelSpecification": {
"LabelImageFormat": { "Code": "PDF" }
}
}
}'Successful responses and async settlement fields
Unified UPS import success response
{
"ok": true,
"created": 1,
"total": 1,
"executionMode": "production",
"sideEffectsSuppressed": false,
"results": [
{
"index": 0,
"reference": "UPS-ERP-0001",
"ok": true,
"orderId": "ord_ups_20260001",
"jobId": "job_settlement_20260001",
"jobType": "api_async_settlement",
"trackingNumber": "1Z12345E0205271688",
"labelUrl": "https://www.sendlabel.de/api/v1/labels?orderId=ord_ups_20260001",
"asyncSettlement": {
"status": "pending",
"jobId": "job_settlement_20260001"
},
"notes": [
"UPS shipment created successfully. Billing settlement continues asynchronously in the background."
]
}
]
}UPS compat import success response
{
"ok": true,
"created": 1,
"total": 1,
"executionMode": "production",
"sideEffectsSuppressed": false,
"results": [
{
"index": 0,
"reference": "UPS-COMPAT-0001",
"ok": true,
"orderId": "ord_ups_20260002",
"jobId": "job_settlement_20260002",
"jobType": "api_async_settlement",
"trackingNumber": "1Z12345E0205271689",
"labelUrl": "https://www.sendlabel.de/api/compat/ups/v1/labels?orderId=ord_ups_20260002",
"asyncSettlement": {
"status": "pending",
"jobId": "job_settlement_20260002"
},
"notes": [
"UPS shipment created successfully. Billing settlement continues asynchronously in the background."
]
}
]
}- - `results[].trackingNumber` and `results[].labelUrl` mean UPS has already created the shipment and the client can show or download the label immediately.
- - `results[].asyncSettlement.status = pending` means local charging / credit deduction continues in the background.
- - If async settlement ultimately fails, the system retries automatically, sends alert emails after repeated failures, and then tries to void the UPS label automatically.
Common UPS follow-up endpoints
- - After unified creation: poll `GET /api/v1/jobs?ids=<jobId>` for job status.
- - Read order details with `GET /api/v1/orders/{orderId}`; UPS compat clients can also use `GET /api/compat/ups/v1/orders/{orderId}`.
- - Download the label PDF via `GET /api/v1/labels?orderId={orderId}` or the UPS compat route `GET /api/compat/ups/v1/labels?orderId={orderId}`.
- - Read tracking via `GET /api/v1/orders/{orderId}/tracking` or `GET /api/compat/ups/v1/orders/{orderId}/tracking`.
- - Remote-cancel a UPS label via `POST /api/v1/orders/{orderId}/cancel` or by tracking number using `DELETE /api/compat/ups/shipments/v1/void/cancel/{shipmentIdentificationNumber}`.
Carrier and address handling
This section keeps the important business rules but expresses them in shorter, easier-to-scan blocks.
Carriers and services
- - DHL_PARCEL_DE: DHL Paket (domestic / EU)
- - DHL_KLEINPAKET: DHL Kleinpaket (DE only, <= 1 kg)
- - DP_INTL: Deutsche Post International (Germany to non-EU)
- - For UPS, prefer the compat routes, especially when you already have a native UPS client.
Address validation and splitting
- - Before live DHL label creation, the system calls validate and returns field-level errors where possible.
- - If the error mentions Leitcode, ZIP, city, street, or house number are usually inconsistent.
- - The system tries to split street1 into streetName + streetNo + addressExtra, for example Lindenstr. 5, 1.OG links, c/o Mann.
- - The UPS compat routes reuse the same address splitting logic so c/o, floor, and buzzer details do not pollute the main street line.
Example request and response
The most useful dry_run request and the standard response shape are placed together for faster copy-and-test work.
Request example: dry_run import and estimate
curl -X POST "https://www.sendlabel.de/api/v1/shipments/import" \
-H "Authorization: Bearer <API_KEY>" \
-H "X-SendLabel-Execution-Mode: dry_run" \
-H "Idempotency-Key: erp-2026-0001" \
-H "Content-Type: application/json" \
-d '{
"carrier": "DHL_PARCEL_DE",
"labelPrintFormat": "A4",
"buyerType": "b2b",
"shipments": [
{
"reference": "ERP-0001",
"recipient": {
"name": "Max Mustermann",
"street1": "Dingelberg 18",
"postalCode": "38444",
"city": "Wolfsburg",
"countryCode": "DE",
"email": "max@example.com",
"phone": "+49 176 23414739"
},
"parcel": { "weightKg": 1.8, "lengthCm": 30, "widthCm": 20, "heightCm": 10 }
}
]
}'Response example: standard contract
{
"ok": true,
"created": 0,
"total": 1,
"executionMode": "dry_run",
"sideEffectsSuppressed": true,
"results": [
{
"index": 0,
"reference": "ERP-0001",
"ok": true,
"simulated": true,
"wouldCreateShipment": true,
"estimatedAmount": { "currency": "EUR", "amount": 6.23 },
"notes": ["Dry run completed. No order, label, payment, or queue job was created."]
}
]
}- - In production, results[] usually contains orderId and jobId.
- - UPS dry_run may also return estimatedService; low-confidence address parsing may also add notes and addressReview.
- - Common labelPrintFormat values: A4, A5, 910-300-600, 100x70mm.
Order lifecycle and webhooks
Lifecycle lookups, cancellation, webhooks, and signature rules now live together in one area.
Orders and cancellation
- - GET /api/v1/orders/{orderId}: returns order details, label summary, tracking snapshot, and the public tracking URL.
- - GET /api/v1/orders/{orderId}/tracking: read tracking data; DHL supports ?refresh=now.
- - POST /api/v1/orders/{orderId}/cancel: request remote cancellation; the API key needs cancel:write.
Webhook
- - Configure webhook URL, event list, and shared secret on the API key.
- - Supported events: order.created, order.cancelled, label.created, tracking.updated.
- - Headers: x-sendlabel-event, x-sendlabel-timestamp, x-sendlabel-signature.
- - Signature formula: HMAC_SHA256(webhookSecret, timestamp + '.' + rawBody).
- - Webhooks are delivered asynchronously via background jobs and retry automatically on failure.
Web UI batch import
A clear path for non-API customers so they know the web workflow is also available.
- - Use “Batch Import (Excel)” on the “Create Shipment” page.
- - The system reads the first worksheet, adds the shipments to the cart, and then handles payment and label creation together.