NavKids API
The NavKids API serves the driver app, the school dashboard and the public landing page. This page is the reference for developers building against it.
Basics
- Base URL:
https://api.investika.co.ke/api/v1(staging) - Format: JSON in and out. Send
Accept: application/json. - Time: every timestamp is ISO 8601 with an offset, in the school's time
zone (
Africa/Nairobi). Devices send the time they recorded something; the server adds the time it received it. - Envelope: a success is
{"data": ...}; lists addmeta(page,per_page,total). A failure is{"error": {"code", "message", "details?"}}.
Authentication
Sign in with POST /auth/login, sending identifier (an email, or a driver's
Driver ID), password and device_name. The reply holds a bearer token:
Authorization: Bearer <token>
Each device gets its own token, which does not expire; it ends when the user
signs out, a device is revoked, or the password changes. A driver may also send
assistant_id, their co-driver's ID.
Tenancy and identity always come from the token, never from the request body:
a school_id in a body is ignored, and another school's records answer 404.
Errors
| Status | Code | Meaning |
|---|---|---|
| 401 | unauthenticated |
No token, or an invalid one |
| 401 | invalid_credentials |
Sign-in details are wrong |
| 403 | insufficient_permission |
Signed in, but without the permission this needs |
| 403 | account_inactive |
The account or school is suspended |
| 404 | not_found |
Does not exist, or belongs to another school |
| 409 | trip_already_active, students_still_aboard, no_assignment, resource_in_use, assignment_conflict, primary_guardian_required |
The request conflicts with the current state; details explains |
| 422 | validation_failed, import_validation_failed |
details lists each field's or row's problem |
| 429 | too_many_attempts |
Too many requests; slow down and retry |
| 500 | server_error |
Something failed on our side |
Rate limits
| Kind | Limit |
|---|---|
| Sign-in and password reset | 6 a minute, per address and per identifier |
| Reads | 120 a minute |
| Writes | 60 a minute |
| Location batches | 120 a minute (generous: a phone catching up after no signal sends a burst) |
| Launch registrations | 5 an hour, per address |
| Emergencies | Never limited |
Retries and offline devices
Every write from a device carries a client_event_id (a UUID the device
makes). Sending the same write again returns the original result and creates
nothing new, so a phone can retry freely after losing signal. Location batches
count duplicates instead of failing.
Driver endpoints
| Method | Path | Notes |
|---|---|---|
| GET | /driver/assignment |
Today's runs (morning, afternoon, evening) with stops and the children expected at each |
| POST | /driver/trips |
Start a trip; works for trips started offline |
| GET | /driver/trips/{trip} |
The trip's state, for an app restarted mid-trip |
| POST | /driver/trips/{trip}/locations |
Up to 500 GPS points per batch |
| POST | /driver/trips/{trip}/stops/{stop}/arrive |
Arrival at a stop; out-of-order arrivals are flagged, not refused |
| POST | /driver/trips/{trip}/attendance |
Boarded, alighted or absent, in batches; exceptions are flagged, not refused |
| POST | /driver/trips/{trip}/end |
Refused with 409 while children are recorded on board, unless confirmed |
| POST | /driver/emergencies |
Raise an emergency; never refused, never rate-limited |
| GET, PATCH | /driver/profile |
The driver's profile; contact details are editable |
| GET | /driver/alerts |
Messages from the school |
| POST | /driver/alerts/{alert}/acknowledge |
Mark a message read |
Account endpoints
| Method | Path | Notes |
|---|---|---|
| POST | /auth/login |
Sign in |
| POST | /auth/logout |
End this device's session |
| GET | /auth/sessions |
This user's devices |
| DELETE | /auth/sessions/{id} |
Sign a device out |
| POST | /auth/password/forgot |
Texts a 6-digit code; the same reply whether or not the account exists |
| POST | /auth/password/reset |
Set a new password with that code |
| PUT | /auth/password |
Change the password while signed in |
School administration endpoints
For school staff. Lists accept page and per_page (up to 200).
| Method | Path | Notes |
|---|---|---|
| GET, POST, PATCH, DELETE | /school/vehicles |
Buses; expiring insurance or inspection is flagged |
| GET, POST, PATCH, DELETE | /school/drivers |
New drivers are texted their Driver ID and an activation code |
| POST | /school/drivers/{id}/invite |
Send a fresh activation code |
| GET, POST, PATCH, DELETE | /school/attendants |
Co-drivers |
| GET, POST, PATCH | /school/routes |
Routes, morning or home-bound |
| GET, POST, PUT | /school/routes/{id}/stops |
Changing stops creates a new route version; past trips keep theirs |
| GET, POST, PATCH, DELETE | /school/students |
Filter by name, class, route and status |
| POST | /school/students/import |
Check a CSV; .../import/{id}/confirm saves it, all or nothing |
| GET, POST, PATCH, DELETE | /school/students/{id}/guardians |
Parents and guardians, with one primary contact |
| GET, POST, PATCH | /school/assignments |
Driver, bus, route and run; warns about double-booking and capacity |
| GET | /school/trips, /school/trips/active |
Trip history and the live board, problems first |
| GET | /school/trips/{id}, .../locations |
One trip in full, and its GPS trail |
| GET | /school/attendance |
Each child on each trip, including who received them at drop-off |
| GET, POST | /school/emergencies, .../acknowledge, .../resolve |
Emergencies, acknowledged and resolved by named staff |
| GET | /school/reports/{type} |
attendance, trips or emergencies, as JSON or CSV |
| GET | /school/audit |
Every change, and every view of a child's data |
Real-time
The API publishes live events over a Pusher-compatible WebSocket (Laravel
Reverb). Subscribe to a private channel through
POST /broadcasting/auth with your bearer token; every subscription is
authorised on its own.
| Channel | Events |
|---|---|
private-trip.{id} |
trip.started, location.updated, stop.arrived, attendance.recorded, trip.ended |
private-school.{id} |
trip.started, trip.ended, emergency.raised, emergency.updated, trip.dark, trip.tracking_restored, trip.students_aboard |
On shared hosting the WebSocket server is off; the dashboard polls instead.
Public endpoints
No account needed.
| Method | Path | Notes |
|---|---|---|
| GET | /status |
System status, uptime and recent incidents; 503 while down. Also shown at / |
| POST | /registrations |
Launch registration from the landing page |
| GET | /up (no /api/v1 prefix) |
A plain health check for monitors |
