Docs › Orders
Create an order
POST /v1/orders — single drops and multi-stop routes.
http
POST /v1/ordersCreates a delivery order in your Dragonfly account. Safe to retry: it is idempotent on externalId.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
externalId | string (≤200) | yes | Your own order id. Re-sending it returns the existing order instead of creating a duplicate. |
pickup | Stop | yes | Where the driver collects the order. |
dropoff | Stop | one of | A single delivery. |
dropoffs | Stop[] (1–25) | one of | A multi-stop route from the same pickup. |
subMerchantId | string | no | The pickup location, for merchants with several locations. It must belong to your account. |
subtotalCents | integer | recommended | Order value in cents. Drives tiered pricing, and minimum gratuity where your contract has one. |
tipCents | integer | no | Tip in cents. 100% goes to the driver. |
taxCents, totalCents | integer | no | For your records and reporting. |
metadata | object | no | Free-form; echoed back in webhooks. |
Send either dropoff (one delivery) or dropoffs (a route).
Single drop (catering, on-demand)
bash
curl -s https://api.trydragonfly.com/v1/orders \
-H "Authorization: Bearer $DRAGONFLY_API_KEY" -H 'content-type: application/json' -d '{
"externalId": "cater-88412",
"pickup": { "address": "100 W Randolph St, Chicago, IL 60601", "contactName": "Kitchen", "contactPhone": "+13125550100",
"windowStart": "2026-10-09T10:45:00-05:00", "notes": "Back door on Lake St" },
"dropoff": { "address": "233 S Wacker Dr, Chicago, IL 60606", "contactName": "Front desk, 31st floor", "contactPhone": "+13125550111",
"contactEmail": "[email protected]",
"windowStart": "2026-10-09T11:30:00-05:00", "windowEnd": "2026-10-09T11:45:00-05:00",
"notes": "Set up on the conference room credenza", "photoRequired": "REQUIRED" },
"subtotalCents": 64000,
"tipCents": 9000
}'Multi-stop route
bash
curl -s https://api.trydragonfly.com/v1/orders \
-H "Authorization: Bearer $DRAGONFLY_API_KEY" -H 'content-type: application/json' -d '{
"externalId": "route-2026-10-09-am",
"pickup": { "address": "870 Market St, San Francisco, CA 94102", "contactPhone": "+14155550100" },
"dropoffs": [
{ "address": "1 Ferry Building, San Francisco, CA 94111", "contactName": "A. Patel", "contactPhone": "+14155550111" },
{ "address": "2173 Harbor Bay Pkwy, Alameda, CA 94502", "contactName": "J. Rivera", "contactPhone": "+14155550112", "requiresSignature": true }
]
}'Note: If your account is on Dragonfly routing, send one order per recipient rather than building routes yourself. Dragonfly optimizes the day's routes across all of your orders.
Response
201 Created for a new order. 200 OK for an idempotent replay, which returns the existing order.
json
{
"data": {
"orderId": "cmuyh89rz000d01pc9uuokrld",
"externalId": "cater-88412",
"status": "PENDING",
"dropoffs": 1,
"dispatchedTo": "cartwheel",
"trackingUrl": null,
"idempotentReplay": false
}
}See The order object for every field and value.
Errors
| HTTP | code | Typical cause |
|---|---|---|
| 400 | VALIDATION_ERROR | A missing contactPhone, a bad window format, or neither dropoff nor dropoffs. details[] names each field. |
| 400 | INVALID_SUB_MERCHANT | subMerchantId isn't one of your locations. |
| 401 | UNAUTHORIZED | Missing, wrong or revoked key. |
| 403 | MERCHANT_INACTIVE | The account is deactivated. |
| 429 | RATE_LIMITED | More than 100 requests per minute on this key. |
Full list: Errors.
Something unclear or missing? Tell us.