Skip to main content
RapidDev - Software Development Agency
bolt-ai-integrationsBolt Chat + API Route

How to Integrate Bolt.new with DHL API

DHL's REST APIs let your Bolt.new app track shipments, calculate shipping rates, and generate labels. Authentication is simple: an API key in the request header. The free developer sandbox includes test credentials for all three core APIs. Build your tracking dashboard and rate calculator in Bolt's WebContainer preview, then switch to production credentials when deploying.

What you'll learn

  • How to register for the DHL developer portal and create a free sandbox application
  • How to track DHL shipments using the Shipment Tracking API
  • How to calculate shipping rates with the Express Rate Finding API
  • How to generate DHL shipping labels via the Shipment and Tracking API
  • How to build a multi-shipment tracking dashboard that monitors packages in real time
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Intermediate12 min read20 minutesOtherApril 2026RapidDev Engineering Team
TL;DR

DHL's REST APIs let your Bolt.new app track shipments, calculate shipping rates, and generate labels. Authentication is simple: an API key in the request header. The free developer sandbox includes test credentials for all three core APIs. Build your tracking dashboard and rate calculator in Bolt's WebContainer preview, then switch to production credentials when deploying.

DHL API in Bolt.new: Tracking, Rates, and Labels for Shipping Apps

DHL offers REST APIs for tracking, rate calculation, and label creation covering their global express network. Authentication is a single API key in a header — no OAuth complexity. The free developer sandbox at developer.dhl.com provides instant test credentials, making this one of the simpler logistics integrations to build.

The three core APIs are: Shipment Tracking (query status by waybill number), Express Rate Finding (get quotes for origin/destination/weight), and Shipment API (create shipments and generate PDF labels). All use the same DHL-API-Key header authentication and the same base URL structure.

DHL tracking uses polling rather than webhooks — you query the API to get the latest status rather than receiving push notifications. This means the full integration works in Bolt's WebContainer preview without deployment.

Integration method

Bolt Chat + API Route

DHL APIs use simple API key authentication — pass your key in the DHL-API-Key header on every request. Build Next.js API routes that proxy calls to DHL's endpoints, keeping your API key server-side. Outbound API calls (tracking, rate quotes) work in Bolt's WebContainer preview. DHL doesn't use webhooks for tracking updates, so there are no incoming connection requirements.

Prerequisites

  • A Bolt.new account with a Next.js project created
  • A DHL developer account at developer.dhl.com (free registration)
  • A DHL sandbox application created in the developer portal to get test API credentials
  • For label generation: a DHL Express business account (separate from the developer account)
  • Basic understanding of shipping terminology (waybill, service level, dimensions)

Step-by-step guide

1

Register on DHL Developer Portal and Create a Sandbox Application

Go to developer.dhl.com and click Sign Up. Registration requires a name and email address — there's no approval process for sandbox access, so credentials are available immediately after confirming your email. After logging in, click 'Create App' in the My Apps section. Name your application and select which APIs you want to enable: start with 'DHL Express - MyDHL API' for rate finding and shipment creation, and 'Shipment Tracking' for the tracking API. Each API has both a Sandbox and Production environment. After creating your app, the dashboard shows your API key for each environment. The sandbox and production API keys are different strings. Copy your sandbox API key — you'll use this for all development and testing. Switch to your production key only when you've tested everything and are ready to go live. For the Shipment Tracking API, you'll also see a sandbox test waybill number in the documentation — use this to test tracking responses without needing a real shipment. The number returns a realistic tracking history with multiple scan events.

Pro tip: The DHL developer portal has separate API keys for each API product (Tracking, Express). If your app needs both, note that you may have different keys per product. Check the API reference for each API to confirm the correct authentication header name.

Expected result: You have a DHL developer account, a sandbox application created, and your sandbox API key. You've noted a test waybill number from the documentation for testing.

2

Configure Environment Variables and Install HTTP Client

DHL's APIs are straightforward to call with standard fetch() — no SDK required. The authentication is a single header: 'DHL-API-Key: your_api_key'. Add your sandbox API key to your Bolt.new project's .env file. The API key must be server-side only (no NEXT_PUBLIC_ prefix). While DHL's API key is simpler than OAuth credentials, it still grants API quota access and should not be exposed in client-side code where it could be scraped and abused by others. For the DHL API base URLs: the Shipment Tracking API uses api-eu.dhl.com, and the Express (MyDHL) API for rate finding and label creation uses express.api.dhl.com. These are the production URLs — the sandbox uses the same base URLs but with sandbox API keys that automatically route requests to test environments.

Bolt.new Prompt

Create a lib/dhl.ts file that exports a dhlRequest(endpoint, options) helper function. The function should prepend the DHL API base URL (from DHL_API_BASE_URL env var), add the 'DHL-API-Key' header using DHL_API_KEY env var, handle response errors (including parsing DHL's error response format), and return the parsed JSON. Use TypeScript.

Paste this in Bolt.new chat

.env
1# .env file additions
2# DHL API credentials server-side only, never NEXT_PUBLIC_
3DHL_API_KEY=your_sandbox_api_key_here
4DHL_TRACKING_API_BASE=https://api-eu.dhl.com
5DHL_EXPRESS_API_BASE=https://express.api.dhl.com/mydhlapi
6# Use 'test' for sandbox, 'production' for live
7DHL_ENVIRONMENT=test

Pro tip: DHL's sandbox API key automatically routes to test data when ENVIRONMENT=test — you don't need separate base URLs. Switch to your production API key and set DHL_ENVIRONMENT=production when going live.

Expected result: lib/dhl.ts is created with a request helper. Environment variables are set. TypeScript compiles without errors.

3

Build the Shipment Tracking API Route

The DHL Shipment Tracking API accepts a waybill number (tracking number) and returns the current status plus a full event history of every scan the package has received. The endpoint is: GET /track/shipments?trackingNumber={waybillNumber}. The response includes: the shipment's current status (transit, in-transit, delivered, failure), the estimated delivery date, the origin and destination, and an events array where each event has a timestamp, location, description, and service area code. For a tracking dashboard, normalize the response to extract the most useful fields: current status, latest event location and description, estimated delivery date, and the full event timeline sorted newest-first. Multiple tracking numbers can be queried in a single request by comma-separating them: ?trackingNumber=1234,5678.

Bolt.new Prompt

Create a /api/dhl/track route that accepts a 'waybill' query parameter, calls the DHL Shipment Tracking API (GET /track/shipments), and returns: currentStatus, estimatedDelivery, originLocation, destinationLocation, and an events array with timestamp, location, description, and remark for each event. Handle the case where the tracking number is not found. Use the dhlRequest helper from lib/dhl.ts.

Paste this in Bolt.new chat

app/api/dhl/track/route.ts
1// app/api/dhl/track/route.ts
2import { NextResponse } from 'next/server';
3
4async function dhlRequest(url: string) {
5 const response = await fetch(url, {
6 headers: {
7 'DHL-API-Key': process.env.DHL_API_KEY ?? '',
8 'Accept': 'application/json',
9 },
10 });
11 if (!response.ok) {
12 const error = await response.json().catch(() => ({}));
13 throw Object.assign(new Error('DHL API error'), { status: response.status, body: error });
14 }
15 return response.json();
16}
17
18export async function GET(request: Request) {
19 const url = new URL(request.url);
20 const waybill = url.searchParams.get('waybill')?.trim();
21
22 if (!waybill) {
23 return NextResponse.json({ error: 'waybill query parameter is required' }, { status: 400 });
24 }
25
26 try {
27 const trackingUrl = `${process.env.DHL_TRACKING_API_BASE}/track/shipments?trackingNumber=${encodeURIComponent(waybill)}`;
28 const data = await dhlRequest(trackingUrl);
29
30 const shipment = data?.shipments?.[0];
31 if (!shipment) {
32 return NextResponse.json({ error: 'Shipment not found' }, { status: 404 });
33 }
34
35 const normalized = {
36 waybill,
37 status: shipment.status?.status ?? 'unknown',
38 description: shipment.status?.description ?? '',
39 estimatedDelivery: shipment.estimatedTimeOfDelivery ?? null,
40 origin: {
41 name: shipment.origin?.address?.addressLocality ?? '',
42 countryCode: shipment.origin?.address?.countryCode ?? '',
43 },
44 destination: {
45 name: shipment.destination?.address?.addressLocality ?? '',
46 countryCode: shipment.destination?.address?.countryCode ?? '',
47 },
48 events: (shipment.events ?? []).map((event: Record<string, unknown>) => ({
49 timestamp: event.timestamp,
50 location: (event.location as Record<string, unknown>)?.address
51 ? `${((event.location as Record<string, unknown>).address as Record<string, unknown>).addressLocality}, ${((event.location as Record<string, unknown>).address as Record<string, unknown>).countryCode}`
52 : 'Unknown',
53 description: event.description,
54 remark: event.remark ?? '',
55 })),
56 };
57
58 return NextResponse.json(normalized);
59 } catch (error: unknown) {
60 const err = error as { status?: number };
61 if (err.status === 404) {
62 return NextResponse.json({ error: 'Shipment not found' }, { status: 404 });
63 }
64 console.error('DHL tracking error:', error);
65 return NextResponse.json({ error: 'Failed to fetch tracking data' }, { status: 500 });
66 }
67}

Pro tip: Test with DHL's sandbox test waybill numbers from their documentation page. These return realistic tracking events without needing an actual shipment. Common test numbers include numbers like 1234567890 — check the current sandbox documentation for valid test values.

Expected result: The /api/dhl/track?waybill=[number] endpoint returns normalized tracking data. Test in Bolt's WebContainer preview using a sandbox test waybill number.

4

Build the Rate Calculator API Route

The DHL Express Rate Finding API (part of MyDHL API) returns available shipping services, their prices, and estimated delivery dates for a given origin/destination/package combination. The endpoint is: POST /rates to the express.api.dhl.com base URL. The request body requires: an account number (your DHL Express account, or a sandbox account number from the developer portal), the planned shipment date, origin and destination address details (country code, postal code, city), and package details (weight in kg, dimensions in cm). The response lists available service products (EXPRESS_WORLDWIDE, EXPRESS_9_00, EXPRESS_12_00, EXPRESS_9_00_DOC) with total charge, currency, and commitment date for each. Present these as a comparison table so users can choose based on price vs. delivery speed.

Bolt.new Prompt

Create a /api/dhl/rates route (POST) that accepts originCountry, originPostalCode, originCity, destinationCountry, destinationPostalCode, destinationCity, weightKg, and packageDimensions (length, width, height in cm). Call the DHL Express Rate Finding API and return an array of available services with: productName, serviceCode, totalCharge, currency, and deliveryDate. Sort by total charge ascending.

Paste this in Bolt.new chat

app/api/dhl/rates/route.ts
1// app/api/dhl/rates/route.ts
2import { NextResponse } from 'next/server';
3
4export async function POST(request: Request) {
5 try {
6 const body = await request.json();
7 const {
8 originCountry, originPostalCode, originCity,
9 destinationCountry, destinationPostalCode, destinationCity,
10 weightKg, packageDimensions,
11 } = body;
12
13 // Shipment date must be today or future, in ISO format
14 const plannedDate = new Date();
15 plannedDate.setHours(14, 0, 0, 0); // 2pm local time
16 const plannedShipmentDateAndTime = plannedDate.toISOString();
17
18 const rateRequest = {
19 customerDetails: {
20 shipperDetails: {
21 postalCode: originPostalCode,
22 cityName: originCity,
23 countryCode: originCountry,
24 },
25 receiverDetails: {
26 postalCode: destinationPostalCode,
27 cityName: destinationCity,
28 countryCode: destinationCountry,
29 },
30 },
31 accounts: [{
32 typeCode: 'shipper',
33 number: process.env.DHL_ACCOUNT_NUMBER ?? 'TEST_ACCOUNT',
34 }],
35 plannedShipmentDateAndTime,
36 unitOfMeasurement: 'metric',
37 isCustomsDeclarable: false,
38 packages: [{
39 weight: Number(weightKg),
40 dimensions: {
41 length: Number(packageDimensions?.length ?? 20),
42 width: Number(packageDimensions?.width ?? 15),
43 height: Number(packageDimensions?.height ?? 10),
44 },
45 }],
46 };
47
48 const response = await fetch(`${process.env.DHL_EXPRESS_API_BASE}/rates`, {
49 method: 'POST',
50 headers: {
51 'DHL-API-Key': process.env.DHL_API_KEY ?? '',
52 'Content-Type': 'application/json',
53 'Accept': 'application/json',
54 },
55 body: JSON.stringify(rateRequest),
56 });
57
58 if (!response.ok) {
59 const error = await response.json();
60 return NextResponse.json({ error: error?.detail ?? 'Rate request failed' }, { status: response.status });
61 }
62
63 const data = await response.json();
64 const rates = (data?.products ?? []).map((product: Record<string, unknown>) => ({
65 productName: product.productName,
66 serviceCode: product.productCode,
67 totalCharge: (product.totalPrice as Array<Record<string, unknown>>)?.[0]?.price ?? 0,
68 currency: (product.totalPrice as Array<Record<string, unknown>>)?.[0]?.priceCurrency ?? 'USD',
69 deliveryDate: (product.deliveryCapabilities as Record<string, unknown>)?.estimatedDeliveryDateAndTime ?? null,
70 })).sort((a: Record<string, unknown>, b: Record<string, unknown>) => Number(a.totalCharge) - Number(b.totalCharge));
71
72 return NextResponse.json({ rates });
73 } catch (error) {
74 console.error('DHL rates error:', error);
75 return NextResponse.json({ error: 'Failed to calculate rates' }, { status: 500 });
76 }
77}

Pro tip: The DHL Express API requires an account number in the rates request. For sandbox testing, DHL provides a test account number in the documentation (or use any number — the sandbox accepts placeholder values). For production, use your actual DHL Express account number.

Expected result: The /api/dhl/rates endpoint returns available DHL Express services with prices and delivery dates. Test with real country codes and postal codes in the sandbox environment.

Common use cases

Shipment Tracking Dashboard

Build a customer-facing portal where users can enter their DHL waybill number to get real-time tracking status. Show the full event history, estimated delivery date, and current location. For businesses shipping large volumes, display all active shipments in a table with bulk tracking.

Bolt.new Prompt

Create a DHL shipment tracking page. Add a search input where users enter a DHL waybill number. On submit, call /api/dhl/track?waybill=[number] which fetches the tracking status from the DHL Shipment Tracking API. Display the shipment status, current location, estimated delivery, and full event timeline sorted by date. Handle 'shipment not found' errors gracefully.

Copy this prompt to try it in Bolt.new

Shipping Rate Calculator

Integrate a real-time shipping rate calculator into a checkout flow or order management system. Users enter the origin, destination, weight, and dimensions, and your app returns DHL Express rate options with transit time and price for each service level.

Bolt.new Prompt

Build a shipping rate calculator using the DHL Express Rate Finding API. Create a form with origin country/postal code, destination country/postal code, weight (kg), and package dimensions (cm). Call /api/dhl/rates with these values and display available service levels (EXPRESS_WORLDWIDE, EXPRESS_9, EXPRESS_12) with price and delivery date. Show prices in USD.

Copy this prompt to try it in Bolt.new

E-Commerce Fulfillment with Label Generation

Automate label generation for an e-commerce store. When an order is ready to ship, call the DHL Shipment API to create a shipment record and receive a base64-encoded PDF label. Display or download the label, and store the waybill number with the order for tracking.

Bolt.new Prompt

Build a shipment creation flow for my order management system. Create an API route that accepts shipper details, recipient address, package weight/dimensions, and calls the DHL Shipment API to create a shipment and return a PDF label as base64. Build a UI form pre-filled from order data, with a 'Create Shipment' button that generates the label and shows a download link.

Copy this prompt to try it in Bolt.new

Troubleshooting

'Authentication Failed' or 401 error on API calls despite correct API key

Cause: The API key is for the wrong environment (using a production key for sandbox endpoints or vice versa), or the DHL-API-Key header name is not capitalized exactly correctly.

Solution: Verify the exact header name is 'DHL-API-Key' (not 'dhl-api-key' or 'X-API-Key'). Confirm you're using the sandbox API key from your developer portal app, not the production key. Check that the key was copied without trailing spaces.

typescript
1headers: {
2 'DHL-API-Key': process.env.DHL_API_KEY ?? '', // Exact capitalization required
3 'Accept': 'application/json',
4}

Tracking returns 404 'Shipment not found' for real DHL tracking numbers

Cause: Sandbox API keys only return data for DHL's designated test tracking numbers. Real tracking numbers from actual shipments only work with production API keys.

Solution: Use sandbox test waybill numbers from DHL's documentation during development. Switch to production API key (update DHL_API_KEY in your environment variables) to track real shipments.

Rate API returns 'Error: Invalid account' or rates come back empty

Cause: The account number in the rates request doesn't match a valid DHL Express account, or the origin/destination country codes are not in ISO 3166-1 alpha-2 format.

Solution: Use 2-letter country codes (US, GB, DE) not country names. For sandbox testing, check DHL documentation for the correct test account number. For production, use your actual DHL Express contract account number.

typescript
1// Correct: 2-letter ISO country codes
2countryCode: 'US' // NOT 'United States' or 'USA'

CORS error when calling DHL API from the Bolt preview

Cause: DHL API endpoints do not include CORS headers allowing browser-origin requests, so direct calls from client-side React code fail.

Solution: All DHL API calls must go through Next.js API routes (server-side), never from client-side code. Your React components should call /api/dhl/track, not api-eu.dhl.com directly.

typescript
1// WRONG — client-side call fails with CORS
2// const data = await fetch('https://api-eu.dhl.com/track/shipments?...');
3
4// CORRECT — call your own API route which proxies to DHL
5const data = await fetch('/api/dhl/track?waybill=' + waybillNumber);

Best practices

  • Store DHL_API_KEY server-side only — never use NEXT_PUBLIC_ prefix, as the API key grants quota access and should not be exposed in browser network requests
  • All DHL API calls must go through Next.js API routes to avoid CORS errors — DHL's APIs don't include browser-origin CORS headers
  • Use sandbox test waybill numbers from DHL documentation during development, and switch to production keys only when deploying to a live environment
  • Cache tracking responses for 5-10 minutes — tracking status doesn't change minute-by-minute, and caching reduces API calls and improves page load speed
  • Normalize DHL's response format in your API route rather than in the frontend — keep the frontend components independent of DHL's specific field names
  • Handle 404 responses gracefully with a user-friendly 'Shipment not found — please check the tracking number' message rather than a generic error
  • For label generation, store the returned waybill number in your database immediately — it's your reference for tracking the shipment after creation

Alternatives

Frequently asked questions

How do I connect Bolt.new to DHL?

Register at developer.dhl.com, create a sandbox application, and copy your sandbox API key. Add DHL_API_KEY to your .env file (server-side only). Create Next.js API routes that pass the DHL-API-Key header to DHL's endpoints. The Shipment Tracking API (api-eu.dhl.com) and Express API (express.api.dhl.com) are the two base URLs you'll use most. Test with DHL's sandbox test waybill numbers.

Is the DHL API free to use?

The DHL developer sandbox is free with no usage limits for testing. Production API access is included with a DHL Express business account — there are no per-call API charges, but you must have an active shipping contract with DHL Express. The Shipment Tracking API is generally available without a contract for tracking existing shipments.

Can I use DHL tracking in Bolt's WebContainer preview?

Yes. DHL's tracking API is an outbound HTTP call from your server — exactly the kind of request that works in Bolt's WebContainer. Your Next.js API route calls DHL's servers, and those results are returned to your React component. There are no incoming webhooks or special networking requirements for tracking.

What's the difference between DHL Express, DHL Parcel, and DHL eCommerce?

DHL operates multiple business units with different APIs. DHL Express (international express delivery) uses the MyDHL API (express.api.dhl.com). DHL Parcel (domestic parcel delivery in Europe) has its own API. DHL eCommerce (economy international shipping) has a separate API. The APIs, credentials, and endpoints are different between divisions — verify which DHL service your business uses before choosing the API.

How do I track multiple shipments at once?

The DHL Shipment Tracking API supports tracking multiple waybill numbers in a single request by comma-separating them in the trackingNumber query parameter: /track/shipments?trackingNumber=1234,5678,9012. The response includes a shipments array with one entry per waybill. This is more efficient than making separate requests for each shipment.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.