Docs β€Ί Webhooks

Webhooks overview

Register endpoints and receive signed delivery events.

Webhooks push every change on your orders to your HTTPS endpoint within seconds: driver assigned, pickup, dropoff, proof-of-delivery photos, failures, cancellations. They're signed, retried and logged.

Register an endpoint

bash
curl -s https://api.trydragonfly.com/v1/webhooks \
  -H "Authorization: Bearer $DRAGONFLY_API_KEY" -H 'content-type: application/json' \
  -d '{ "url": "https://your-app.example.com/dragonfly", "events": ["delivery.*"], "description": "production" }'
json
{ "success": true, "data": { "id": "cm…", "url": "https://your-app.example.com/dragonfly", "events": ["delivery.*"], "secret": "whsec_…", "isActive": true } }
Important: secret is shown once. Store it to verify signatures.
  • events: [] subscribes to everything. Wildcards like delivery.* and * work. See the event catalog.
  • Endpoints belong to the API key that created them. Each key receives events for the orders it created.
  • Register several endpoints (for example, one per environment or consumer).

Manage endpoints

MethodPathDoes
GET/v1/webhooksList your endpoints (secrets redacted).
POST/v1/webhooksCreate an endpoint.
PATCH/v1/webhooks/{id}Change url, events, description, or re-enable with isActive: true.
DELETE/v1/webhooks/{id}Remove an endpoint.
GET/v1/webhooks/{id}/deliveriesRecent delivery attempts: status, response code, error.
POST/v1/webhooks/{id}/testReplay your latest order's current state as delivery.updated.
GET/v1/webhooks/eventsThe event catalog.

The message

http
POST /dragonfly HTTP/1.1
content-type: application/json
dragonfly-id: msg_2Lk9…
dragonfly-timestamp: 1791400501
dragonfly-signature: v1,K5oZfzN95Z9UVu1EsfQmfVNQhnkZ2pj9o9NDN/H/pI4=
dragonfly-event: delivery.dropoff_complete
json
{
  "type": "delivery",
  "event": "delivery.dropoff_complete",
  "id": "msg_2Lk9…",
  "occurredAt": "2026-10-09T16:38:12.000Z",
  "data": {
    "delivery": {
      "id": "cm…",
      "externalId": "cater-88412",
      "status": "dropoff_complete",
      "orderStatus": "DELIVERED",
      "pickup": { "address": { "formatted": "100 W Randolph St, Chicago, IL 60601" } },
      "dropoffs": [{ "address": { "formatted": "233 S Wacker Dr, Chicago, IL 60606" }, "completion": { "photoUrl": "https://…" } }],
      "courier": { "name": "Driver name", "phone": "+1…" },
      "proofOfDelivery": [{ "type": "photo_proof_of_delivery", "url": "https://…", "capturedAt": "2026-10-09T16:38:10.000Z" }],
      "publicTrackingUrl": "https://…",
      "onTime": true
    },
    "nashStatus": "dropoff_complete",
    "onfleetTrigger": "taskCompleted"
  }
}

data.delivery is a superset of Nash's Delivery object and Onfleet's Task, so a receiver written for either maps cleanly. Timestamps are ISO 8601 UTC.

Respond fast

Return any 2xx within a few seconds, then process asynchronously. Anything else is retried. Deduplicate on dragonfly-id: a message can arrive more than once.

Something unclear or missing? Tell us.