Delivery Tracking Event Webhooks Guide
This guide is for developers integrating with the iDrive Shipping API outbound webhook system. It covers what the service does, how to authenticate, how to create and manage subscriptions, what event payloads look like, and how to build a reliable consumer.
iDrive Shipping API Webhooks
Push: Receive tracking updates to your endpoint as they happen. You don't need to poll.
Prefer to fetch tracking data on demand?See the Tracking Event (polling) Guide for pulling tracker data yourself.
Who this is for
3PLs (most integrators). You manage many merchants, each set up as a subtenant under your 3PL tenant. You create one subscription on your 3PL tenant, and it receives events for every merchant under it. Each event tells you which merchant it belongs to.
Single shippers. You ship for your own business only, so you create a subscription on your own tenant. Everything below still applies, and you can skip the 3PL notes.
Events
| Event | Fires when |
|---|---|
tracking.updated | A shipment's tracking status changes |
Environments
https://api.beta.idrivelogistics.com # sandbox (testing)
https://api.idrivelogistics.com # production
The sandbox uses its own account and API keys. Ask your iDrive contact for sandbox credentials.
1. Get an access token
Create an API key in the iDrive TMS under Settings > API Keys and choose Full access. Read-only keys can't manage webhooks. 3PLs should create the key while logged into the 3PL tenant. You can also ask your iDrive contact to create the key for you.
POST /api/v1/tokens/m2m
Content-Type: application/json
{ "grantType": "clientCredentials", "clientId": "...", "clientSecret": "..." }tenantId is optional in this request and defaults to your key's tenant. 3PLs should use their 3PL tenant.
Send Authorization: Bearer <accessToken> on every request. Tokens last 1 hour, so request a new one before the current one expires.
2. Create a subscription
curl -X POST https://api.idrivelogistics.com/api/v1/webhooks \
-H "Authorization: Bearer <accessToken>" \
-H "Content-Type: application/json" \
-d '{
"uri": "https://your-app.example.com/webhooks/idrive",
"email": "[email protected]",
"registeredEvents": ["tracking.updated"],
"secret": "your-hmac-secret"
}'| Field | Required | Notes |
|---|---|---|
uri | Yes | HTTPS only. Must be publicly reachable. Redirects are not followed. |
email | Yes | Receives an alert if the subscription is auto-disabled |
registeredEvents | Yes | For example ["tracking.updated"] |
secret | One of these two | Used to sign each delivery (recommended) |
credentials | One of these two | { "username", "password" }, sent as Basic Auth |
customHeader | No | One extra { "key", "value" } header sent on every delivery |
Secrets are never returned. The response shows hasSecret, hasCredentials and hasCustomHeader instead.
Other endpoints:
GET /api/v1/webhookslists your subscriptions.GET /api/v1/webhooks/{webhookId}gets one subscription.PATCH /api/v1/webhooks/{webhookId}updates one. To change a stored secret, credentials or custom header, also sendupdateSecret,updateCredentialsorupdateCustomHeaderset totrue.DELETE /api/v1/webhooks/{webhookId}deletes one.
3. What you receive
{
"id": "kwevt_abc123",
"eventType": "tracking.updated",
"tenantId": "merchant-tenant-id",
"payloadType": "TrackerV1",
"createdDate": "2026-06-15T12:00:00.000Z",
"payload": { }
}tenantIdis the merchant the shipment belongs to. 3PLs should use it to route each event to the right merchant. Single shippers will always see their own tenant ID.payloadis the full tracker. Its fields and statuses are described in The Tracker resource.- Check
payloadTypebefore processing. If you see a value you don't recognize, log it and skip it.
4. Build your endpoint
Your endpoint should do the following:
-
Verify the signature. The
X-Hmac-Sha256header is a base64 HMAC-SHA256 of the raw request body. Compute it before you parse the JSON.import { createHmac, timingSafeEqual } from "node:crypto"; function isValid(rawBody: string, signature: string, secret: string) { const expected = Buffer.from( createHmac("sha256", secret).update(rawBody, "utf8").digest("base64") ); const received = Buffer.from(signature); return expected.length === received.length && timingSafeEqual(expected, received); } -
Respond within 500 ms. Return a 2xx right away and do the real work in a background queue. Slower responses count as failures.
-
Skip duplicates. The same event can arrive more than once. Save each
id(also sent in thex-idrive-event-idheader) for at least 48 hours, and skip any you've already seen. -
Handle events arriving out of order. Compare
payload.updatedAtwith what you have stored, and ignore anything older.
5. Retries and auto-disable
If your endpoint fails or times out, we retry after about 30 s, 60 s, 120 s and 240 s, for 5 attempts in total. After that, we don't send that event again.
If 10 events in a row fail every retry, the subscription is turned off and the email on file is notified. To turn it back on:
PATCH /api/v1/webhooks/{webhookId}
{ "isActive": true }3PLs: one subscription covers all of your merchants, so if it's disabled, events stop for every merchant at once. Watch that inbox.
6. Expiration
Subscriptions expire 120 days after they're created (see expirationDate in the response). Expired subscriptions stop receiving events, and no email is sent when that happens.
To keep receiving events, create a new subscription before the old one expires, then delete the old one. The new subscription gets a new webhookId, so don't hard-code it.
7. Catching up on missed events
If events were missed, for example while your endpoint was down or the subscription was disabled:
- 3PLs: use
GET /api/v1/trackerswith your 3PL token. It returns trackers for all of your merchants. - Single shippers: use
GET /api/v1/trackers, orGET /api/v1/webhookEventsto see what we sent.
8. Errors
Error responses include message, statusCode, errorCode, errors and correlationId.
| Status | Meaning |
|---|---|
| 400 | Invalid request. Check errors. |
| 403 | Your API key doesn't have access. Use a Full access key. |
| 404 | The item doesn't exist or isn't yours. |
| 500 | Our error. Retry, and include the correlationId if you contact support. |
FAQ
Can I send events to more than one URL? Yes. Create one subscription per URL.
Can a 3PL get events for only some of its merchants? No. A subscription on the 3PL tenant receives events for every merchant under it. Filter by tenantId on your side.
How do I test locally? Use a tunnel such as ngrok against the sandbox (api.beta.idrivelogistics.com).
Updated 3 days ago
