# DHL API

- Tool: Bubble
- Difficulty: Intermediate
- Time required: 2–3 hours
- Last updated: July 2026

## TL;DR

Connect your Bubble app to DHL's tracking or shipping APIs using the API Connector plugin with a Private header. The Tracking API uses a simple DHL-API-Key header; the Express API uses HTTP Basic Auth. These are two entirely separate products on developer.dhl.com with separate registrations, separate credentials, and different base URLs — plan accordingly before you start.

## Two DHL APIs, two registrations — choose the right one first

DHL organizes its developer platform into distinct API products. The most common for Bubble founders is the Tracking API: register on developer.dhl.com, receive an API key, and use a single GET request to retrieve scan events for any DHL Express, eCommerce, or Parcel shipment. The other product founders reach for is the DHL Express API, which requires an existing DHL Express customer account, uses HTTP Basic Auth with credentials separate from your account login, and enables shipment creation and label generation — a full logistics workflow. Critically, these two products live at different base URLs and require separate registrations. A Tracking API key will not work on Express endpoints, and vice versa. This guide focuses on the Tracking API as the starting point for most Bubble apps, with an optional section on adding the Express API once your tracking integration is working.

## Before you start

- A Bubble account on any plan (tracking display); paid Bubble plan if you need Backend Workflows for webhook-based notifications
- A developer.dhl.com account — register separately for the Shipment Tracking API and optionally the DHL Express API
- DHL API key from developer.dhl.com (Tracking API registration — approval typically takes 24–48 hours)
- If using Express API: an active DHL Express customer account number and separate Express API credentials from developer.dhl.com
- The 'API Connector' plugin by Bubble installed in your app (Plugins tab → Add plugins → search 'API Connector')

## Step-by-step guide

### 1. Register for the DHL Tracking API and obtain your API key

Go to developer.dhl.com and create a developer account if you don't have one. From the dashboard, navigate to 'My Apps' and create a new application. When prompted to select API products, choose 'Shipment Tracking'. Complete the registration form with your use case description. DHL reviews applications manually — approval typically takes 24 to 48 hours, not instantly. Once approved, return to your application in the developer portal and copy the API key shown under your app's credentials. Note that this API key targets a specific environment (sandbox or production) — confirm which environment is active before you paste it into Bubble. Sandbox credentials let you test with DHL's provided sample tracking numbers without touching any live data.

**Expected result:** You have a DHL API key ready to paste into Bubble. You know whether it targets sandbox or production.

### 2. Install the API Connector and configure the DHL Tracking API

In your Bubble editor, click the Plugins tab in the left sidebar. If you don't already have the 'API Connector' plugin by Bubble, click 'Add plugins', search for 'API Connector', and install it — it is free and made by Bubble. After installation, click on the API Connector in the Plugins tab. Click 'Add another API' and name it 'DHL Tracking'. In the 'Shared headers' section, add a new header: key = `DHL-API-Key`, value = your API key from developer.dhl.com. Critically, check the checkbox labelled 'Private' next to this header. This tells Bubble to keep the key on its servers and never send it to the browser — it is the correct and secure way to store API credentials in Bubble. Set the base URL to `https://api.dhl.com/track/shipments`. Do not add a trailing slash.

```
{
  "api_name": "DHL Tracking",
  "base_url": "https://api.dhl.com/track/shipments",
  "shared_headers": [
    {
      "key": "DHL-API-Key",
      "value": "<your_api_key>",
      "private": true
    }
  ]
}
```

**Expected result:** The 'DHL Tracking' API appears in your API Connector plugin with the shared DHL-API-Key header marked Private.

### 3. Add the tracking call and run Initialize with a sandbox tracking number

Within the 'DHL Tracking' API entry in the API Connector, click 'Add a call'. Name this call 'Track Shipment'. Set the method to GET. For the URL, leave the path field blank — the base URL `https://api.dhl.com/track/shipments` is already the correct tracking endpoint. In the Parameters section, add a URL parameter: key = `trackingNumber`, value = type a sample DHL sandbox tracking number from developer.dhl.com (for example, `1234567890`). Mark this parameter as 'dynamic' so you can pass different tracking numbers from your Bubble workflows later. Set 'Use as' to 'Data' since you'll be reading tracking data, not triggering an action. Now click 'Initialize call'. Bubble sends a real GET request using your API key and the sample tracking number. For the Initialize step to succeed, Bubble must receive a valid JSON response — this is why you need a real sandbox tracking number, not a made-up string. Once the call initializes successfully, Bubble auto-maps the response structure so you can reference fields like `shipments`, `events`, and nested properties in your workflows and UI bindings.

```
GET https://api.dhl.com/track/shipments?trackingNumber=1234567890
Headers:
  DHL-API-Key: <private>
```

**Expected result:** The Initialize call succeeds. Bubble shows a preview of the DHL tracking response with `shipments`, `events`, and other fields mapped and ready to use in your app.

### 4. Parse the DHL tracking response and display events in a Repeating Group

DHL's tracking response is a nested JSON structure. The top level contains a `shipments` array. Each shipment object contains a `status` object (current overall status) and an `events` array (individual scan events in reverse chronological order). Each event has `timestamp`, `location` (with nested `address.addressLocality` and `address.countryCode`), and `description`. In Bubble, add a Repeating Group to your page and set its Type of content to the data type returned by your 'Track Shipment' call — specifically, select the 'events' sub-type. Set the data source to the result of your API workflow: use the expression `Result of step [N]'s shipments's first item's events`. Bubble uses 'first item' to navigate into the array. Inside the Repeating Group, add Text elements for each field: one for `Current cell's timestamp`, one for `Current cell's location's address's addressLocality`, and one for `Current cell's description`. Add a Workflow on page load (or on a button click) to run the 'Track Shipment' API call and store its result in a Custom State, then bind the Repeating Group to that state's events array. Test with different sandbox tracking numbers to verify all display states — in transit, customs, delivered, and exception.

```
{
  "shipments": [
    {
      "id": "1234567890",
      "service": "express",
      "origin": { "address": { "addressLocality": "Prague" } },
      "destination": { "address": { "addressLocality": "London" } },
      "status": {
        "timestamp": "2026-07-09T10:30:00",
        "location": { "address": { "addressLocality": "London", "countryCode": "GB" } },
        "status": "delivered",
        "description": "Delivered - Signed for by RECIPIENT"
      },
      "events": [
        {
          "timestamp": "2026-07-09T10:30:00",
          "location": { "address": { "addressLocality": "London", "countryCode": "GB" } },
          "description": "Delivered - Signed for by RECIPIENT"
        },
        {
          "timestamp": "2026-07-09T07:00:00",
          "location": { "address": { "addressLocality": "London", "countryCode": "GB" } },
          "description": "Out for Delivery"
        }
      ]
    }
  ]
}
```

**Expected result:** Your Repeating Group shows scan events with timestamp, city, and description. Each sandbox tracking number you test shows a different status progression.

### 5. (Optional) Add the DHL Express API for shipment creation

The DHL Express API is an entirely separate product. Before adding it, confirm you have an active DHL Express customer account and have registered separately for the Express API at developer.dhl.com. Your Express API credentials (username and password from the developer portal) are different from your DHL account login and different from your Tracking API key. In the API Connector, click 'Add another API' and name it 'DHL Express'. Set the base URL to `https://express.api.dhl.com/mydhlapi` for production, or `https://express.api.dhl.com/test/mydhlapi` for sandbox. In the Authentication section, select 'HTTP Basic Auth'. Enter your Express API username in the username field and your Express API password in the password field. Check 'Private' on both. Add a POST call named 'Create Shipment'. The Express API requires a detailed JSON body including sender address, recipient address, parcel dimensions (in cm and kg), the service product code (e.g., `P` for Express Worldwide), and your DHL account number. Initialize the call with a valid sandbox body to map the response, which includes the shipment tracking number and a label URL for PDF download.

```
{
  "api_name": "DHL Express",
  "base_url": "https://express.api.dhl.com/mydhlapi",
  "auth": "HTTP Basic Auth",
  "username": "<express_api_username>",
  "password": "<express_api_password>",
  "private": true,
  "sandbox_base_url": "https://express.api.dhl.com/test/mydhlapi"
}
```

**Expected result:** The DHL Express API entry appears separately in your API Connector, using Basic Auth. You can create a test shipment and receive a sandbox waybill number and label URL in response.

### 6. Add a scheduled tracking check for exception notifications (paid Bubble plan)

Polling the DHL Tracking API manually is fine for on-demand lookups, but real logistics workflows need proactive exception alerts — a notification when a shipment is delayed or held in customs. Bubble's Backend Workflows (available on paid plans only) let you run scheduled server-side workflows. In your Bubble app, go to the Backend Workflows section and create a new scheduled API workflow named 'Daily Tracking Check'. Inside it, build a recursive loop: search your Bubble database for all shipments with status 'In Transit', run the DHL Tracking API call for each, compare the returned latest event description to the stored description in your database, and if changed, update the database record and trigger a notification email. To schedule this workflow, use 'Schedule API Workflow' and set it to repeat every 24 hours. Each API Connector call consumes Workload Units (WU) on Bubble's pricing — for apps with many active shipments, consider reducing poll frequency or filtering to shipments expected to arrive within the next 7 days to keep WU costs manageable. Note: if you want real-time DHL webhooks instead of polling, DHL's notification service can push status changes to your Bubble Backend Workflow endpoint — set this up in your DHL developer portal and register your Bubble API endpoint URL (`https://yourapp.bubbleapps.io/api/1.1/wf/dhl-notification`). Backend Workflows and API endpoints require a paid Bubble plan.

**Expected result:** Active shipments in your database are checked daily. Staff receive email notifications when a shipment status changes, especially for exceptions like customs holds or failed delivery attempts.

## Best practices

- Always mark your DHL-API-Key header and Express API credentials as 'Private' in the API Connector — this keeps credentials server-side and prevents them from appearing in browser developer tools.
- Develop exclusively against the DHL sandbox environment until your tracking display and shipment creation workflows are fully tested. Switch to production credentials only when you're ready to go live — sandbox and production are separate environments.
- Use DHL's push notification webhooks instead of polling for high-volume apps. Each scheduled tracking check consumes Bubble Workload Units; webhooks push status changes to your Backend Workflow endpoint on-demand, which is cheaper and faster.
- Set Privacy rules on any Bubble Data Type you create to store shipment or tracking data. Bubble's default 'everyone can see' setting can expose shipping details to unauthenticated users if left unconfigured.
- Store your DHL API key and Express credentials in the API Connector's shared headers only — never store them in Bubble's database, in page inputs, or as URL parameters. Private headers are encrypted at rest.
- Limit your scheduled tracking check workflow to shipments that are actively in transit. Polling delivered or cancelled shipments wastes WU with no value — filter your database search with a status condition before looping.
- Re-initialize your API Connector call after any DHL API response structure change or after you add a new field to your query parameters. Bubble's field mapping is based on the Initialize response snapshot — stale mappings cause missing fields in your UI.
- For multi-tenant logistics platforms where different users have different DHL accounts, store per-user Express API credentials in encrypted Bubble database fields and construct dynamic API calls inside Backend Workflows rather than hardcoding one set of credentials in the API Connector.

## Use cases

### E-commerce order tracking dashboard

Display live DHL scan events — in transit, customs clearance, out for delivery, delivered — inside a Bubble customer portal so buyers can track their orders without leaving your app or visiting dhl.com.

Prompt example:

```
Build a Bubble page with an input field for a DHL tracking number. When the user submits, call the DHL Tracking API, then show the resulting scan events in a Repeating Group with the timestamp, location city, and event description for each scan.
```

### Logistics operations portal with multi-shipment monitoring

Pull DHL tracking data for all active orders stored in your Bubble database and surface exception events (customs holds, delivery failures) in an internal dashboard, triggering email notifications to ops staff when a package status changes.

Prompt example:

```
Build a Bubble backend workflow that runs daily, loops through all orders with status 'In Transit' in our database, calls the DHL Tracking API for each tracking number, and updates the order record with the latest scan event description and timestamp.
```

### DHL Express shipment creation (Express API)

Allow marketplace sellers in your Bubble app to book DHL Express shipments, generate PDF shipping labels, and receive waybill numbers — all without leaving your platform.

Prompt example:

```
Add a Bubble workflow triggered by a 'Create Shipment' button. It should call the DHL Express API with the sender address, recipient address, parcel dimensions, and our DHL account number, then save the returned waybill number and label URL to the order record.
```

## Troubleshooting

### API Connector Initialize call fails with 'There was an issue setting up your call'

Cause: The Initialize step requires a real successful API response. This error usually means the tracking number you used for testing doesn't exist in DHL's sandbox, the base URL has a typo or trailing slash, or the DHL-API-Key header value is incorrect.

Solution: Copy a valid sandbox tracking number directly from developer.dhl.com's documentation page. Confirm your base URL is exactly `https://api.dhl.com/track/shipments` with no trailing slash. Double-check that the DHL-API-Key header value matches your approved API key.

### Tracking call returns 401 Unauthorized

Cause: The DHL API key is either invalid, pending approval, or you are calling the production endpoint with sandbox credentials (or vice versa).

Solution: Log in to developer.dhl.com and confirm your application status shows 'Approved', not 'Pending'. Check which environment (sandbox or production) your key targets. If the key was recently generated, wait for the 24–48 hour approval window before testing against production.

### Tracking call returns 404 for a valid DHL tracking number

Cause: The Tracking API endpoint doesn't use a path parameter — the tracking number must be passed as a URL query parameter named `trackingNumber`, not appended to the URL path.

Solution: In your API Connector call configuration, verify the tracking number is in the Parameters section as `trackingNumber=<number>`, not appended as `/track/shipments/1234567890`. The base URL already points to the correct endpoint; the tracking number is always a query parameter.

```
GET https://api.dhl.com/track/shipments?trackingNumber=1234567890
```

### DHL Express API returns 401 even with correct-looking credentials

Cause: The Express API username and password from the developer portal are NOT the same as your DHL account login credentials. Using your DHL.com login on the Express API endpoint always returns 401.

Solution: Return to developer.dhl.com, open your Express API application, and copy the API-specific credentials (not your portal login, not your DHL shipping account login — the credentials listed under your application's API access section).

### Repeating Group shows no events even though the API call succeeds

Cause: The DHL tracking response nests events inside `shipments[0].events`. If the Repeating Group data source is bound to the full result instead of drilling into the first shipment's events array, Bubble returns nothing to display.

Solution: Set the Repeating Group data source to `[API result]'s shipments's first item's events`. Verify in the API Connector preview that `shipments` contains at least one entry with an `events` array — some sandbox tracking numbers return a shipment with an empty events array until status progresses.

### Backend Workflow option is not available when trying to set up scheduled tracking checks

Cause: Backend Workflows (API Workflows) are only available on paid Bubble plans. The free Bubble plan does not include access to the Backend Workflows section.

Solution: Upgrade to a paid Bubble plan (Starter or higher) to unlock Backend Workflows. On a free plan, tracking status checks can only be triggered by user actions, not scheduled server-side. As an alternative, use a free external service like Make.com to schedule the DHL API call and send results to your Bubble app via a Bubble Data API call.

## Frequently asked questions

### Do I need a DHL customer account to use the Tracking API?

No. The DHL Tracking API is available to any developer who registers at developer.dhl.com — you don't need an existing DHL shipping account. It tracks shipments across DHL Express, DHL eCommerce, and DHL Parcel using their tracking numbers. The DHL Express API (for creating shipments and labels) does require an active DHL Express customer account with an account number.

### Why is the DHL API key not working immediately after I created my application?

DHL reviews Tracking API applications manually, and approval typically takes 24 to 48 hours. The API key is not active until the application status changes to 'Approved' in developer.dhl.com. During this waiting period, test your Bubble API Connector configuration using sandbox tracking numbers from DHL's documentation — the Initialize step and response structure mapping can be done before your production key is approved.

### Can I display DHL tracking data without a paid Bubble plan?

Yes. The DHL Tracking API and Bubble's API Connector work together on Bubble's free plan for on-demand tracking lookups. What requires a paid Bubble plan is Backend Workflows — specifically, scheduling automatic daily tracking checks or receiving DHL webhook push notifications for status changes. If you only need a 'Track my order' button that fetches status on click, the free Bubble plan is sufficient.

### How do I handle the deeply nested DHL tracking response in Bubble?

DHL's response structure is `shipments → [0] → events → [each event] → description / timestamp / location`. In Bubble, after running Initialize call, navigate to the events using: `result's shipments's first item's events`. Use this expression as your Repeating Group data source. For individual event fields inside the Repeating Group, use `Current cell's description`, `Current cell's timestamp`, and `Current cell's location's address's addressLocality` for the city name.

### Can I receive real-time DHL status updates instead of polling?

Yes, DHL's Shipment Event Notification service can push tracking updates to a URL you specify — your Bubble Backend Workflow endpoint. Set up the endpoint in Bubble's Backend Workflows section (paid plan required), then register the URL in your DHL developer account's notification settings. DHL pushes an event JSON payload to your endpoint whenever a shipment status changes, which is more efficient than scheduled polling.

### My team at RapidDev works with DHL integrations frequently. What if our Bubble setup is more complex than this guide covers?

If you're building a logistics portal with custom DHL Express shipment creation, multi-warehouse routing, or integrating DHL tracking into an existing Bubble database schema, RapidDev's team has built complex Bubble apps with carrier API integrations like this. Reach out for a free scoping call at rapidevelopers.com/contact.

---

Source: https://www.rapidevelopers.com/bubble-integrations/dhl-api
© RapidDev — https://www.rapidevelopers.com/bubble-integrations/dhl-api
