Drivers

Driver-side (cisternero) operations: going online, performance and earnings stats, discovering nearby orders, and the driver's own order history and receipts. Paths are relative to the /api/v1 prefix; every route requires Authorization: Bearer {token} and the DRIVER role.

See Common errors. The customer-facing order flow lives under Orders; see also the order lifecycle and driver wallet & cash debt.

Endpoints

Method URI Role Description
GET /drivers/me/stats DRIVER Earnings stats (week / month / all-time)
GET /driver/stats DRIVER Performance stats by period (+ rating)
GET /driver/surplus DRIVER My surplus listings with status
GET /driver/available-orders DRIVER Nearby broadcasting orders
POST /driver/online DRIVER Go online / offline
GET /driver/orders/active DRIVER My current active order
GET /driver/orders/{orderId}/receipt DRIVER Driver receipt for a delivered order
GET /driver/orders DRIVER My order history (cursor)

Endpoints that resolve the driver from the token return 404 DriverNotFound when the caller has no driver profile. Money fields end in _usd (decimal).


GET /drivers/me/stats

Aggregated delivery stats over fixed windows, plus the all-time totals and the driver-bonus counters.

Response 200

{
  "week": { "trips": 8, "liters": 40000, "earningsUSD": 130.0, "solidaryUSD": 1.3 },
  "month": { "trips": 32, "liters": 160000, "earningsUSD": 520.0, "solidaryUSD": 5.2 },
  "allTime": {
    "trips": 120,
    "liters": 600000,
    "solidaryUSD": 19.5,
    "bonusQualifyingTrips": 45,
    "bonusMinReceives": 40
  }
}

Errors

Status Body When
404 { "error": "DriverNotFound" } The caller has no driver profile

GET /driver/stats

Performance for a single period, with the driver's rating. acceptance_rate is currently always null.

Query

Field Type Required Rules
period string no day, week, month, total, or all; defaults to all

Response 200 — for a specific period (e.g. ?period=week):

{
  "rating": { "average": 4.8, "total": 96 },
  "acceptance_rate": null,
  "period": "week",
  "stats": { "trips": 8, "liters": 40000, "earningsUSD": 130.0, "solidaryUSD": 1.3 },
  "previous": { "trips": 6, "liters": 30000, "earningsUSD": 98.0, "solidaryUSD": 0.98 }
}

With period=all, the response instead carries day, week, month, and total breakdowns side by side. previous (a comparison window) is omitted for period=total.

Errors

Status Body When
404 { "error": "DriverNotFound" } The caller has no driver profile

GET /driver/surplus

All of the caller's surplus listings (active, reserved, expired, cancelled) with a status. See Surplus for the listing shape.

Response 200

{
  "listings": [
    {
      "id": 5,
      "available_liters": 5000,
      "remaining_liters": 0,
      "price_per_liter_usd": 0.02,
      "total_price_usd": 100.0,
      "address": "Av. Principal, Las Mercedes",
      "expires_at": "2026-06-26T14:00:00+00:00",
      "status": "RESERVADA"
    }
  ]
}

status is one of ACTIVA, RESERVADA, EXPIRADA, or CANCELADA.


GET /driver/available-orders

Nearby BROADCASTING orders the driver can still serve, ordered by distance. Requires the driver to be ACTIVE and online.

Query

Field Type Required Rules
latitude number yes between −90 and 90
longitude number yes between −180 and 180

Response 200

{
  "items": [
    {
      "id": 42,
      "address": "Av. Principal, Las Mercedes",
      "latitude": 10.487,
      "longitude": -66.88,
      "liters_requested": 5000,
      "water_type": "POTABLE",
      "base_price_usd": 20.0,
      "notes": null,
      "distance_km": 1.2,
      "expires_at": "2026-06-26T12:05:00+00:00",
      "created_at": "2026-06-26T12:00:00+00:00"
    }
  ]
}

Errors

Status Body When
404 { "error": "DriverNotFound" } The caller has no driver profile
403 { "error": "DriverNotActive", "message": "…" } Driver status is not ACTIVE
403 { "error": "DriverOffline", "message": "Debe estar online." } Driver is offline

POST /driver/online

Toggles the driver online or offline. Going online requires location and a liters declaration, and checks that the driver is ACTIVE, under the cash-debt cap, and not exceeding the vehicle's capacity.

Request body

Field Type Required Rules
online boolean yes
latitude number conditional required when online=true; between −90 and 90
longitude number conditional required when online=true; between −180 and 180
liters integer conditional required when online=true; ≥ 1

Response 200

{
  "driver": {
    "id": 3,
    "isOnline": true,
    "availableLiters": 5000,
    "remainingLiters": 5000,
    "currentLat": 10.49,
    "currentLng": -66.85,
    "lastLocationAt": "2026-06-26T11:55:00+00:00"
  }
}

Errors

Status Body When
404 { "error": "DriverNotFound" } The caller has no driver profile
403 { "error": "DriverNotActive", "message": "…" } Driver status is not ACTIVE
403 { "error": "DebtExceedsLimit", "message": "…", "cashDebtUsd": 25.0, "cashDebtCapUsd": 20.0 } Cash debt exceeds the cap
422 { "error": "NoVehicle", "message": "…" } No vehicle with a registered capacity
422 { "error": "LitersExceedCapacity", "message": "…", "capacityLiters": 5000 } Declared liters exceed the tank capacity

GET /driver/orders/active

The driver's current active order, or null. The payload is the order in the DRIVER view (see Orders → the order object); the delivery_pin is hidden until the order is paid (CONFIRMED/IN_PROGRESS/ARRIVED).

Response 200{ "order": { … } } or { "order": null }.


GET /driver/orders/{orderId}/receipt

The driver's receipt for a delivered order they served — the driver-side money split only (no client amounts).

Response 200

{
  "receipt": {
    "order_id": 42,
    "status": "DELIVERED",
    "delivered_at": "2026-06-26T12:40:00+00:00",
    "liters_requested": 5000,
    "actual_liters": 5000,
    "water_type": "POTABLE",
    "payment_method": "CASH_USD",
    "breakdown": {
      "driver_gross_usd": 16.4,
      "driver_solidary_usd": 0.16,
      "driver_receives_usd": 16.24
    },
    "client": { "id": 1, "name": "Ana Martínez", "phone": "+584241000001" }
  }
}

Errors

Status Body When
404 { "error": "DriverNotFound" } The caller has no driver profile
404 { "error": "OrderNotFound" } Unknown order
403 { "error": "Forbidden" } The order was not served by this driver
409 { "error": "OrderNotDelivered", "message": "…" } Order not delivered yet

GET /driver/orders

Cursor-paginated history of the driver's orders, newest first. See Pagination → cursor-based.

Query

Field Type Required Rules
status string no one of WAITING_FOR_PAYMENT, CONFIRMED, IN_PROGRESS, ARRIVED, DELIVERED, CANCELLED, EXPIRED
date_from date no filters created_at
date_to date no after or equal to date_from; filters created_at
limit integer no 1–100; defaults to 25
cursor string no opaque cursor from next_cursor

Response 200

{
  "items": [
    {
      "id": 42,
      "status": "DELIVERED",
      "liters_requested": 5000,
      "water_type": "POTABLE",
      "address": "Av. Principal, Las Mercedes",
      "driver_receives_usd": 16.24,
      "payment_method": "CASH_USD",
      "client": { "id": 1, "name": "Ana Martínez" },
      "created_at": "2026-06-26T12:00:00+00:00",
      "delivered_at": "2026-06-26T12:40:00+00:00"
    }
  ],
  "next_cursor": "eyJpZCI6NDF9",
  "has_more": true
}

Errors

Status Body When
404 { "error": "DriverNotFound" } The caller has no driver profile

Examples

# Go online with 5000 L at the current location
curl -X POST /api/v1/driver/online \
  -H "Authorization: Bearer {driver_token}" \
  -H "Content-Type: application/json" \
  -d '{"online": true, "latitude": 10.49, "longitude": -66.85, "liters": 5000}'

# Discover nearby broadcasting orders
curl "/api/v1/driver/available-orders?latitude=10.49&longitude=-66.85" \
  -H "Authorization: Bearer {driver_token}"

# This week's performance
curl "/api/v1/driver/stats?period=week" -H "Authorization: Bearer {driver_token}"