# How to Integrate Lovable with DHL Express API

- Tool: Lovable
- Difficulty: Intermediate
- Time required: 45 minutes
- Last updated: March 2026

## TL;DR

To integrate the DHL Express API with Lovable, create a Supabase Edge Function that proxies rating, shipment creation, and tracking requests using your DHL API key and account number stored in Cloud Secrets. This lets you build international shipping calculators, label generators, and parcel trackers in Lovable without exposing DHL credentials to the browser. Setup takes about 45 minutes.

## Add International Shipping Rates and Tracking to Your Lovable App with DHL

DHL Express is the global standard for international express shipping — if your e-commerce app ships across borders, DHL's APIs give you real-time rate quotes, automated label generation, and end-to-end parcel tracking across 220+ countries and territories. Integrating DHL with Lovable means your customers see accurate shipping costs at checkout, you can print DHL labels from within your app, and order tracking pages update automatically as packages move through DHL's network.

Because DHL's API requires authentication via an API key tied to a business account number, all calls must flow through Lovable's server-side Edge Function layer. Your DHL API key and account number live encrypted in Cloud → Secrets — they never touch the browser. The Edge Function acts as a secure proxy: it receives a request from your React frontend (e.g., 'get rates for a 2kg package from Berlin to Tokyo'), authenticates with DHL's REST API, and returns rate options or tracking status back to the UI.

DHL Express differs from domestic carriers like UPS in its international specialist focus. The DHL API is purpose-built for cross-border shipments with features like commodity declarations, customs duty estimation, and multi-piece shipment support — capabilities that matter when you're building a storefront that sells internationally. This guide covers the three DHL API products you'll use most: the Rate API for cost calculations, the Shipment API for label generation, and the Tracking API for delivery updates.

## Before you start

- A DHL Express business account — register at developer.dhl.com and request API access (DHL provides a sandbox environment for testing)
- Your DHL API key and DHL account number from the DHL Developer Portal dashboard
- A Lovable project with Lovable Cloud enabled (the default for all new projects)
- Basic understanding of what an Edge Function does — it runs server-side TypeScript on Deno, separate from your React frontend
- An e-commerce or logistics app in Lovable that needs shipping rate, label, or tracking functionality

## Step-by-step guide

### 1. Get your DHL API credentials from the Developer Portal

Before writing any code, you need a DHL API key and account number. Navigate to developer.dhl.com and sign in or create a free developer account. Once logged in, go to My Apps and click Create App. Give the app a name (e.g., 'Lovable Storefront') and select the APIs you want access to — at minimum, select Express Rating, Express Shipment, and Express Tracking. After creating the app, DHL generates an API key (a long alphanumeric string) visible on the app detail page.

Importantly, DHL Express APIs also require your DHL account number — this is the 9-digit number associated with your DHL Express business account, not your developer portal account. If you don't have a DHL business account yet, contact DHL sales to open one; the developer sandbox works with a test account number provided in the developer portal documentation. Write down both your API key and account number before proceeding — you'll need both for the Cloud Secrets step.

DHL's sandbox environment uses the base URL https://api-mock.dhl.com/mydhlapi for testing. Production uses https://api.dhl.com/mydhlapi. It is strongly recommended to build and test with the sandbox first, then swap to production credentials when you're ready to go live.

**Expected result:** You have a DHL API key (e.g., 'a1b2c3d4e5f6...') and a 9-digit DHL account number ready to paste into Cloud Secrets.

### 2. Store DHL credentials in Cloud Secrets

Now that you have your DHL API key and account number, store them securely in Lovable's Cloud Secrets panel. In your Lovable project, look at the top of the screen and click the '+' icon next to the Preview panel to open the Cloud tab. Inside the Cloud tab, click Secrets in the left-hand navigation. You'll see a list of encrypted environment variables — click Add Secret to add each credential.

Add your first secret: set the name to DHL_API_KEY and paste your DHL API key as the value, then click Save. Add a second secret: set the name to DHL_ACCOUNT_NUMBER and enter your 9-digit account number as the value, then click Save. The secrets are now encrypted and stored — they will only be accessible from Edge Functions via Deno.env.get(), never from frontend React code or the browser.

A critical rule: never paste your DHL API key directly into Lovable's chat prompt or into your React component code. On Lovable's free tier, chat history is publicly visible, and keys pasted in chat are recoverable from Git commit history. Always use Cloud → Secrets for any credential that authenticates an external API. Lovable's security layer blocks approximately 1,200 hardcoded API keys per day — use the Secrets panel to stay on the right side of that protection.

**Expected result:** The Cloud → Secrets panel shows two entries: DHL_API_KEY and DHL_ACCOUNT_NUMBER, both displaying as encrypted values.

### 3. Create the DHL Edge Function proxy

With credentials secured, ask Lovable to create the Edge Function that proxies DHL API calls. Type the following prompt into Lovable's chat interface. Lovable will generate the TypeScript code, create the file at supabase/functions/dhl-proxy/index.ts, and deploy it to your Cloud project automatically.

The Edge Function uses a switch on an 'action' query parameter to route between the three DHL API endpoints: 'rates' calls the DHL Rate API, 'shipment' calls the Shipment API, and 'track' calls the Tracking API. The DHL Express REST API uses HTTP Basic Auth where the username is your account number and the password is your API key. The function constructs the Authorization header using btoa() to base64-encode the credentials retrieved from Deno.env.get(). All responses include CORS headers so your React frontend can call the function from the browser.

```
import { serve } from 'https://deno.land/std@0.168.0/http/server.ts'

const DHL_BASE_URL = 'https://api-mock.dhl.com/mydhlapi'

const corsHeaders = {
  'Access-Control-Allow-Origin': '*',
  'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',
}

serve(async (req) => {
  if (req.method === 'OPTIONS') {
    return new Response('ok', { headers: corsHeaders })
  }

  try {
    const apiKey = Deno.env.get('DHL_API_KEY')
    const accountNumber = Deno.env.get('DHL_ACCOUNT_NUMBER')

    if (!apiKey || !accountNumber) {
      return new Response(
        JSON.stringify({ error: 'DHL credentials not configured in Cloud Secrets' }),
        { status: 500, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
      )
    }

    const authHeader = 'Basic ' + btoa(`${accountNumber}:${apiKey}`)
    const url = new URL(req.url)
    const action = url.searchParams.get('action')

    let dhlUrl: string
    let dhlMethod: string
    let dhlBody: string | undefined

    if (action === 'rates') {
      dhlUrl = `${DHL_BASE_URL}/rates`
      dhlMethod = 'POST'
      dhlBody = await req.text()
    } else if (action === 'shipment') {
      dhlUrl = `${DHL_BASE_URL}/shipments`
      dhlMethod = 'POST'
      dhlBody = await req.text()
    } else if (action === 'track') {
      const trackingNumber = url.searchParams.get('trackingNumber')
      dhlUrl = `${DHL_BASE_URL}/tracking?trackingNumber=${trackingNumber}&trackingView=all-checkpoints&levelOfDetail=all`
      dhlMethod = 'GET'
    } else {
      return new Response(
        JSON.stringify({ error: 'Invalid action. Use: rates, shipment, or track' }),
        { status: 400, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
      )
    }

    const dhlResponse = await fetch(dhlUrl, {
      method: dhlMethod,
      headers: {
        'Authorization': authHeader,
        'Content-Type': 'application/json',
        'Accept': 'application/json',
        'Message-Reference': crypto.randomUUID(),
        'Message-Reference-Date': new Date().toISOString(),
        'Plugin-Name': 'Lovable',
        'Plugin-Version': '1.0',
        'Shipper-Account': accountNumber,
      },
      body: dhlBody,
    })

    const data = await dhlResponse.json()

    return new Response(JSON.stringify(data), {
      status: dhlResponse.status,
      headers: { ...corsHeaders, 'Content-Type': 'application/json' },
    })
  } catch (error) {
    return new Response(
      JSON.stringify({ error: error.message }),
      { status: 500, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
    )
  }
})
```

**Expected result:** Lovable creates the Edge Function file, deploys it to Cloud, and confirms it's live. You'll see the function listed under Cloud → Edge Functions in your project.

### 4. Build the shipping rate calculator React component

With the Edge Function deployed, ask Lovable to build a rate calculator UI component that calls it. This component collects shipment details from the user — origin and destination countries, package weight, and dimensions — formats them as a DHL Rate API request body, sends it to your Edge Function, and displays the returned service options with prices and delivery dates.

The DHL Rate API expects a specific JSON body structure with plannedShippingDateAndTime, unitOfMeasurement, isCustomsDeclarable, productCode ('EXPRESS_WORLDWIDE' or left empty for all products), packages array with weight and dimensions, and customerDetails with shipperDetails and receiverDetails including postal code, city, and countryCode. Lovable will generate all of this from the prompt below, including a TypeScript interface for the rate response and a properly typed component using Tailwind CSS and shadcn/ui.

The component calls the Edge Function at /functions/v1/dhl-proxy?action=rates using the Supabase client's functions.invoke() method or a direct fetch to the function URL. Error states are handled gracefully — if DHL returns an error (e.g., invalid account number in sandbox), the component displays the error message rather than crashing. Successful responses show a list of available DHL services with price, currency, and estimated transit days.

**Expected result:** A rate calculator form appears in your Lovable preview. Entering test values and clicking Calculate shows DHL service options with prices returned from the Edge Function.

### 5. Add parcel tracking and test end-to-end

Add a tracking page that lets customers look up a DHL shipment by tracking number. This calls the Edge Function with action=track and the tracking number as a query parameter, then displays a timeline of shipment events from DHL's Tracking API.

Once both components are working, test the full flow end-to-end. For the sandbox environment, DHL provides test tracking numbers in their developer documentation (e.g., '1234567890' returns a pre-defined tracking response). Enter a test tracking number and verify the event timeline displays correctly — you should see events like 'Shipment picked up', 'Arrived at facility', and 'Delivered' with timestamps and locations.

For complex integrations involving customs declarations, multi-piece shipments, or DHL account setup issues, RapidDev's team has experience configuring DHL Express integrations for international e-commerce apps and can help troubleshoot account provisioning and API authentication errors. Before going to production, switch your Cloud Secrets from sandbox values to your live DHL API key and account number, and update DHL_BASE_URL in the Edge Function from api-mock.dhl.com to api.dhl.com. Run a test rate request against the live API to confirm your production credentials work before launching.

**Expected result:** The tracking page loads, accepts a test DHL tracking number, and displays a timeline of shipment events returned from the DHL Tracking API via your Edge Function.

## Best practices

- Always use DHL's sandbox environment (api-mock.dhl.com) during development — switching to production requires only changing the base URL and Cloud Secrets values, not the Edge Function logic.
- Store origin address details (your warehouse country, postal code, city) as additional Cloud Secrets rather than hardcoding them in the Edge Function, so they're easy to update when your fulfillment location changes.
- Log the DHL Message-Reference UUID from each API response to your Supabase database — DHL support uses this value to trace specific API calls when you report issues.
- Validate package weight and dimension limits before calling the DHL Rate API — DHL Express has a 70kg per-piece limit and a 120cm length limit. Add client-side validation to prevent unnecessary API calls for packages that exceed DHL's thresholds.
- Cache DHL rate responses in Supabase for identical shipment parameters with a short TTL (e.g., 10 minutes) to reduce API call volume during high-traffic checkout sessions.
- For international shipments, set isCustomsDeclarable to true and include a valid commodityCode (HS code) in the shipment request — missing customs data causes DHL label creation to fail at the carrier level.
- Test your production DHL credentials with a small, low-value shipment before routing live customer orders through the API, to confirm your account is provisioned for the origin-destination lanes you need.

## Use cases

### International shipping rate calculator at checkout

Display live DHL Express rate options to customers at checkout based on their destination country, package weight, and dimensions. Show estimated delivery dates alongside prices so customers can choose between DHL Express Worldwide, DHL Express 12:00, and other service levels.

Prompt example:

```
Create a shipping rate calculator component that calls an Edge Function to get DHL Express rates. The form takes origin country, destination country, weight in kg, and dimensions in cm. Display each available DHL service with its price in USD and estimated delivery date. Store my DHL API key and account number in Cloud Secrets.
```

### DHL shipment creation and label printing

Allow store admins to generate DHL Express shipping labels directly from your Lovable app. The Edge Function calls the DHL Shipment API with sender, recipient, and package details and returns a PDF label URL for printing.

Prompt example:

```
Build an order fulfillment page where I can enter shipper and recipient addresses, package weight, and dimensions, then click Create Shipment to call the DHL Shipment API via an Edge Function. Display the returned tracking number and show a Download Label button that opens the PDF. Save the tracking number to the orders table in Supabase.
```

### Parcel tracking status dashboard

Give customers a self-service tracking page where they enter a DHL tracking number and see real-time shipment events, current location, and estimated delivery date. The Edge Function calls DHL's Tracking API and formats the event timeline for display.

Prompt example:

```
Create a parcel tracking page where users enter a DHL tracking number and see a timeline of shipment events from the DHL Tracking API. Call the API via an Edge Function using my DHL API key in Cloud Secrets. Show each event with its timestamp, location, and description. Highlight the current status at the top.
```

## Troubleshooting

### Edge Function returns 401 Unauthorized from DHL

Cause: The DHL Basic Auth header is constructed incorrectly, or the API key / account number values in Cloud Secrets contain extra whitespace or are swapped (account number used as key and vice versa).

Solution: Go to Cloud → Secrets and verify DHL_API_KEY contains the API key string and DHL_ACCOUNT_NUMBER contains the 9-digit account number — not the other way around. The Basic Auth format is base64(accountNumber:apiKey). Also check that neither value has leading or trailing spaces, which can happen when copy-pasting. Delete and re-enter the secrets if unsure.

### DHL Rate API returns 'No rates found' or an empty products array

Cause: The requested route or package dimensions are outside DHL Express service coverage, or the plannedShippingDateAndTime is in the past or uses an incorrect ISO 8601 format.

Solution: Ensure plannedShippingDateAndTime is formatted as 'YYYY-MM-DDTHH:MM:SS GMT+HH:MM' — for example '2026-04-01T14:00:00 GMT+00:00'. Verify the origin and destination country codes are valid ISO 3166-1 alpha-2 codes. Test with common routes like US→GB or DE→JP to confirm the API is responding before testing edge routes.

```
// Correct date format for DHL Rate API
const plannedDate = new Date()
plannedDate.setDate(plannedDate.getDate() + 1) // Tomorrow
const isoDate = plannedDate.toISOString().slice(0, 19) + ' GMT+00:00'
```

### CORS error when calling the Edge Function from the React frontend

Cause: The Edge Function is not handling the OPTIONS preflight request, or the CORS headers are missing from error responses.

Solution: Check that the Edge Function returns 'ok' with corsHeaders for OPTIONS requests before any other logic runs. Also ensure every return statement in the function — including catch blocks and early error returns — includes the corsHeaders object spread. Rebuild the Edge Function via Lovable chat if the CORS handling is missing.

```
// Add to every Response in the Edge Function
return new Response(JSON.stringify(data), {
  status: dhlResponse.status,
  headers: { ...corsHeaders, 'Content-Type': 'application/json' },
})
```

### DHL returns 'Secret DHL_API_KEY not found' error (P0001) in Cloud Logs

Cause: The secret name referenced in Deno.env.get() does not exactly match the name stored in Cloud → Secrets, including case sensitivity.

Solution: Open Cloud → Secrets and confirm the exact secret names match what the Edge Function code uses. Secret names are case-sensitive — 'DHL_API_KEY' and 'dhl_api_key' are different secrets. Click the secret name to verify it, then check the Edge Function code for the exact string used in Deno.env.get(). Update one or the other to match exactly.

## Frequently asked questions

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

Yes. The DHL Express API requires both an API key from the Developer Portal and a DHL business account number. The developer sandbox provides a test account number for building and testing, but you need a live DHL Express business account to process real shipments. Contact DHL sales at dhl.com to open an account — approval typically takes 2-3 business days.

### Why must DHL API calls go through an Edge Function instead of directly from my React app?

DHL's API uses Basic Auth with your account number and API key as credentials. Calling the DHL API directly from React would expose these credentials in your browser's network tab, visible to any user with developer tools open. The Edge Function keeps credentials server-side in Cloud Secrets, where they are encrypted and inaccessible to the browser. This is Lovable's standard security pattern for any authenticated external API.

### Can I use the DHL API to ship domestically as well as internationally?

DHL Express focuses on international express shipping and also offers domestic express services in many countries. However, if your primary need is domestic US shipping (ground, standard, and next-day), UPS or FedEx typically offer better domestic rates and service options. DHL is most cost-effective for international cross-border shipments where its global network and customs expertise provide the most value.

### How do I switch from DHL sandbox to production?

Update two things: change the DHL_BASE_URL in your Edge Function from 'https://api-mock.dhl.com/mydhlapi' to 'https://api.dhl.com/mydhlapi', and update your Cloud Secrets to replace sandbox credentials with your live DHL API key and production account number. No other code changes are required. Redeploy the Edge Function via Lovable chat after making the URL change.

### Does the DHL API support generating printable shipping labels?

Yes. The DHL Shipment API (action=shipment in this integration) returns a base64-encoded PDF label that you can decode and display as a download link in your React component. The label includes the DHL barcode, tracking number, routing information, and destination details in DHL's standard label format accepted at all DHL drop-off locations and pickup services.

---

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