Admin cities

Manage the city catalogue (operating areas with a bounding box) and the admin↔city assignment that drives every other admin endpoint's scope. Paths are relative to the /api/v1 prefix; these are back-office endpoints that require an admin token.

Requires an admin bearer token (see Admin auth). Super-admin only.

See Common errors.

Endpoints

Method URI Access Description
GET /admin/cities Super admin List all cities with their admin counts
POST /admin/cities Super admin Create a city
PATCH /admin/cities/{cityId} Super admin Update a city
POST /admin/cities/{cityId}/admins Super admin Assign an admin to a city
DELETE /admin/cities/{cityId}/admins/{adminId} Super admin Unassign an admin from a city

GET /admin/cities

Lists every city (ordered by name) with its assigned-admin count.

Response 200

{
  "items": [
    {
      "id": 1,
      "name": "Caracas",
      "slug": "caracas",
      "is_active": true,
      "center_lat": 10.4806,
      "center_lng": -66.9036,
      "radius_km": 25.0,
      "bbox": { "lat_min": 10.3, "lat_max": 10.6, "lng_min": -67.1, "lng_max": -66.7 },
      "admins_count": 3
    }
  ]
}

POST /admin/cities

Creates a city. The bounding box must be well-formed (lat_max >= lat_min, lng_max >= lng_min).

Request body

Field Type Required Rules
name string yes ≀ 120 chars, unique among cities
is_active boolean no defaults to true
center_lat number yes between βˆ’90 and 90
center_lng number yes between βˆ’180 and 180
radius_km number yes > 0, ≀ 500
lat_min number yes between βˆ’90 and 90
lat_max number yes between βˆ’90 and 90, >= lat_min
lng_min number yes between βˆ’180 and 180
lng_max number yes between βˆ’180 and 180, >= lng_min

Response 201 β€” { "city": { … } } (same shape as a list item, admins_count 0).


PATCH /admin/cities/{cityId}

Partial update.

Request body

Field Type Required Rules
name string no ≀ 120 chars, unique (excluding this city)
is_active boolean no β€”
center_lat number no between βˆ’90 and 90
center_lng number no between βˆ’180 and 180
radius_km number no > 0, ≀ 500
lat_min number no between βˆ’90 and 90
lat_max number no between βˆ’90 and 90, >= lat_min
lng_min number no between βˆ’180 and 180
lng_max number no between βˆ’180 and 180, >= lng_min

Response 200 β€” { "city": { … } }.

Errors

Status Body When
404 { "error": "CityNotFound" } Unknown city id

POST /admin/cities/{cityId}/admins

Assigns an admin to the city (idempotent β€” re-assigning is a no-op).

Request body

Field Type Required Rules
admin_id integer yes must be an existing admin

Response 200 β€” { "ok": true, "city": { … } } (the city object with an updated admins_count).

Errors

Status Body When
404 { "error": "CityNotFound" } Unknown city id

DELETE /admin/cities/{cityId}/admins/{adminId}

Removes the admin↔city assignment.

Response 200

{ "ok": true }

Errors

Status Body When
404 { "error": "CityNotFound" } Unknown city id