List orders
GET /v1/ordersReturns the venue's orders, paginated and filterable by status and time.
This is the backbone of a pull-based integration — there are no webhooks;
poll this endpoint with updatedSince to pick up new and changed orders
(see Polling).
Paid plans only
The Orders API is available on the paid plans (Duckling and Golden
Duck). On the free Egg plan, requests are rejected with
403 Forbidden and the message
"The Orders API requires a paid plan". API keys and the
Menu API work on every plan.
Query parameters#
| Parameter | Type | Default | Constraints |
|---|---|---|---|
page | integer | 1 | ≥ 1 |
limit | integer | 20 | 1–100 |
status | string | — | new | confirmed | preparing | delivering | completed | cancelled |
since | string | — | ISO 8601 with timezone; orders created at/after this time |
until | string | — | ISO 8601 with timezone; orders created at/before this time |
updatedSince | string | — | ISO 8601 with timezone; orders updated at/after this time — the polling cursor |
Timestamps must carry an explicit timezone
since, until and updatedSince must
end with Z or a ±hh:mm offset —
2026-07-05T12:00:00Z, not 2026-07-05T12:00:00.
Naive timestamps are rejected with 400 to prevent silent
timezone bugs. We recommend always using UTC (Z).
Sorting#
- With
updatedSince: sorted byupdatedAtascending — stable order for cursor-based polling. - Without it: sorted by
createdAtdescending (newest first).
Example#
curl "https://api.duck-hub.com/v1/orders?status=new&limit=50" \
-H "Authorization: Bearer dk_live_your_api_key"const params = new URLSearchParams({
status: 'new',
limit: '50',
})
const response = await fetch(
`https://api.duck-hub.com/v1/orders?${params}`,
{ headers: { Authorization: 'Bearer dk_live_your_api_key' } },
)
const { items, total, totalPages } = await response.json()Response#
200 OK:
{
"items": [
{
"id": "cml9x2f4a0001abcd1234efgh",
"orderNumber": "1024",
"status": "new",
"type": "delivery",
"customerName": "Anna",
"customerPhone": "+380971234567",
"customerEmail": null,
"deliveryAddress": "Khreshchatyk St 1, Kyiv",
"deliveryNotes": null,
"paymentMethod": "cash",
"comment": null,
"changeFromAmount": 50000,
"scheduledFor": null,
"currency": "UAH",
"subtotalAmount": 43000,
"deliveryFee": 6000,
"discountAmount": 0,
"totalAmount": 49000,
"createdAt": "2026-07-05T11:58:21.000Z",
"updatedAt": "2026-07-05T11:58:21.000Z",
"confirmedAt": null,
"completedAt": null,
"items": [
{
"productExternalId": "prod-margherita",
"productName": "Margherita",
"quantity": 2,
"unitPrice": 21500,
"totalPrice": 43000,
"modifiers": [
{
"groupName": "Extras",
"ingredientExternalId": "ing-olives",
"ingredientName": "Olives",
"priceAdjustment": 2500,
"quantity": 1
}
]
}
]
}
],
"total": 1,
"page": 1,
"limit": 50,
"totalPages": 1
}| Field | Meaning |
|---|---|
items | Orders for this page — full shape in the field reference |
total | Total orders matching the filters |
page / limit | Echo of the pagination inputs |
totalPages | ceil(total / limit) |
Errors#
400— naive timestamp (no timezone) or invalid ISO 8601 insince/until/updatedSince; other validation failures401— see Authentication403— free plan (no Orders API access)429— see Rate limits