The crowd-sourced filling-station directory: find nearby stations, read their
live status, post traffic-light reports, and chat on a station's comment wall.
Paths are relative to the /api/v1 prefix; all routes require
Authorization: Bearer {token}.
See Common errors. Comment lists are cursor-paginated — see Pagination.
| Method | URI | Role | Description |
|---|---|---|---|
GET |
/stations/nearby |
any | Nearby stations within a radius (throttled) |
GET |
/stations |
any | Nearby stations (alias of /stations/nearby) |
POST |
/stations/report |
DRIVER | Report a station's status |
GET |
/stations/{stationId} |
any | Station detail with recent reports |
POST |
/stations/{stationId}/reports |
DRIVER | Report a station (REST alias of /stations/report) |
GET |
/stations/{stationId}/comments |
any | Station comment wall (cursor) |
POST |
/stations/{stationId}/comments |
DRIVER | Post a comment (throttled) |
DELETE |
/stations/{stationId}/comments/{commentId} |
DRIVER | Delete your own comment |
{stationId} and {commentId} are numeric. Reporting and commenting are
restricted to drivers; everyone authenticated can read.
Stations within a bounding box around a point. /stations is an exact alias.
Rate limit: 20 requests / minute.
Query
| Field | Type | Required | Rules |
|---|---|---|---|
lat |
number | yes | between −90 and 90 |
lng |
number | yes | between −180 and 180 |
radiusKm |
number | no | > 0, ≤ 100; defaults to 10 |
type |
string | no | WATER or FUEL |
Response 200
{
"stations": [
{
"id": 7,
"name": "E/S Las Mercedes",
"address": "Av. Principal, Las Mercedes",
"latitude": 10.487,
"longitude": -66.88,
"city": "Caracas",
"station_type": "WATER",
"is_verified": true,
"is_active": true,
"current_status": {
"current_color": "GREEN",
"confidence": 0.8,
"report_count": 4,
"avg_wait_minutes": 12,
"last_report_at": "2026-06-26T12:00:00+00:00"
}
}
]
}
current_status is null until the station has at least one report.
Alias of GET /stations/nearby — identical query, response,
and 20 req/min throttle.
A driver posts a traffic-light report for a station. Re-reporting the same station
is blocked by a 15-minute cooldown per driver. POST /stations/{stationId}/reports
is the REST alias (it supplies stationId from the path instead of the body).
Request body
| Field | Type | Required | Rules |
|---|---|---|---|
stationId |
integer | yes | required (supplied by path on the /reports alias) |
color |
string | yes | GREEN, YELLOW, RED, or CLOSED |
waitMinutes |
integer | no | 0–240 |
comment |
string | no | ≤ 280 chars |
driverLat |
number | yes | between −90 and 90 |
driverLng |
number | yes | between −180 and 180 |
Response 200
{
"report": {
"id": 51,
"station_id": 7,
"driver_id": 3,
"color": "YELLOW",
"wait_minutes": 20,
"comment": "Cola moderada",
"driver_lat": 10.49,
"driver_lng": -66.85,
"created_at": "2026-06-26T12:05:00+00:00"
},
"confidence": 0.6
}
Errors
| Status | Body | When |
|---|---|---|
404 |
{ "error": "DriverNotFound" } |
The caller has no driver profile |
429 |
{ "error": "Cooldown", "message": "…", "retryAfterMinutes": 15 } |
Reported this station within the cooldown window |
REST alias of POST /stations/report: stationId comes from
the path, the rest of the body and all responses/errors are identical.
Full station detail plus its 20 most recent reports.
Response 200
{
"station": {
"id": 7,
"name": "E/S Las Mercedes",
"address": "Av. Principal, Las Mercedes",
"latitude": 10.487,
"longitude": -66.88,
"city": "Caracas",
"station_type": "WATER",
"is_verified": true,
"is_active": true,
"current_status": { "current_color": "GREEN", "confidence": 0.8, "report_count": 4 }
},
"reports": [
{
"id": 51,
"color": "YELLOW",
"waitMinutes": 20,
"comment": "Cola moderada",
"createdAt": "2026-06-26T12:05:00+00:00"
}
]
}
Errors
| Status | Body | When |
|---|---|---|
404 |
{ "error": "StationNotFound" } |
Unknown or inactive station |
Cursor-paginated comment wall, newest first. See Pagination → cursor-based.
Query
| Field | Type | Required | Rules |
|---|---|---|---|
limit |
integer | no | 1–100; defaults to 30 |
cursor |
string | no | opaque cursor from next_cursor |
Response 200
{
"items": [
{
"id": 12,
"station_id": 7,
"author": { "id": 3, "name": "Carlos Rodríguez", "role": "DRIVER" },
"content": "Ahora mismo sin cola.",
"created_at": "2026-06-26T12:10:00+00:00"
}
],
"next_cursor": "eyJpZCI6MTF9",
"has_more": true
}
Errors
| Status | Body | When |
|---|---|---|
404 |
{ "error": "StationNotFound", "message": "…" } |
Unknown or inactive station |
A driver posts a comment to the wall. Rate limit: 10 requests / minute.
Request body
| Field | Type | Required | Rules |
|---|---|---|---|
content |
string | yes | 1–500 chars |
Response 201
{
"comment": {
"id": 13,
"station_id": 7,
"author": { "id": 3, "name": "Carlos Rodríguez", "role": "DRIVER" },
"content": "Acaban de abrir.",
"created_at": "2026-06-26T12:12:00+00:00"
}
}
Errors
| Status | Body | When |
|---|---|---|
404 |
{ "error": "StationNotFound", "message": "…" } |
Unknown or inactive station |
Deletes a comment. Only the comment's author may delete it.
Response 200 — { "ok": true }.
Errors
| Status | Body | When |
|---|---|---|
403 |
{ "error": "Forbidden", "message": "…" } |
The caller is not the comment's author |
404 |
{ "error": "NotFound", "message": "…" } |
Unknown comment |
# Nearby water stations
curl "/api/v1/stations/nearby?lat=10.487&lng=-66.88&radiusKm=5&type=WATER" \
-H "Authorization: Bearer {token}"
# Driver: report a station (plain endpoint)
curl -X POST /api/v1/stations/report \
-H "Authorization: Bearer {driver_token}" \
-H "Content-Type: application/json" \
-d '{"stationId": 7, "color": "YELLOW", "waitMinutes": 20, "driverLat": 10.49, "driverLng": -66.85}'
# Driver: comment on a station
curl -X POST /api/v1/stations/7/comments \
-H "Authorization: Bearer {driver_token}" \
-H "Content-Type: application/json" \
-d '{"content": "Ahora mismo sin cola."}'