Admin orders

Browse live and archived orders, export them, read full detail, force status changes, and refund a client over Pago MĂłvil. 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.

Endpoints

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/cancellation-reasons Admin Admin cancellation-reason catalogue
GET /admin/orders/{orderId} Admin Full order detail, timeline & chat
PATCH /admin/orders/{orderId}/force-status Admin Force an order into another status
GET /admin/orders/{orderId}/refund Admin Refundable amount and the order's refund, if any
POST /admin/orders/{orderId}/refund Admin Refund the client, full or partial, over Pago MĂłvil

GET /admin/orders

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.


GET /admin/orders/export

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

GET /admin/orders/stats

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.


GET /admin/orders/archived

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 }.


GET /admin/orders/{orderId}

Full order detail. The order is the complete record (all money fields), plus a timeline and the in-order chat.

billing holds the customer's billing data as it stood when the order was created, or null when the order has none. billing.address is the billing address, unrelated to the order's delivery address.

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.0,
    "aguita_revenue_usd": 3.6,
    "driver_receives_usd": 16.4,
    "solidary_fund_usd": 0.0,
    "delivery_pin": "1234",
    "billing": {
      "entity_type": "JURIDICA",
      "id_number": "J-123456789",
      "name": "Distribuidora Aguas del Valle, C.A.",
      "address": "Av. Libertador, Torre Norte, Piso 3, Caracas",
      "phone": "+58 212 5551234"
    }
  },
  "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

GET /admin/orders/cancellation-reasons

Admin cancellation-reason catalogue, for the reason dropdown when forcing a CANCELLED status.

Response 200

{ "reasons": [ { "code": "ADMIN_FRAUD", "label": "Sospecha de fraude" } ] }

PATCH /admin/orders/{orderId}/force-status

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 free-text note; 10–500 chars
reason_code string no an admin CancellationReason code (ADMIN_FRAUD, ADMIN_TEST, ADMIN_SUPPORT, ADMIN_DUPLICATE, ADMIN_OTHER); stored only when cancelling

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

GET /admin/orders/{orderId}/refund

Returns the ceiling for a refund and the order's refund when one exists. An order has at most one refund.

Response 200

{
  "refundable_usd": 10.1,
  "refund": {
    "id": 7,
    "order_id": 42,
    "kind": "PARTIAL",
    "status": "CONFIRMED",
    "amount_usd": 4,
    "amount_bs": 160,
    "bcv_rate": 40,
    "beneficiary": {
      "name": "María Pérez",
      "id_number": "V12345678",
      "phone": "04125551234",
      "bank_code": "0102"
    },
    "reference": "998877",
    "last_error": null,
    "created_at": "2026-09-12T14:00:00+00:00",
    "confirmed_at": "2026-09-12T14:02:00+00:00"
  },
  "saved_account": {
    "id_number": "V12345678",
    "phone": "04125551234",
    "bank_code": "0102"
  }
}
Field Type Description
refundable_usd number Maximum refundable, in USD
refund object|null null when the order has no refund
refund.kind string FULL or PARTIAL
refund.status string PENDING, DISPERSING, SENT, CONFIRMED or FAILED
refund.amount_usd number Amount refunded, in USD
refund.amount_bs number Amount sent, in bolĂ­vares
refund.bcv_rate number BCV rate used, Bs per USD
refund.beneficiary object name, id_number, phone, bank_code
refund.reference string|null Bank reference, present once confirmed
refund.last_error string|null Provider's reason when FAILED
saved_account object|null The client's saved Pago MĂłvil account to pre-fill the form; null when none. id_number, phone, bank_code

Errors

Status Body When
404 { "error": "OrderNotFound" } No order with that id

POST /admin/orders/{orderId}/refund

Refunds the client over Pago MĂłvil. The beneficiary's data is required: the platform holds no bank details for clients.

Request body

Field Type Required Rules
kind string yes FULL or PARTIAL
amountUSD number yes when kind=PARTIAL min:0.01; prohibited when kind=FULL
idNumber string yes 6–10 digits, optional V/E/J/G/P prefix; separators are stripped
phone string yes Venezuelan mobile, 04125551234 or 584125551234; separators are stripped
bankCode string yes exactly 4 digits

Response 201 — { "refund": { … } }, same shape as the GET.

Errors

Status Body When
404 { "error": "OrderNotFound" } No order with that id
422 { "error": "RefundNotAllowed", "message": "…" } The order already has a refund, has nothing refundable, the amount exceeds what the client paid, or there is no stored BCV rate
422 validation errors Body fails the rules above