Browse live and archived orders, export them, read full detail, and force status
changes. Paths are relative to the /api/v1 prefix; these are back-office endpoints
requiring an admin token.
Requires an admin bearer token (see Admin auth). Admin only.
See Common errors and the order lifecycle.
Admins see the full order record with all money fields.
| Method | URI | Access | Description |
|---|---|---|---|
GET |
/admin/orders |
Admin | Live orders (cursor-paginated) |
GET |
/admin/orders/export |
Admin | Export filtered orders as CSV |
GET |
/admin/orders/stats |
Admin | Status counters for the dashboard cards |
GET |
/admin/orders/archived |
Admin | Archived order history (cursor-paginated) |
GET |
/admin/orders/{orderId} |
Admin | Full order detail, timeline & chat |
PATCH |
/admin/orders/{orderId}/force-status |
Admin | Force an order into another status |
Cursor-paginated live orders (archived excluded), newest first. See Pagination → cursor-based.
Query
| Field | Type | Required | Rules |
|---|---|---|---|
status |
string | no | one order status (BROADCASTING … EXPIRED) |
date_from |
date | no | filter created_at >= |
date_to |
date | no | filter created_at <=; >= date_from |
driver_id |
integer | no | filter by assigned driver |
payment_method |
string | no | filter by payment method code |
limit |
integer | no | 1–100, default 25 |
cursor |
string | no | opaque cursor from next_cursor |
Response 200
{
"items": [
{
"id": 42,
"status": "IN_PROGRESS",
"client": { "id": 1, "name": "Ana MartĂnez", "phone": "+584241000001" },
"driver": { "id": 3, "name": "Carlos RodrĂguez", "phone": "+584241001001" },
"liters": 5000,
"amount_usd": 20.2,
"payment_method": "CASH_USD",
"address": "Av. Principal, Las Mercedes",
"created_at": "2026-06-26T12:00:00+00:00"
}
],
"next_cursor": "eyJpZCI6NDF9",
"has_more": true
}
driver is null for unassigned orders.
Streams the filtered orders as a CSV download (Content-Type: text/csv); there is
no JSON body. Accepts the same filters as the list except limit/cursor.
Columns: ID, Status, Client Name, Driver Name, Liters, Price (USD),
Payment Method, Created At, Delivered At, Cancelled At, Cancelled By.
Errors
| Status | Body | When |
|---|---|---|
422 |
{ "error": "TooManyResults", "message": "…" } |
More than 10,000 rows match the filters |
Status counters over the live (non-archived) set, for the dashboard cards.
Response 200
{
"active": 13,
"today": 8,
"delivered": 30,
"cancelled_expired": 4,
"broadcasting": 1,
"waiting_for_payment": 1,
"confirmed": 3,
"in_progress": 5,
"arrived": 2
}
active covers all non-archived orders; cancelled_expired covers CANCELLED and
EXPIRED orders.
Same shape, filters, and cursor pagination as GET /admin/orders,
but over archived orders (terminal orders from previous days).
Response 200 — { "items": [ … ], "next_cursor": "…", "has_more": false }.
Full order detail. The order is the complete record (all money fields), plus a
timeline and the in-order chat.
Response 200
{
"order": {
"id": 42,
"status": "DELIVERED",
"client_id": 1,
"driver_id": 3,
"address": "Av. Principal, Las Mercedes",
"liters_requested": 5000,
"actual_liters": 5000,
"payment_method": "CASH_USD",
"base_price_usd": 20.0,
"client_pays_usd": 20.2,
"aguita_revenue_usd": 3.6,
"driver_receives_usd": 16.24,
"solidary_fund_usd": 0.36,
"delivery_pin": "1234"
},
"timeline": [
{ "event": "CREATED", "at": "2026-06-26T12:00:00+00:00" },
{ "event": "CONFIRMED", "at": "2026-06-26T12:05:00+00:00" },
{ "event": "DELIVERED", "at": "2026-06-26T12:40:00+00:00" }
],
"chat": [
{
"id": 1,
"sender_id": 1,
"sender_role": "client",
"body": "¿Cuánto falta?",
"created_at": "2026-06-26T12:20:00+00:00"
}
]
}
A CANCELLED timeline entry also carries by and reason. See
Business → money breakdown.
Errors
| Status | Body | When |
|---|---|---|
404 |
{ "error": "OrderNotFound" } |
No order with that id |
Forces the order into a new status. Only lifecycle-valid
transitions are allowed; terminal states (DELIVERED, CANCELLED, EXPIRED) cannot
transition.
Request body
| Field | Type | Required | Rules |
|---|---|---|---|
status |
string | yes | target order status |
reason |
string | yes | 10–500 chars |
Response 200
{
"order": {
"id": 42,
"status": "DELIVERED",
"accepted_at": "2026-06-26T12:02:00+00:00",
"confirmed_at": "2026-06-26T12:05:00+00:00",
"paid_at": "2026-06-26T12:05:00+00:00",
"in_progress_at": "2026-06-26T12:10:00+00:00",
"arrived_at": "2026-06-26T12:35:00+00:00",
"delivered_at": "2026-06-26T12:40:00+00:00",
"cancelled_at": null,
"delivery_pin": "1234",
"side_effects": { "delivery_pin_generated": true }
},
"audit_entry": {
"from_status": "ARRIVED",
"to_status": "DELIVERED",
"reason": "ConfirmaciĂłn manual de entrega",
"admin_id": 1,
"created_at": "2026-06-29T12:00:00+00:00"
}
}
side_effects may include delivery_pin_generated and/or payment_cancelled.
Errors
| Status | Body | When |
|---|---|---|
404 |
{ "error": "OrderNotFound" } |
No order with that id |
422 |
{ "error": "InvalidTransition", "message": "…" } |
Not an allowed status change |