Driver bidding and the client's accept/reject of offers. A driver either takes an
order at its published price or sends a counter-offer (a custom price bid); each
attempt creates an offer and the client confirms the one they
want. Paths are relative to the /api/v1 prefix; all routes require
Authorization: Bearer {token}.
The order payload and its role filtering are documented under Orders → the order object. See also the order lifecycle.
See Common errors.
| Method | URI | Role | Description |
|---|---|---|---|
GET |
/orders/{orderId}/offer |
DRIVER | The order as the driver sees it, to bid on |
POST |
/orders/{orderId}/accept |
DRIVER | Take the order at its published price |
POST |
/orders/{orderId}/driver-accept |
DRIVER | Alias of /accept |
POST |
/orders/{orderId}/counter-offer |
DRIVER | Bid a custom price |
POST |
/orders/{orderId}/offers |
DRIVER | Alias of /counter-offer |
POST |
/orders/offers/{offerId}/accept |
CLIENT | Accept a specific driver offer |
POST |
/counter-offers/{offerId}/accept |
CLIENT | Alias of /orders/offers/{offerId}/accept |
POST |
/orders/{orderId}/accept-counter |
CLIENT | Accept the standing counter-offer by order id |
POST |
/counter-offers/{offerId}/reject |
CLIENT | Reject a driver offer |
Driver bids are returned under an offer key. Money
is exposed as offer_price_usd (decimal) alongside offer_price_cents.
{
"offer": {
"id": 17,
"order_id": 42,
"driver_id": 3,
"offer_price_cents": 2000,
"estimated_minutes": 20,
"available_liters": 5000,
"status": "PENDING",
"over_capacity": false,
"expires_at": "2026-06-26T12:05:00.000000Z",
"driver_latitude": 10.4895,
"driver_longitude": -66.8805,
"created_at": "2026-06-26T12:00:00.000000Z",
"updated_at": "2026-06-26T12:00:00.000000Z",
"offer_price_usd": 20.0
}
}
driver_latitude / driver_longitude snapshot the driver's position at bid time
(null if no recent GPS).
When the bid exceeds the driver's remaining liters, the offer carries
over_capacity: true and the response adds a warning string.
The order as the bidding driver sees it (DRIVER-filtered, with the client's public
contact). Only available while the order is biddable
(BROADCASTING/COUNTER_OFFERED). The payload is returned at the top level, not
wrapped under order.
Response 200
{
"id": 42,
"status": "BROADCASTING",
"latitude": 10.487,
"longitude": -66.88,
"address": "Av. Principal, Las Mercedes",
"liters_requested": 5000,
"water_type": "POTABLE",
"payment_method": "CASH_USD",
"base_price_usd": 20.0,
"driver_gross_usd": 16.4,
"driver_solidary_usd": 0.16,
"driver_receives_usd": 16.24,
"notes": null,
"client": { "id": 1, "name": "Ana MartĂnez", "phone": "+584241000001" },
"created_at": "2026-06-26T12:00:00.000000Z"
}
Client money fields (client_solidary_*, client_pays_*), platform fields, and
delivery_pin are stripped for the driver.
Errors
| Status | Body | When |
|---|---|---|
404 |
{ "error": "OrderNotFound", "message": "La orden ya no está disponible." } |
Order is no longer biddable |
A request for a non-existent order id resolves as a generic 404 (see
Common errors).
Take the order at its published price — creates a candidacy at the order's base
price. The client confirms later which candidate wins. POST /orders/{orderId}/driver-accept is an alias with identical behavior.
Request body
| Field | Type | Required | Rules |
|---|---|---|---|
estimatedMinutes |
integer | no | 1–240 |
force |
boolean | no | post even if the order exceeds remaining liters (assumes refill) |
driverGross is ignored here; to bid a custom price use /counter-offer.
Response 201 — { "offer": { … } }, plus warning when over_capacity is
set. See the offer object.
Errors
| Status | Body | When |
|---|---|---|
409 |
{ "error": "InsufficientLiters", "message": "…", "remaining_liters": 3000, "requested_liters": 5000 } |
Not enough available liters and force not set |
409 |
{ "error": "Conflict", "message": "…" } |
Order not open for bids, already taken, or driver ineligible |
/orders/{orderId}/acceptis an alias of/orders/{orderId}/driver-accept(identical behavior).
Bid a custom price for the order. Omitting driverGross posts at the order's
base price. POST /orders/{orderId}/offers is an alias with identical behavior.
Request body
| Field | Type | Required | Rules |
|---|---|---|---|
driverGross |
number | no | > 0, ≤ 100000; omit to bid the base price |
estimatedMinutes |
integer | no | 1–240 |
force |
boolean | no | post even if the order exceeds remaining liters |
Response 201 — { "offer": { … } }, plus warning when over_capacity is
set.
Errors
| Status | Body | When |
|---|---|---|
409 |
{ "error": "InsufficientLiters", "message": "…", "remaining_liters": 3000, "requested_liters": 5000 } |
Not enough available liters and force not set |
409 |
{ "error": "Conflict", "message": "…" } |
Order not open for bids, already taken, or driver ineligible |
/orders/{orderId}/counter-offeris an alias of/orders/{orderId}/offers(identical behavior).
The client accepts a specific driver offer; the order is confirmed to that
driver. POST /counter-offers/{offerId}/accept is an alias with identical behavior.
Response 200 — { "order": { … } } (CLIENT view).
Errors
| Status | Body | When |
|---|---|---|
404 |
{ "error": "NotFound", "message": "La contraoferta no existe." } |
Unknown offer |
409 |
{ "error": "InsufficientLiters", "message": "…", "remaining_liters": 3000, "requested_liters": 5000 } |
Driver no longer has enough liters for this order |
403 |
{ "error": "Forbidden", "message": "…" } |
Caller may not accept this offer |
409 |
{ "error": "Conflict", "message": "…" } |
Offer expired or already taken |
/orders/offers/{offerId}/acceptis an alias of/counter-offers/{offerId}/accept(identical behavior).
The client accepts the standing counter-offer by order id (rather than offer id). Confirms the order to the offering driver.
Response 200 — { "order": { … } } (CLIENT view).
Errors
| Status | Body | When |
|---|---|---|
409 |
{ "error": "Conflict", "message": "…" } |
No acceptable counter-offer, or the order is not in a confirmable state |
The client rejects a driver offer.
Response 200 — { "ok": true }.
Errors
| Status | Body | When |
|---|---|---|
404 |
{ "error": "NotFound", "message": "La contraoferta no existe." } |
Unknown offer |
403 |
{ "error": "Forbidden", "message": "…" } |
Caller may not reject this offer |
409 |
{ "error": "Conflict", "message": "…" } |
Offer not in a rejectable state |
# Driver: take the order at its published price (with an ETA)
curl -X POST /api/v1/orders/42/accept \
-H "Authorization: Bearer {driver_token}" \
-H "Content-Type: application/json" \
-d '{"estimatedMinutes": 20}'
# Driver: bid a custom price
curl -X POST /api/v1/orders/42/counter-offer \
-H "Authorization: Bearer {driver_token}" \
-H "Content-Type: application/json" \
-d '{"driverGross": 18.5, "estimatedMinutes": 25}'
# Client: accept a specific offer → order is confirmed to that driver
curl -X POST /api/v1/orders/offers/17/accept -H "Authorization: Bearer {client_token}"