HomeCreate LabelExport CustomsFreight QuotePricingTrackingHS CodeHelpAPI Docs
You can create labels without registration, but addresses won’t be saved. Create an account to reuse saved addresses.
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://t2.sendlabel.de
All API paths are based on this domain.
OpenAPI
https://t2.sendlabel.de/openapi.json
Machine-readable spec for Postman, Insomnia, and code generation tools.
Unified API
https://t2.sendlabel.de/api/v1
Recommended for new integrations.
DHL compat base
https://t2.sendlabel.de/api/compat/dhl-parcel-de
Includes both native-like `/orders /labels /manifests /pickup` mirrors and `/v1/*` resource aliases.
UPS compat base
https://t2.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. 1. Create the API key in /admin/api-keys and assign the correct scopes.
  2. 2. Optional: create a sender and set it as the default sender.
  3. 3. Test /api/v1/shipments/import with validate_only or dry_run first.
  4. 4. Then poll /api/v1/jobs or read /api/v1/orders/{orderId}.
Customer API self-test
After login, customers can use `/profile/api` as the unified console for key management, access state, and production requests. Actual integration testing now lives in the dedicated `/profile/api-tester` hub.
  • - API console: manage keys, inspect access state, submit production requests, and confirm test completion after integration.
  • - Tester hub: split into dedicated SendLabel Unified, UPS Compat, and DHL Compat entry points.
  • - During integration, test the real `/api/v1/*` or `/api/compat/*` endpoints directly instead of using the retired customer-side validator wrapper.
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://t2.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://t2.sendlabel.de/api/compat/dhl-parcel-de/orders
Accepts native DHL POST /orders payloads.
https://t2.sendlabel.de/api/compat/dhl-parcel-de/orders?validate=true
Validates address/data only and creates no real shipment.
https://t2.sendlabel.de/api/compat/dhl-parcel-de/labels?shipment={shipmentNumber}
Returns the PDF directly by shipment number.
https://t2.sendlabel.de/api/compat/dhl-parcel-de/manifests
Supports manifest / closeout creation and lookup.
https://t2.sendlabel.de/api/compat/dhl-parcel-de/pickup/v3/orders
Create pickup orders and auto-map internal orders.
https://t2.sendlabel.de/api/compat/dhl-parcel-de/pickup/v3/orders/{pickupId}
Cancel pickup and close the refund loop.
UPS compatibility
https://t2.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://t2.sendlabel.de/api/compat/ups/security/v1/oauth/token
Exchange API key prefix + full key for an access token.
https://t2.sendlabel.de/api/compat/ups/v1/shipments/import
Import UPS shipments with the normalized JSON contract and return label/tracking immediately on success.
https://t2.sendlabel.de/api/compat/ups/shipments/v1/ship
Accepts native ShipmentRequest payloads and creates the shipment synchronously.
https://t2.sendlabel.de/api/compat/ups/shipments/v1/labels/{shipmentIdentificationNumber}
Return the PDF directly by tracking number.
https://t2.sendlabel.de/api/compat/ups/shipments/v1/void/cancel/{shipmentIdentificationNumber}
Void the UPS shipment directly by tracking number.
https://t2.sendlabel.de/api/compat/ups/track/v1/details/{inquiryNumber}
UPS-style tracking lookup.
https://t2.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://t2.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": "Max Mustermann",
          "company": "Muster GmbH",
          "street1": "Dingelberg 18",
          "postalCode": "38444",
          "city": "Wolfsburg",
          "countryCode": "DE",
          "email": "max@example.com",
          "phone": "+4953611234567"
        },
        "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://t2.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://t2.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": "Max Mustermann",
          "company": "Muster GmbH",
          "street1": "Dingelberg 18",
          "postalCode": "38444",
          "city": "Wolfsburg",
          "countryCode": "DE",
          "email": "max@example.com",
          "phone": "+4953611234567"
        },
        "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://t2.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": "MyCompany DE GmbH",
          "AttentionName": "SendLabel Absender",
          "Phone": { "Number": "+4953176543210" },
          "Address": {
            "AddressLine": ["Steinriedendamm 15"],
            "PostalCode": "38108",
            "City": "Braunschweig",
            "CountryCode": "DE"
          }
        },
        "ShipFrom": {
          "Name": "MyCompany DE GmbH",
          "AttentionName": "SendLabel Absender",
          "Phone": { "Number": "+4953176543210" },
          "Address": {
            "AddressLine": ["Steinriedendamm 15"],
            "PostalCode": "38108",
            "City": "Braunschweig",
            "CountryCode": "DE"
          }
        },
        "ShipTo": {
          "Name": "Max Mustermann",
          "AttentionName": "Max Mustermann",
          "Phone": { "Number": "+4953611234567" },
          "Address": {
            "AddressLine": ["Dingelberg 18"],
            "PostalCode": "38444",
            "City": "Wolfsburg",
            "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://t2.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://t2.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://t2.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": 5.88 },
      "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.