Transport
Trips, routes, vehicles, positions and the geo services behind them.
42 endpoints
bearer driver_app beneficiary_app device credential
point-to-point (or multi-via) polyline + totals.
Request body Field Type Constraints stopsobject[] required min items 2 · max items 25
Response Returns { "data": … }; this endpoint's payload is not yet
pinned to a named shape.
bearer driver_app beneficiary_app device credential
nearest road point for marker placement.
Query parameters Name Type Constraints latnumber required min -90 · max 90 lngnumber required min -180 · max 180
Response Returns { "data": … }; this endpoint's payload is not yet
pinned to a named shape.
bearer driver_app beneficiary_app device credential
optimal dropoff order. The first stop is the driver (OSRM `source=first`); `destination=last` anchors the end at the final stop (the school run).
Request body Field Type Constraints stopsobject[] required min items 2 · max items 25 destinationstring optional any lastroundtripboolean optional —
Response Returns { "data": … }; this endpoint's payload is not yet
pinned to a named shape.
bearer driver_app beneficiary_app transport.trip_manage device credential
Request body Field Type Constraints idstring (uuid) required — trip_plan_idstring | null optional — route_idstring | null optional — zone_idstring | null optional — bus_zone_idstring | null optional — directionstring required home_to_school school_to_home customstarted_atstring (date-time) required —
Response Returns { "data": TripWrite }.
Field Type Constraints idstring (uuid) required — statusstring required — directionstring required — started_atstring | null required — ended_atstring | null required — expected_ridersinteger required — boarded_ridersinteger required — polylinestring | null required — planned_polylinestring | null required — ridersobject[] required —
PATCH
/v3/app/trip/{id}
#
bearer driver_app beneficiary_app transport.trip_manage device credential
Path parameters Request body Field Type Constraints statusstring required completed cancelledended_atstring (date-time) required —
Response Returns { "data": TripWrite }.
Field Type Constraints idstring (uuid) required — statusstring required — directionstring required — started_atstring | null required — ended_atstring | null required — expected_ridersinteger required — boarded_ridersinteger required — polylinestring | null required — planned_polylinestring | null required — ridersobject[] required —
POST
/v3/app/trip/{id}/event
#
bearer driver_app beneficiary_app transport.trip_manage device credential
alerts / SOS (terra-api §4.6).
Path parameters Request body Field Type Constraints kindstring required geofence_enter geofence_exit approach_alert arrival_alert overspeed route_deviation sos breakdown +2 more severitystring | null optional info warning criticalmessagestring | null optional max length 2000 detailsstring | null optional max length 2000 occurred_atstring (date-time) required — client_event_idstring | null optional — student_idstring | null optional —
Response Returns { "data": TripEvent }.
Field Type Constraints idstring (uuid) required — kindstring required — severitystring | null required — messagestring | null required — student_idstring | null required — occurred_atstring (date-time) required —
POST
/v3/app/trip/{id}/position
#
bearer driver_app beneficiary_app device credential gzip
batched, dedup by (trip_id, recorded_at) (terra-api §4.2).
Path parameters Headers Header Notes Content-Encodingoptional Optional request-body compression; compressed cap 1 MB, decompressed cap 10 MB.
Request body Field Type Constraints positionsobject[] required min items 1 · max items 500
Response Returns { "data": PositionBatch }.
Field Type Constraints acceptedinteger required — duplicatesinteger required — staleinteger optional — next_position_secondsinteger required —
POST
/v3/app/trip/{id}/rider
#
bearer driver_app beneficiary_app device credential gzip
non-tap attendance, per-item results (terra-api §4.3).
Path parameters Headers Header Notes Content-Encodingoptional Optional request-body compression; compressed cap 1 MB, decompressed cap 10 MB.
Request body Field Type Constraints eventsRiderEventInput []required min items 1 · max items 500
Response
POST
/v3/app/trip/{id}/share-link
#
bearer driver_app beneficiary_app parent_app device credential
expiring public tracking link (terra-api §4.10).
Path parameters Response Returns { "data": … }; this endpoint's payload is not yet
pinned to a named shape.
GET
/v3/geocode/reverse
#
bearer driver_app beneficiary_app admin_web device credential
Query parameters Name Type Constraints latnumber required min -90 · max 90 lngnumber required min -180 · max 180
Response Returns { "data": … }; this endpoint's payload is not yet
pinned to a named shape.
GET
/v3/portal/fuel-price
#
bearer admin_web device credential
Response Returns { "data": FuelPrice }.
Field Type Constraints dieselobject | null required — diesel. price_kes_per_lnumber required — diesel. effective_datestring required — petrolobject | null required — petrol. price_kes_per_lnumber required — petrol. effective_datestring required — staleboolean required —
bearer admin_web device credential
Query parameters Name Type Constraints qstring | null optional max length 120 cursorstring | null optional max length 200 per_pageinteger | null optional min 1 · max 500
Response Returns { "data": [WebRoute ] } with meta.next_cursor for the next page.
Field Type Constraints idstring (uuid) required — zone_idstring (uuid) required — namestring required — descriptionstring | null required — statusstring required — est_durationinteger | null required — est_distance_mnumber | null required — rider_countinteger required — row_versioninteger required —
bearer admin_web transport.plan device credential
Request body Field Type Constraints namestring required max length 120 descriptionstring | null optional max length 500 zone_idstring (uuid) required — est_duration_hoursinteger | null optional min 0 · max 23 est_duration_minutesinteger | null optional min 0 · max 59 est_distance_valuenumber | null optional min 0 · max 999 est_distance_unitstring | null optional km malert_settingsarray | null optional — alert_settings. high_delay_minutesinteger | null optional min 1 · max 480 alert_settings. medium_delay_minutesinteger | null optional min 1 · max 480
Response Returns { "data": WebRouteDetail }.
Field Type Constraints idstring (uuid) required — zone_idstring (uuid) required — namestring required — descriptionstring | null required — statusstring required — est_durationinteger | null required — est_distance_mnumber | null required — row_versioninteger required — alert_settingsobject required — alert_settings. high_delay_minutesinteger required — alert_settings. medium_delay_minutesinteger required — rider_countinteger required — stopsRouteStopRow []required — trip_plansobject[] required —
POST
/v3/portal/route-assignment/apply
#
bearer admin_web transport.plan device credential
Request body Field Type Constraints assignmentsobject[] required min items 1
Response Returns { "data": RouteAssignmentApply }.
Field Type Constraints appliedstring (uuid) [] required — applied_routesobject[] required — failedobject[] required —
DELETE
/v3/portal/route-assignment/draft
#
bearer admin_web transport.plan device credential
"Run another assignment" (2026-08-05 feedback, live-testing follow-up) — explicitly discards the tenant's current draft, since apply() no longer does this itself. See WebPlanningService::discardRouteAssignmentDraft().
Response Returns { "data": RouteAssignmentDraftPatchResult }.
Field Type Constraints okboolean required —
GET
/v3/portal/route-assignment/draft
#
bearer admin_web transport.plan device credential
The tenant's current Route Assignment draft, if any — see WebPlanningService::getRouteAssignmentDraft().
Response Returns { "data": RouteAssignmentDraft }.
Field Type Constraints foundboolean required — computed_atstring | null required — assignmentsobject[] required — skipped_vehiclesobject[] required — skipped_studentsobject[] required — savingsany required — depotany required — student_locationsobject[] required — applied_atstring | null required — applied_resultany required —
PATCH
/v3/portal/route-assignment/draft
#
bearer admin_web transport.plan device credential
Renames a route within the tenant's current draft — see WebPlanningService::patchRouteAssignmentDraft().
Request body Field Type Constraints vehicle_zone_idstring (uuid) required — route_namestring required max length 120
Response Returns { "data": RouteAssignmentDraftPatchResult }.
Field Type Constraints okboolean required —
POST
/v3/portal/route-assignment/measure
#
bearer admin_web transport.plan device credential
Re-measures a drag-edited roster split ahead of apply() — see WebPlanningService::measureRouteAssignment().
Request body Field Type Constraints assignmentsobject[] required min items 1
Response Returns { "data": RouteAssignmentMeasure }.
Field Type Constraints assignmentsobject[] required — savingsany required —
POST
/v3/portal/route-assignment/suggest
#
bearer admin_web transport.plan device credential
Request body Field Type Constraints vehicle_zone_idsstring (uuid) [] optional —
Response Returns { "data": RouteAssignmentSuggestion }.
Field Type Constraints assignmentsobject[] required — skipped_vehiclesobject[] required — skipped_studentsobject[] required — savingsany required — depotobject required — depot. latnumber required — depot. lngnumber required — student_locationsobject[] required — computed_atstring (date-time) required —
DELETE
/v3/portal/route/{id}
#
bearer admin_web transport.plan device credential
Path parameters Response Returns { "data": … }; this endpoint's payload is not yet
pinned to a named shape.
GET
/v3/portal/route/{id}
#
bearer admin_web device credential
Path parameters Response Returns { "data": WebRouteDetail }.
Field Type Constraints idstring (uuid) required — zone_idstring (uuid) required — namestring required — descriptionstring | null required — statusstring required — est_durationinteger | null required — est_distance_mnumber | null required — row_versioninteger required — alert_settingsobject required — alert_settings. high_delay_minutesinteger required — alert_settings. medium_delay_minutesinteger required — rider_countinteger required — stopsRouteStopRow []required — trip_plansobject[] required —
PATCH
/v3/portal/route/{id}
#
bearer admin_web transport.plan device credential
Path parameters Request body Field Type Constraints update_maskstring[] required min items 1 · max items 9 expected_row_versioninteger required min 1 namestring | null optional max length 120 descriptionstring | null optional max length 500 statusstring | null optional active inactive archivedzone_idstring | null optional — est_duration_hoursinteger | null optional min 0 · max 23 est_duration_minutesinteger | null optional min 0 · max 59 est_distance_valuenumber | null optional min 0 · max 999 est_distance_unitstring | null optional km malert_settingsarray | null optional — alert_settings. high_delay_minutesinteger | null optional min 1 · max 480 alert_settings. medium_delay_minutesinteger | null optional min 1 · max 480
Response Returns { "data": WebRouteDetail }.
Field Type Constraints idstring (uuid) required — zone_idstring (uuid) required — namestring required — descriptionstring | null required — statusstring required — est_durationinteger | null required — est_distance_mnumber | null required — row_versioninteger required — alert_settingsobject required — alert_settings. high_delay_minutesinteger required — alert_settings. medium_delay_minutesinteger required — rider_countinteger required — stopsRouteStopRow []required — trip_plansobject[] required —
PUT
/v3/portal/route/{id}/stops
#
bearer admin_web transport.plan device credential
Path parameters Request body Field Type Constraints stopsobject[] required max items 100
Response Returns { "data": WebRouteDetail }.
Field Type Constraints idstring (uuid) required — zone_idstring (uuid) required — namestring required — descriptionstring | null required — statusstring required — est_durationinteger | null required — est_distance_mnumber | null required — row_versioninteger required — alert_settingsobject required — alert_settings. high_delay_minutesinteger required — alert_settings. medium_delay_minutesinteger required — rider_countinteger required — stopsRouteStopRow []required — trip_plansobject[] required —
bearer admin_web device credential
Query parameters Name Type Constraints datestring | null optional — statusstring | null optional scheduled active completed cancelled abandonedroute_idstring | null optional — cursorstring | null optional max length 200 per_pageinteger | null optional min 1 · max 500
Response Returns { "data": [WebTrip ] } with meta.next_cursor for the next page.
Field Type Constraints idstring (uuid) required — statusstring required — directionstring required — started_atstring | null required — ended_atstring | null required — routeany required — vehicleany required — driverstring required — ridersobject required — riders. expectedinteger required — riders. boardedinteger required — alerts_openinteger required — locationsobject[] required —
GET
/v3/portal/trip-plan
#
bearer admin_web device credential
Query parameters Name Type Constraints route_idstring | null optional — cursorstring | null optional max length 200 per_pageinteger | null optional min 1 · max 500
Response Returns { "data": [WebTripPlan ] } with meta.next_cursor for the next page.
Field Type Constraints idstring (uuid) required — route_idstring | null required — labelstring | null required — directionstring required — schedulestring required — start_timestring | null required — scheduled_onstring | null required — recurring_daysarray | null required — checkout_counts_as_rollcallboolean required — statusstring required — row_versioninteger required — stops_staleboolean required —
POST
/v3/portal/trip-plan
#
bearer admin_web transport.plan device credential
Request body Field Type Constraints route_idstring (uuid) required — labelstring required max length 120 directionstring | null optional home_to_school school_to_home customschedulestring | null optional once recurringstart_timestring | null optional — scheduled_onstring | null optional — recurring_daysinteger[] optional max items 7 checkout_counts_as_rollcallboolean | null optional —
Response Returns { "data": WebTripPlan }.
Field Type Constraints idstring (uuid) required — route_idstring | null required — labelstring | null required — directionstring required — schedulestring required — start_timestring | null required — scheduled_onstring | null required — recurring_daysarray | null required — checkout_counts_as_rollcallboolean required — statusstring required — row_versioninteger required — stops_staleboolean required —
DELETE
/v3/portal/trip-plan/{id}
#
bearer admin_web transport.plan device credential
Path parameters Response Returns { "data": … }; this endpoint's payload is not yet
pinned to a named shape.
PATCH
/v3/portal/trip-plan/{id}
#
bearer admin_web transport.plan device credential
Path parameters Request body Field Type Constraints update_maskstring[] required min items 1 · max items 9 expected_row_versioninteger required min 1 route_idstring | null optional — labelstring | null optional max length 120 directionstring | null optional home_to_school school_to_home customschedulestring | null optional once recurringstart_timestring | null optional — scheduled_onstring | null optional — recurring_daysinteger[] optional max items 7 checkout_counts_as_rollcallboolean | null optional — statusstring | null optional active suspended archived
Response Returns { "data": WebTripPlan }.
Field Type Constraints idstring (uuid) required — route_idstring | null required — labelstring | null required — directionstring required — schedulestring required — start_timestring | null required — scheduled_onstring | null required — recurring_daysarray | null required — checkout_counts_as_rollcallboolean required — statusstring required — row_versioninteger required — stops_staleboolean required —
GET
/v3/portal/trip-plan/{id}/measure
#
bearer admin_web transport.plan device credential
The currently-saved order's own distance/duration/road geometry — no reordering. Lets the manifest screen show a real baseline cost the moment it loads, not only after Auto-order runs.
Path parameters Response Returns { "data": MeasuredOrder }.
Field Type Constraints distance_mnumber required — duration_snumber required — polylinestring | null required — depotobject required — depot. latnumber required — depot. lngnumber required —
POST
/v3/portal/trip-plan/{id}/measure-order
#
bearer admin_web transport.plan device credential
the same distance/duration/road geometry measure-saved-order's GET sibling reports, but for a CALLER-SUPPLIED sequence rather than the currently-saved one. Never writes anything — what lets a manual drag/arrow reorder in progress show its own real cost/savings before Save.
Path parameters Request body Field Type Constraints student_idsstring (uuid) [] required max items 200
Response Returns { "data": MeasuredOrder }.
Field Type Constraints distance_mnumber required — duration_snumber required — polylinestring | null required — depotobject required — depot. latnumber required — depot. lngnumber required —
GET
/v3/portal/trip-plan/{id}/rider
#
bearer admin_web device credential
the ordered manifest with navigation stops.
Path parameters Response Returns { "data": [PlanRider ] } with meta.next_cursor for the next page.
Field Type Constraints student_idstring (uuid) required — namestring required — gradestring | null required — positioninteger required — pickup_stop_idstring | null required — dropoff_stop_idstring | null required — latnumber | null required — lngnumber | null required —
PUT
/v3/portal/trip-plan/{id}/rider-order
#
bearer admin_web transport.plan device credential
Path parameters Request body Field Type Constraints student_idsstring (uuid) [] required max items 200 stopsobject[] optional max items 200 from_optimizerboolean | null optional —
Response Returns { "data": [PlanRider ] } with meta.next_cursor for the next page.
Field Type Constraints student_idstring (uuid) required — namestring required — gradestring | null required — positioninteger required — pickup_stop_idstring | null required — dropoff_stop_idstring | null required — latnumber | null required — lngnumber | null required —
GET
/v3/portal/trip-plan/{id}/suggest-order
#
bearer admin_web transport.plan device credential
the ML platform's suggested visiting sequence for this plan's current riders. Never writes anything; the caller pre-fills the editable manual order with this and only setRiderOrder() (a separate, explicit save) persists it — "editable defaults, not locked" (Faith, 2026-07-21).
Path parameters Response Returns { "data": SuggestedOrder }.
Field Type Constraints ridersPlanRider []required — optimal_distance_mnumber required — optimal_duration_snumber required — optimal_polylinestring | null required — saved_distance_mnumber | null required — saved_duration_snumber | null required — distance_saved_mnumber | null required — duration_saved_snumber | null required — depotobject required — depot. latnumber required — depot. lngnumber required —
GET
/v3/portal/trip/{id}
#
bearer admin_web device credential
Path parameters Response Returns { "data": WebTripDetail }.
Field Type Constraints idstring (uuid) required — statusstring required — directionstring required — started_atstring | null required — ended_atstring | null required — routeany required — driverstring | null required — ridersobject[] required — eventsobject[] required — checkpointsRouteStopRow []required — polylinestring | null required — planned_polylinestring | null required —
POST
/v3/portal/trip/{id}/end
#
bearer admin_web transport.trip_manage device credential
The dispatcher's end (docs/terra-api.md §11.6, absorbs the v2 `trips/update/{id}` PUT): a school admin closes a stuck or forgotten trip from the web board. Same terminal transition as the driver's PATCH — driver-ownership waived, tenant fence intact, idempotent on an already-ended trip.
Path parameters Request body Field Type Constraints statusstring required completed cancelledended_atstring (date-time) required —
Response Returns { "data": TripEndResult }.
Field Type Constraints idstring (uuid) required — statusstring required — ended_atstring (date-time) required —
GET
/v3/portal/trip/{id}/replay
#
bearer admin_web device credential
The trip-history replay artifact — v2's trip file {polyline, timestamps, metadata}, now an authenticated read built lazily from trip_positions (docs/terra-api.md §11.6). Only a finished trip replays; its path is immutable, so browsers may cache hard.
Path parameters Response Returns { "data": TripReplay }.
Field Type Constraints polylinestring required — timestampsstring | null[] required — metadataarray required — points_countinteger required — snappedboolean required — generated_atstring (date-time) required —
GET
/v3/portal/trip/{id}/route-comparison
#
bearer admin_web device credential
"Did the driver follow the plan, what could've been saved" — Trip History's optimizer-comparison ask, same completed-trip gate as replay(). Best-effort: a comparison the ML platform can't produce (down, or not enough usable stop/GPS data on this trip) responds 404 rather than 500 — matching ml.md's fallback posture at the boundary the web board actually sees.
Path parameters Response Returns { "data": RouteComparison }.
Field Type Constraints optimal_orderstring[] required — stop_locationsRouteComparisonStop []required — optimal_distance_mnumber | null required — optimal_duration_snumber | null required — optimal_polylinestring | null required — actual_distance_mnumber required — actual_duration_snumber required — distance_saved_mnumber required — duration_saved_snumber required —
GET
/v3/portal/trip/{id}/route-segments
#
bearer admin_web device credential
Segment-by-segment: did the driver take a good ROAD between each real, consecutive stop — routeComparison()'s sibling, but Route Path's question ("was the driver efficient here") rather than Stop Ordering's ("was this the best order"). Same completed-trip gate and best-effort 404-not-500 posture as routeComparison().
Path parameters Response Returns { "data": RouteSegments }.
Field Type Constraints segmentsobject[] required —
public 30,1
Path parameters Response Returns { "data": … }; this endpoint's payload is not yet
pinned to a named shape.
bearer driver_app beneficiary_app parent_app admin_web device credential
the Redis-backed snapshot (terra-api §4.5); a tenant-scoped read (driver, dashboard, and the parent app's §6.4 all read the same shape). The SSE stream lands with the realtime slice.
Path parameters Response Returns { "data": TripLive }.
Field Type Constraints trip_idstring (uuid) required — statusstring required — boarded_ridersinteger | null optional — expected_ridersinteger | null optional — last_positionany optional — eta_schoolstring | null optional — planned_polylinestring | null optional — stop_etasobject[] optional — next_poll_secondsinteger optional —
POST
/v3/trip/{id}/handover
#
bearer driver_app beneficiary_app admin_web transport.trip_manage device credential
breakdown reassignment (terra-api §4.12).
One capability, two principals (lego L1b): a handset hands over only its OWN trip, while the console — the dispatcher taking the breakdown phone call (uber UB-21c) — has the driver requirement waived by its surface. The fence is identical either way; only the ownership rule is per-principal.
Path parameters Request body Field Type Constraints target_trip_idstring (uuid) required — occurred_atstring (date-time) required —
Response Returns { "data": TripHandover }.
Field Type Constraints moved_ridersinteger required — target_trip_idstring (uuid) required — dead_trip_statusstring required —
POST
/v3/webhook/geofence
#
public 300,1
Response Returns { "data": … }; this endpoint's payload is not yet
pinned to a named shape.