Skip to content

Webhooks

Webhooks deliver real-time shipment status updates to your HTTP endpoint as they occur. This is one of two status relay methods supported by Duty Pro (the other being SFTP).

Configure your webhook endpoint in the dashboard under Settings > Status Relay:

  1. Select Webhook as the relay method.
  2. Enter your endpoint URL (must accept POST requests).
  3. Optionally provide a webhook secret for signature verification.

Webhook configuration can be set at the account level (applies to all brands) or overridden per brand.

Duty Pro sends a POST request with a JSON body:

{
"reference": "ORD-2026-00123",
"held": true,
"held_on_error": false,
"canceled": false
}
FieldTypeDescription
referencestringYour shipment reference number
heldbooleantrue when the shipment is held and customs payment is required
held_on_errorbooleantrue if the shipment is held because of a calculation error
canceledbooleantrue if the payment has expired
EventheldcanceledTrigger
Payment requiredtruefalseShipment created with fees > 0
Payment receivedfalsefalseConsignee completed payment
No payment requiredfalsefalseShipment created with fees = 0
Payment expiredfalsetruePayment deadline passed

If your receiving system expects different field names, contact the Duty Pro team to configure custom key mappings for your account. For example, reference can be mapped to barcode or any other name your system requires.

Every webhook request includes the following headers:

HeaderDescription
Content-Typeapplication/json
X-DutyPro-SignatureHMAC-SHA256 signature (only if a webhook secret is configured)

If you configured a webhook secret, every request includes an X-DutyPro-Signature header containing an HMAC-SHA256 signature. Verify it to ensure the request is authentic and hasn’t been tampered with.

  1. Extract the X-DutyPro-Signature header value.
  2. Serialize the request body as JSON with keys sorted alphabetically.
  3. Compute HMAC-SHA256 using your webhook secret as the key and the serialized body as the message.
  4. Compare the computed signature with the header value.
import hmac
import hashlib
import json
def verify_signature(payload: dict, secret: str, signature: str) -> bool:
body = json.dumps(payload, sort_keys=True).encode()
expected = hmac.new(secret.encode(), body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, signature)
const crypto = require('crypto');
function verifySignature(payload, secret, signature) {
const body = JSON.stringify(payload, Object.keys(payload).sort());
const expected = crypto
.createHmac('sha256', secret)
.update(body)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(signature)
);
}

If your endpoint returns a non-success HTTP status (anything outside 200-299) or the request times out (15-second timeout), Duty Pro retries with increasing backoff:

AttemptDelay after failure
1st retry5 minutes
2nd retry10 minutes
3rd retry15 minutes
4th retry20 minutes

After 4 failed attempts, the relay is marked as FAILED. You can view failed deliveries in the dashboard under Settings > Status Relay logs, or in the shipment detail view.

Your endpoint should:

  • Return a 2xx status code to acknowledge receipt.
  • Respond within 15 seconds.
  • Process the event idempotently — the same event may be delivered more than once during retries.

All webhook delivery attempts (successful and failed) are logged and visible in two places:

  • Shipment detail view — The “Status Relay Log” section shows relay events for that specific shipment, including payload, response code, and error messages.
  • Settings > Status Relay — Shows the overall relay configuration and recent delivery history.