This guide is for the frontend developer building the new Assured Express Operations Dashboard.
The frontend should use the new API namespace only:
/api/operations/v1/
Do not use the legacy /api/occ/ endpoints for the new dashboard.
This dashboard uses the existing backend system only.
No new models are being introduced for the dashboard. If a business concept does not already have reliable data in the current system, the frontend should not display it as a real metric.
Currently unavailable as first-class dashboard data:
- Hire-purchase lease agreements
- Lease payment history
- Missed lease payment reconciliation
- Persisted KM integrity audit records
- GPS daily KM ingestion records
The backend may expose computed KM visibility from existing VehicleAsset fields, but it does not store new KM integrity records for this dashboard.
All endpoints require authentication.
Use the existing backend auth mechanism:
Authorization: Bearer <access_token>The backend determines dashboard scope from the authenticated user.
The frontend should not manually enforce operational scope. The API already scopes responses.
Supported scopes:
coo: full business visibility.vertical_lead: assigned vertical and zones under that vertical.zone_captain: assigned zone only.service: service-key access, full visibility.unknown: authenticated user without an operational scope.
Call this endpoint after login:
GET /api/operations/v1/me/Use it to configure available navigation and filters.
Example response:
{
"id": "user-uuid",
"name": "Ops Manager",
"role": "coo",
"is_global": true,
"vertical_ids": [],
"zone_ids": [],
"permissions": {
"can_view_all": true,
"can_view_km_integrity": true
}
}Dashboard endpoints that support time filtering accept:
?period=<value>
Current supported values:
todayyesterdaythis_weekpast_7_daysthis_monthlast_monththis_yearYYYY-MM
Month dropdown mapping:
Jan -> period=2026-01
Feb -> period=2026-02
Mar -> period=2026-03
Apr -> period=2026-04
May -> period=2026-05
Jun -> period=2026-06
Jul -> period=2026-07
Aug -> period=2026-08
Sep -> period=2026-09
Oct -> period=2026-10
Nov -> period=2026-11
Dec -> period=2026-12
If period is omitted, the backend defaults to the current month.
List endpoints usually return:
{
"period": "this_month",
"count": 10,
"results": []
}Some dashboard aggregate endpoints return a single object instead of results.
Errors use the existing DRF style:
{
"detail": "Authentication credentials were not provided."
}or:
{
"detail": "You do not have access to this zone."
}GET /api/operations/v1/me/Returns authenticated user identity, role, scope, and dashboard permissions.
Use this before rendering the dashboard shell.
GET /api/operations/v1/dashboard/summary/?period=this_monthReturns high-level KPIs:
- orders
- revenue
- rider counts
- merchant counts
- target revenue attainment where targets exist
- computed flag counts
Use this for the top dashboard cards.
GET /api/operations/v1/dashboard/flags/?limit=50
GET /api/operations/v1/flags/?limit=50Returns computed operational flags from existing fields.
Current flag sources:
- Rider is offline but current speed indicates movement.
- Vehicle GPS KM and completed-order KM differ by more than 10%.
These are computed at request time. They are not persisted records.
GET /api/operations/v1/verticals/?period=this_month
GET /api/operations/v1/verticals/{vertical_id}/?period=this_month
GET /api/operations/v1/verticals/{vertical_id}/zones/?period=this_monthUse these for:
- vertical cards
- vertical detail page
- zones under a selected vertical
The API scopes the list based on the current user.
GET /api/operations/v1/zones/?period=this_month
GET /api/operations/v1/zones/{zone_id}/?period=this_month
GET /api/operations/v1/zones/{zone_id}/riders/?period=this_monthUse these for:
- zone table
- zone performance page
- rider list inside a zone
Zone detail includes nested rider summaries.
GET /api/operations/v1/riders/{rider_id}/?period=this_month
GET /api/operations/v1/riders/{rider_id}/performance/?period=this_month
GET /api/operations/v1/riders/{rider_id}/daily-activity/?period=this_month
GET /api/operations/v1/riders/{rider_id}/vehicle/Use these for:
- rider profile drawer/page
- performance panel
- day-by-day activity chart
- vehicle assignment panel
GET /api/operations/v1/leaderboards/?period=this_monthReturns rankings for:
- zones
- riders
- verticals
Current ranking logic:
- zones and verticals rank by revenue
- riders rank by completed orders
GET /api/operations/v1/orders/?period=this_month
GET /api/operations/v1/orders/analytics/?period=this_monthSupported filters for order list:
status=Done
zone_id=<uuid>
rider_id=<uuid>
merchant_id=<user_uuid>
limit=100
Use /orders/ for an operational order table.
Use /orders/analytics/ for status/source/day trend charts.
GET /api/operations/v1/merchants/?period=this_monthSupported filters:
zone_id=<uuid>
activity_status=active|watch|inactive
status=active|watch|inactive
is_partner=true|false
limit=100
Use this for merchant visibility by zone and activity state.
GET /api/operations/v1/jumia-hubs/?period=this_monthSupported filters:
zone_id=<uuid>
This endpoint uses existing RelayNode records. It does not create a separate Jumia hub model.
Use this for:
- hub list
- assigned rider counts
- hub-to-zone visibility
- hub order rollups
GET /api/operations/v1/vehicles/
GET /api/operations/v1/vehicles/?status=active
GET /api/operations/v1/vehicles/?status=inactiveReturns existing VehicleAsset data:
- assignment
- plate number
- asset ID
- engine status
- telemetry location
- speed
- total distance
- distance today
- completed-order KM today
- computed KM variance
GET /api/operations/v1/km-visibility/
GET /api/operations/v1/km-integrity/
GET /api/operations/v1/km-integrity/?status=failed
GET /api/operations/v1/km-integrity/?status=passed
GET /api/operations/v1/km-integrity/?status=unavailableThis uses existing VehicleAsset fields:
distance_todaydeliveries_km_today
Status values:
passed: both values are available and variance is within 10%.failed: both values are available and variance is above 10%.unavailable: there is not enough KM data to compare.
No new GPS records are created by these endpoints.
Admin console endpoints are write-enabled and must only be shown to users where:
{
"role": "coo",
"is_global": true
}or users with a dispatcher admin profile.
Base path:
/api/operations/v1/admin/
Create or update zones:
GET /api/operations/v1/admin/zones/
POST /api/operations/v1/admin/zones/
GET /api/operations/v1/admin/zones/{zone_id}/
PUT /api/operations/v1/admin/zones/{zone_id}/
PATCH /api/operations/v1/admin/zones/{zone_id}/Zone payload fields:
{
"name": "Ajah",
"description": "Ajah and nearby areas",
"vertical": "vertical-uuid",
"zone_lead": "vertical-lead-uuid-or-null",
"center_lat": 6.4698,
"center_lng": 3.5852,
"radius_km": 5,
"is_active": true
}Create or update hubs:
GET /api/operations/v1/admin/hubs/
POST /api/operations/v1/admin/hubs/
GET /api/operations/v1/admin/hubs/{hub_id}/
PUT /api/operations/v1/admin/hubs/{hub_id}/
PATCH /api/operations/v1/admin/hubs/{hub_id}/Hub payload fields:
{
"name": "NG-AJAH-STATION",
"address": "Ajah, Lagos",
"latitude": 6.4698,
"longitude": 3.5852,
"zone": "zone-uuid",
"catchment_radius_km": 0.5,
"hub_captain_name": "Captain Name",
"hub_captain_phone": "080...",
"is_active": true
}Assign a hub to a zone by patching the hub zone field:
PATCH /api/operations/v1/admin/hubs/{hub_id}/{
"zone": "zone-uuid"
}Set zone targets:
GET /api/operations/v1/admin/zone-targets/
POST /api/operations/v1/admin/zone-targets/
GET /api/operations/v1/admin/zone-targets/{target_id}/
PUT /api/operations/v1/admin/zone-targets/{target_id}/
PATCH /api/operations/v1/admin/zone-targets/{target_id}/Target payload:
{
"zone": "zone-uuid",
"month": "2026-05-01",
"target_orders": 2000,
"target_revenue": "600000.00"
}The backend normalizes month to the first day of the month.
Assign vertical leads:
GET /api/operations/v1/admin/vertical-leads/
POST /api/operations/v1/admin/vertical-leads/
PATCH /api/operations/v1/admin/vertical-leads/{assignment_id}/Payload:
{
"user": "user-uuid",
"vertical": "vertical-uuid",
"is_active": true
}Assign zone captains:
GET /api/operations/v1/admin/zone-captains/
POST /api/operations/v1/admin/zone-captains/
PATCH /api/operations/v1/admin/zone-captains/{assignment_id}/Payload:
{
"user": "user-uuid",
"zone": "zone-uuid",
"is_active": true
}Assign riders to hubs:
PATCH /api/operations/v1/admin/riders/{rider_id}/hub/Payload:
{
"hub": "hub-uuid"
}To remove a rider from a hub:
{
"hub": null
}Main dashboard:
GET /me/GET /dashboard/summary/?period=<period>GET /flags/?limit=50GET /leaderboards/?period=<period>GET /verticals/?period=<period>GET /zones/?period=<period>
Vertical detail:
GET /verticals/{id}/?period=<period>GET /verticals/{id}/zones/?period=<period>
Zone detail:
GET /zones/{id}/?period=<period>GET /zones/{id}/riders/?period=<period>GET /merchants/?zone_id=<id>&period=<period>GET /jumia-hubs/?zone_id=<id>&period=<period>
Rider detail:
GET /riders/{id}/?period=<period>GET /riders/{id}/performance/?period=<period>GET /riders/{id}/daily-activity/?period=<period>GET /riders/{id}/vehicle/
Orders page:
GET /orders/?period=<period>GET /orders/analytics/?period=<period>
Vehicle/KM page:
GET /vehicles/GET /km-visibility/GET /km-integrity/
Admin console:
GET/POST /admin/zones/GET/PATCH /admin/zones/{id}/GET/POST /admin/hubs/GET/PATCH /admin/hubs/{id}/GET/POST /admin/zone-targets/GET/PATCH /admin/zone-targets/{id}/GET/POST /admin/vertical-leads/PATCH /admin/vertical-leads/{id}/GET/POST /admin/zone-captains/PATCH /admin/zone-captains/{id}/PATCH /admin/riders/{id}/hub/
Use empty states when results is empty.
Do not display lease or hire-purchase values unless a future endpoint explicitly provides them.
For KM integrity:
- Show
unavailableas a neutral state. - Show
failedas critical. - Show
passedas healthy.
For role scope:
- Hide global filters when
/me/returnsis_global=false. - A vertical lead may only receive one vertical.
- A zone captain may only receive one zone.
For periods:
- Keep the selected period in route/query state.
- Pass the same
periodvalue to all dashboard endpoints that support it. - For month dropdowns, send
YYYY-MM, not month names.
Backend hardening should add tests for:
period=todayperiod=yesterdayperiod=this_weekperiod=past_7_daysperiod=this_monthperiod=last_monthperiod=this_yearperiod=YYYY-MM- COO/admin scope
- vertical lead scope
- zone captain scope
- empty data responses
- order filters
- merchant filters
- KM integrity
passed - KM integrity
failed - KM integrity
unavailable
Backend work completed for the screenshot period selector:
period=this_yearis supported by the parser.- Tests have been added for
this_yearandYYYY-MM.