# How to Integrate Replit with DHL API

- Tool: Replit
- Difficulty: Intermediate
- Time required: 30 minutes
- Last updated: March 2026

## TL;DR

To integrate Replit with the DHL API, register a DHL developer account, generate an API key for the Shipment Tracking or Express APIs, store it in Replit Secrets (lock icon 🔒), and call DHL's REST APIs from Python or Node.js to track shipments and get express quotes. DHL provides the strongest international shipping coverage, making it ideal for global e-commerce backends.

## Why Connect Replit to DHL?

DHL is the world's largest international logistics company, operating in over 220 countries. For e-commerce platforms and order management systems built on Replit, the DHL API enables real-time shipment tracking, rate calculations, label generation, and pickup scheduling. If your customers or products cross international borders, DHL's API coverage is unmatched compared to domestic-focused carriers.

The DHL developer portal (developer.dhl.com) provides access to several distinct APIs: the Shipment Tracking API for tracking parcels by waybill number across all DHL service lines (Express, eCommerce, Parcel), the Express API for creating shipments with DHL Express and generating labels, and the eCommerce API for lower-cost international parcel services. Each API has its own authentication and endpoint structure.

Replit is well-suited for building DHL integrations because it provides always-on deployment for webhook receivers, supports both Python and Node.js for calling DHL's REST endpoints, and makes it easy to test API calls in the Shell before deploying. Store your DHL API key in Replit Secrets (lock icon 🔒) to keep it out of your codebase and safe from Replit's built-in Secret Scanner.

## Before you start

- A Replit account with a Python or Node.js project created
- A DHL developer account registered at developer.dhl.com
- An active DHL business account (required for Express shipment creation — tracking API is available without a business account)
- Basic familiarity with REST APIs and HTTP authentication headers
- Node.js 18+ or Python 3.10+ (both available on Replit by default)

## Step-by-step guide

### 1. Register at DHL Developer Portal and Get API Keys

Navigate to developer.dhl.com and create a developer account using your email address. Once registered, you will see the API catalog listing all available DHL APIs.

For tracking shipments, subscribe to the 'DHL Shipment Tracking' API — this is free for tracking queries and does not require a DHL business account. Click 'Subscribe' and choose the 'Free' plan. After subscribing, go to your account dashboard and find the 'My Applications' section. Create a new application and select the Shipment Tracking API. Your API key (also called a DHL-API-Key) will be displayed on the application page.

For creating shipments with DHL Express, you will need to subscribe to the 'DHL Express – MyDHL API'. This API requires an active DHL Express account number (account number from your DHL billing). The Express API uses Basic Authentication with your DHL account credentials rather than a standalone API key.

Copy your API key from the developer portal — it will look like a long alphanumeric string. You will use this as the DHL-API-Key header in all tracking requests.

**Expected result:** You have a DHL developer account, a subscribed application, and an API key copied from the developer portal dashboard.

### 2. Store DHL Credentials in Replit Secrets

Open your Replit project and click the lock icon 🔒 in the left sidebar to open the Secrets pane. Add your DHL credentials:

- Key: DHL_API_KEY — Value: your DHL API key from the developer portal
- Key: DHL_ACCOUNT_NUMBER — Value: your DHL Express account number (if using Express shipment creation)

For the Express API (which uses Basic Auth), you may also need:
- Key: DHL_EXPRESS_USER — Value: your DHL Express username
- Key: DHL_EXPRESS_PASSWORD — Value: your DHL Express password

Click 'Add Secret' after each entry. In Python, access these with os.environ['DHL_API_KEY']. In Node.js, use process.env.DHL_API_KEY.

DHL API keys grant access to tracking data for any shipment — treat them with the same care as any production API credential. Replit's Secret Scanner will alert you if a key is accidentally written to a code file.

**Expected result:** DHL_API_KEY and other DHL credentials appear in Replit Secrets with masked values.

### 3. Track Shipments with Python

The DHL Shipment Tracking API v2 is straightforward — send a GET request to https://api-eu.dhl.com/track/shipments with the trackingNumber query parameter and the DHL-API-Key header. The response returns a detailed tracking object with events, estimated delivery, and current status.

The API supports tracking across all DHL service lines (DHL Express, DHL eCommerce, DHL Parcel) using the same endpoint. Multiple tracking numbers can be queried in a single request by passing them as a comma-separated string.

The Python code below implements tracking, batch tracking, and event parsing utilities. It also handles the most common API responses including not-found errors and incomplete data scenarios.

```
import os
import requests
from typing import Optional

DHL_API_KEY = os.environ["DHL_API_KEY"]
BASE_URL = "https://api-eu.dhl.com"

HEADERS = {
    "DHL-API-Key": DHL_API_KEY,
    "Accept": "application/json"
}

def track_shipment(tracking_number: str) -> dict:
    """
    Track a DHL shipment by waybill/tracking number.
    Returns the full tracking response including events and status.
    """
    params = {"trackingNumber": tracking_number}
    response = requests.get(
        f"{BASE_URL}/track/shipments",
        headers=HEADERS,
        params=params
    )
    response.raise_for_status()
    return response.json()

def track_multiple(tracking_numbers: list) -> dict:
    """
    Track multiple shipments in one request (up to 10 numbers).
    Pass a list of tracking number strings.
    """
    numbers_str = ",".join(tracking_numbers[:10])  # API limit: 10 per request
    params = {"trackingNumber": numbers_str}
    response = requests.get(
        f"{BASE_URL}/track/shipments",
        headers=HEADERS,
        params=params
    )
    response.raise_for_status()
    return response.json()

def get_latest_status(tracking_number: str) -> Optional[dict]:
    """
    Get the latest tracking event and overall status for a shipment.
    Returns None if the tracking number is not found.
    """
    try:
        data = track_shipment(tracking_number)
        shipments = data.get("shipments", [])
        if not shipments:
            return None
        shipment = shipments[0]
        events = shipment.get("events", [])
        latest_event = events[0] if events else {}
        return {
            "tracking_number": tracking_number,
            "status": shipment.get("status", {}).get("status"),
            "description": shipment.get("status", {}).get("description"),
            "estimated_delivery": shipment.get("estimatedTimeOfDelivery"),
            "latest_location": latest_event.get("location", {}).get("address", {}).get("addressLocality"),
            "latest_timestamp": latest_event.get("timestamp"),
            "latest_description": latest_event.get("description"),
            "event_count": len(events)
        }
    except requests.exceptions.HTTPError as e:
        if e.response.status_code == 404:
            return None
        raise

if __name__ == "__main__":
    # Replace with a real DHL tracking number for testing
    test_tracking = "1234567890"
    result = get_latest_status(test_tracking)
    if result:
        print(f"Tracking {test_tracking}:")
        print(f"  Status: {result['status']} — {result['description']}")
        print(f"  Latest location: {result['latest_location']}")
        print(f"  Estimated delivery: {result['estimated_delivery']}")
    else:
        print(f"Tracking number {test_tracking} not found")
```

**Expected result:** Running the script with a valid DHL tracking number prints the shipment status, latest location, and estimated delivery date.

### 4. Build a Node.js Tracking Proxy with Express

For web applications, a Node.js Express server acts as a secure proxy between your frontend and the DHL API. This is important because exposing your DHL API key in browser-side JavaScript would allow anyone to make unlimited tracking queries with your credentials.

The Express server below exposes a clean /track/:waybill endpoint that your frontend can call. It also includes a /rates endpoint stub for integrating the DHL Express rates API, which requires Basic Authentication with your DHL Express account credentials instead of the standard API key.

Install axios with npm install express axios in the Replit Shell. The server binds to 0.0.0.0:3000 for Replit's port routing. For production deployment, use Autoscale to handle variable tracking query loads, especially if your storefront has traffic spikes around shipping cut-off times.

```
const express = require('express');
const axios = require('axios');

const app = express();
app.use(express.json());

const DHL_API_KEY = process.env.DHL_API_KEY;
const DHL_EXPRESS_USER = process.env.DHL_EXPRESS_USER;
const DHL_EXPRESS_PASSWORD = process.env.DHL_EXPRESS_PASSWORD;
const DHL_ACCOUNT_NUMBER = process.env.DHL_ACCOUNT_NUMBER;

const trackingClient = axios.create({
  baseURL: 'https://api-eu.dhl.com',
  headers: {
    'DHL-API-Key': DHL_API_KEY,
    Accept: 'application/json'
  }
});

const expressClient = axios.create({
  baseURL: 'https://express.api.dhl.com/mydhlapi',
  auth: {
    username: DHL_EXPRESS_USER,
    password: DHL_EXPRESS_PASSWORD
  },
  headers: { Accept: 'application/json' }
});

// GET /track/:waybill — track a DHL shipment
app.get('/track/:waybill', async (req, res) => {
  try {
    const response = await trackingClient.get('/track/shipments', {
      params: { trackingNumber: req.params.waybill }
    });
    const shipments = response.data.shipments || [];
    if (!shipments.length) {
      return res.status(404).json({ error: 'Shipment not found' });
    }
    const shipment = shipments[0];
    res.json({
      trackingNumber: req.params.waybill,
      status: shipment.status?.status,
      description: shipment.status?.description,
      estimatedDelivery: shipment.estimatedTimeOfDelivery,
      events: (shipment.events || []).map(e => ({
        timestamp: e.timestamp,
        location: e.location?.address?.addressLocality,
        description: e.description
      }))
    });
  } catch (err) {
    const status = err.response?.status || 500;
    res.status(status).json({ error: err.response?.data?.detail || err.message });
  }
});

// POST /rates — get DHL Express shipping rates
// Body: { fromCountry, toCountry, weight, length, width, height, plannedShipDate }
app.post('/rates', async (req, res) => {
  const { fromCountry, toCountry, weight, length, width, height, plannedShipDate } = req.body;
  try {
    const response = await expressClient.get('/rates', {
      params: {
        accountNumber: DHL_ACCOUNT_NUMBER,
        originCountryCode: fromCountry,
        destinationCountryCode: toCountry,
        weight,
        length,
        width,
        height,
        plannedShippingDateAndTime: plannedShipDate || new Date().toISOString()
      }
    });
    res.json(response.data);
  } catch (err) {
    res.status(err.response?.status || 500).json({ error: err.message });
  }
});

app.listen(3000, '0.0.0.0', () => {
  console.log('DHL API proxy server running on port 3000');
});
```

**Expected result:** The server starts on port 3000. A GET request to /track/1234567890 returns structured tracking data for the waybill.

## Best practices

- Store DHL_API_KEY and any Express credentials in Replit Secrets (lock icon 🔒) — never hardcode them in source files or expose them to frontend clients.
- Use separate API clients for the DHL Tracking API (DHL-API-Key header) and the DHL Express API (Basic Auth) — mixing authentication methods will cause 401/403 errors.
- Batch tracking requests using comma-separated tracking numbers (up to 10 per request) to stay within rate limits when processing large order volumes.
- Cache tracking results for 15-30 minutes in a database or key-value store — shipment status rarely changes more frequently than that, and caching reduces API consumption.
- Use the DHL sandbox (api-mock.dhl.com) for development and testing — switch to production (api-eu.dhl.com) only when ready to process real shipments.
- Always handle 404 responses gracefully for tracking queries — not-found does not necessarily mean an invalid number, just that the shipment is not yet in the system.
- Deploy with Autoscale for customer-facing tracking features; use Reserved VM if your integration processes continuous inbound webhooks from DHL eCommerce.
- Log raw API responses during initial integration to understand the exact response structure before building parsing logic — DHL responses can vary between API versions.

## Use cases

### Order Tracking Page Backend

Build a Replit-hosted API that accepts a DHL waybill number from your storefront and returns the full shipment tracking history — including timestamps, locations, and delivery status. Your frontend calls this proxy endpoint rather than DHL directly, keeping your API key hidden from browser users.

Prompt example:

```
Build a Flask server with a GET /track/:waybill endpoint that fetches tracking events from the DHL Shipment Tracking API using DHL_API_KEY from Replit Secrets and returns the events as structured JSON.
```

### Automated Shipping Rate Calculator

Integrate DHL Express rates into your checkout flow so customers see live shipping costs before placing an order. Your Replit backend queries DHL's Express rates API with package dimensions, weight, origin, and destination, then returns available service options and prices.

Prompt example:

```
Create a Node.js Express server with a POST /shipping-rates endpoint that accepts origin, destination, weight, and dimensions in the request body, queries the DHL Express Rates API, and returns available shipping options with estimated prices and delivery times.
```

### Bulk Shipment Status Sync

Build a scheduled Replit script that reads open order IDs and DHL waybill numbers from your database, queries the DHL Tracking API for each in batches, and updates the order status in your system. This keeps your customer-facing order portal in sync with real DHL delivery data without customer-triggered polling.

Prompt example:

```
Write a Python script that reads a list of DHL tracking numbers from a CSV file, queries the DHL Tracking API for each number with a 0.5-second delay between requests, and writes the latest shipment status and estimated delivery date back to the CSV.
```

## Troubleshooting

### API returns 401 Unauthorized with 'Invalid API Key' message

Cause: The DHL-API-Key header value is incorrect, the API key belongs to a different environment (sandbox vs production), or the key has not been associated with a subscribed application in the developer portal.

Solution: Log in to developer.dhl.com and verify your application is active and subscribed to the Shipment Tracking API. Copy the API key directly from the application page — do not type it manually. Ensure DHL_API_KEY in Replit Secrets matches exactly, with no extra spaces or newline characters.

```
# Python: verify API key is loaded correctly
api_key = os.environ.get('DHL_API_KEY', '')
print(f'API key length: {len(api_key)}, starts with: {api_key[:8]}...')
# Should print a non-zero length and a recognizable prefix
```

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

Cause: The tracking number may be for a DHL service line not covered by the standard Tracking API, the shipment is too new (not yet scanned into the system), or the number format is incorrect.

Solution: DHL tracking numbers vary by service line — Express waybills are typically 10 digits starting with a letter, Parcel numbers follow a different format. Verify the format for your service line in the DHL developer documentation. New shipments may take 2-4 hours to appear in the tracking API after label creation.

```
# Python: check response for additional error details
try:
    response = requests.get(url, headers=HEADERS, params=params)
    print('Status:', response.status_code)
    print('Response:', response.json())
except requests.exceptions.HTTPError as e:
    print('HTTP error:', e.response.json())
```

### DHL Express API returns 403 Forbidden for rate requests

Cause: The Express API (MyDHL API) uses Basic Auth with your DHL account username and password, not the API key. Using the API key in the Authorization header for Express endpoints will cause a 403.

Solution: The DHL Express (MyDHL API) and the Tracking API use different authentication mechanisms. Configure a separate axios/requests client for Express with Basic Auth credentials (DHL_EXPRESS_USER and DHL_EXPRESS_PASSWORD from Replit Secrets). The tracking API uses the DHL-API-Key header, while Express uses standard HTTP Basic Authentication.

```
# Python: separate auth for Express vs Tracking APIs
import requests
from requests.auth import HTTPBasicAuth

# Tracking API — API key header
tracking_headers = {'DHL-API-Key': os.environ['DHL_API_KEY']}

# Express API — Basic Auth
express_auth = HTTPBasicAuth(os.environ['DHL_EXPRESS_USER'], os.environ['DHL_EXPRESS_PASSWORD'])
```

### Rate limit errors (429) when tracking many shipments

Cause: The free DHL Tracking API plan allows 250 requests per minute. Bulk tracking operations that exceed this limit will be throttled.

Solution: Implement rate limiting in your code — process tracking numbers in batches of 10 (the API allows up to 10 comma-separated numbers per request) and add a delay between batches. Apply for a higher-tier API plan in the developer portal if you consistently hit rate limits.

```
import time

def batch_track(tracking_numbers: list, batch_size: int = 10) -> list:
    results = []
    for i in range(0, len(tracking_numbers), batch_size):
        batch = tracking_numbers[i:i + batch_size]
        data = track_multiple(batch)
        results.extend(data.get('shipments', []))
        if i + batch_size < len(tracking_numbers):
            time.sleep(0.25)  # Stay under 250 req/min
    return results
```

## Frequently asked questions

### How do I store my DHL API key in Replit?

Click the lock icon 🔒 in the Replit left sidebar to open Secrets. Add DHL_API_KEY with your API key value from the DHL developer portal. Access it in Python with os.environ['DHL_API_KEY'] and in Node.js with process.env.DHL_API_KEY. Never paste the key directly into your code files.

### Does the DHL Tracking API require a DHL business account?

No. The DHL Shipment Tracking API is available on a free plan at developer.dhl.com and does not require a DHL business shipping account. You can track any DHL shipment worldwide using just the API key. Creating shipments and generating labels with the DHL Express API does require an active DHL business account with an account number.

### How do I track a DHL shipment from Replit?

Store your DHL_API_KEY in Replit Secrets, then make a GET request to https://api-eu.dhl.com/track/shipments?trackingNumber=YOUR_NUMBER with the DHL-API-Key header. The response returns the shipment status, all tracking events with timestamps and locations, and the estimated delivery date. Use the Python requests library or Node.js axios for the HTTP call.

### Can I use DHL to create shipping labels from Replit?

Yes, through the DHL Express MyDHL API, which supports creating shipments, generating labels, scheduling pickups, and getting rates. This API requires a DHL Express business account and uses Basic Authentication with your DHL Express username and password — separate from the API key used for tracking. Subscribe to the 'DHL Express – MyDHL API' in the developer portal.

### Why does DHL tracking return empty events for a new shipment?

New DHL shipments may take 2-4 hours after label creation before they appear in the Tracking API. The status will show as 'pre-transit' or similar until the first scan occurs at a DHL facility. This is normal behavior — implement retry logic with exponential backoff or check again after a few hours.

---

Source: https://www.rapidevelopers.com/replit-integration/dhl-api
© RapidDev — https://www.rapidevelopers.com/replit-integration/dhl-api
