Driver API Driver availability, location, trip states and payout settings.
Interactive test console Paste a dedicated development token below. It stays in this browser tab and is sent only to the API endpoint you test.Bearer token
Fixed playground responses These are saved Chromium captures for Onboard Driver · CRZ-ZZZ-0001 · captured 2026-08-28. They remain visible before testing. Paste a bearer token to replace safe GET responses with the current authenticated user's live data; mutations still require an explicit request.
Live Socket events - no polling for rides, notifications or chat Connect once after authentication and keep the connection for the full app session. Socket events are the immediate UI signal; REST is only the recovery path after reconnect.
Step What the app should do When to connect After driver authentication, keep one socket connection alive for the app session. Immediate use Use socket events for offers, trip updates and chat. Do not poll while connected. Recovery fetch GET /driver/offers, GET /driver/trips/active, GET /driver/messages and GET /driver/trips/:id/rider-location once after reconnect or app resume.Trip room After the driver has a trip context, subscribe with socket.emit('trip:subscribe', { tripId }).
Connection pattern
const socket = io(BASE_URL, {
transports: ['websocket'],
auth: { token: accessToken }
});
socket.on('connect', () => setRealtimeConnected(true));
socket.on('disconnect', () => setRealtimeConnected(false));
socket.on('connect_error', showRealtimeError);
socket.on('${event}', (payload) => onRealtimeEvent('${event}', payload));
socket.on('${event}', (payload) => onRealtimeEvent('${event}', payload));
socket.on('${event}', (payload) => onRealtimeEvent('${event}', payload));
socket.on('${event}', (payload) => onRealtimeEvent('${event}', payload));
socket.on('${event}', (payload) => onRealtimeEvent('${event}', payload));
socket.on('${event}', (payload) => onRealtimeEvent('${event}', payload));
socket.on('${event}', (payload) => onRealtimeEvent('${event}', payload));
socket.on('${event}', (payload) => onRealtimeEvent('${event}', payload));
socket.on('${event}', (payload) => onRealtimeEvent('${event}', payload));
socket.on('${event}', (payload) => onRealtimeEvent('${event}', payload)); Live event contract
Event Important payload Render immediately driver:trip_offertripId, offer.id, expiresAtMANUAL: open accept/decline. AUTO: wait for trip:state_updated confirmation; do not show a decision UI. driver:trip_offer_expiredtripId, offerId, reasonClose the offer immediately and mark it expired. driver:trip_offer_retractedtripId, offerId, reasonClose the offer: the rider cancelled matching or another driver accepted. trip:state_updatedtripId, status, tripRender the confirmed automatic/manual assignment and newest trip state. rider:location_updatedtripId, location.latitude, location.longitude, location.recordedAtMove the rider marker before pickup only. rider:location_stoppedtripIdRemove the moving-rider marker and retain the booked pickup pin. message:receivedtrip_id, body, created_atAppend the chat message immediately. call:incomingcallId, tripId, status, version, expiresAtOpen the incoming-call screen and offer Accept or Decline. call:state_changedcallId, tripId, status, versionRender CONNECTING or ACTIVE; request your own join token after acceptance. call:endedcallId, tripId, status, endedAt, versionDisconnect LiveKit and close the call screen.
Reconnect recovery
Make the recovery fetches only on the first reconnect after a disconnect or app resume. Merge that server state into local state, then keep rendering live socket events.
Token lifecycle: disconnect on sign-out. If the access token expires, refresh it and reconnect with the new token.
Driver-rider voice calls (LiveKit) Use REST for decisions and recovery, Socket.IO for ringing/state events, and LiveKit for microphone audio. There is no SSE endpoint. Calls are available only when LIVEKIT_ENABLED=true and the trip has the authenticated rider plus its currently assigned driver.
Connection Endpoint / event Frontend action Backend REST POST /api/v1/trips/:id/callsCaller starts; show RINGING until the answer deadline. Send a fresh Idempotency-Key. Socket.IO io(BASE_URL, { auth: { token: accessToken }, transports: ['websocket'] })Connect after login; the server joins your private user room automatically. Do not emit a call-start socket action. Socket.IO call:incomingRecipient opens incoming-call UI and calls accept or decline REST endpoint before expiresAt. Socket.IO call:state_changedOn CONNECTING, both apps request their own join-token. On ACTIVE, show the in-call state. LiveKit WebRTC room.connect(data.serverUrl, data.token)Connect directly to LiveKit and enable microphone; use LiveKit connection/track events for actual audio status, mute and speaker controls. Socket.IO call:endedStop microphone, disconnect the LiveKit room and close the call UI. REST recovery GET /api/v1/trips/:id/calls/activeFetch after reconnect/app resume; a null response means no active call.
Payload: events carry { callId, tripId, status, version, callerUserId, recipientUserId, expiresAt, acceptedAt, activeAt, endedAt, createdAt } where IDs are public-prefixed. Ignore events with an older version for the same call. The join-token response alone contains serverUrl, token, identity and expiresAt; never log or persist the token.
Ringing deadline: the backend uses a 120-second default. The caller may request ringTimeoutSeconds from 10 to 300 when starting a call; render the authoritative backend-provided expiresAt countdown. The frontend cannot extend an already-created call.
Flow: start → call:incoming → accept → call:state_changed CONNECTING → both join-token requests → both LiveKit connects → verified webhook sets ACTIVE → either end → call:ended. Decline, the expiresAt timeout, a terminal trip or 60-minute maximum closes the call. A backgrounded app needs registered Expo push notifications plus a recovery GET when it opens; a socket alone cannot wake it reliably.
Setup: mobile apps install their LiveKit platform SDK, request microphone permission, configure native audio routing/background behavior and keep the token only in memory. Backend needs LIVEKIT_URL, LIVEKIT_API_KEY, LIVEKIT_API_SECRET, an applied Prisma migration, and the signed LiveKit webhook configured at /api/v1/livekit/webhook. Server credentials never go into the app.
Frontend integration guide Use the endpoint cards below as the source of truth for request methods, authentication and test payloads. Keep credentials in secure storage and send bearer tokens only over HTTPS.
Required availability order
POST /api/v1/driver/location with current GPS. Location freshness is checked by readiness.PATCH /api/v1/driver/dispatch-preferences. Manual without a range: {"offerMode":"MANUAL","usePickupRadius":false}. Range-bound auto-accept: {"offerMode":"AUTO","usePickupRadius":true,"pickupRadiusKm":10}.GET /api/v1/driver/readiness; show and resolve every blocker.PATCH /api/v1/driver/status with {"status":"ONLINE"}.Connect Socket.IO for the entire app session, then render offers and trip changes from events. Auto-accept rule: it is disabled by default and never unbounded. The driver sets the pickup range themselves. Enabling AUTO without an enabled range returns 409 AUTO_ACCEPT_REQUIRES_PICKUP_RANGE. To turn the range off, switch to MANUAL in the same update. The server, not the app timer, decides eligibility and acceptance.
Live activity: connect Socket.IO with auth.token = accessToken. In MANUAL mode, treat driver:trip_offer as an interrupting offer, fetch GET /driver/offers for display/recovery details, and count down to expiresAt; then call POST /driver/offers/:id/respond. In AUTO mode, render trip:state_updated as the confirmation that the range-qualified offer was assigned. Handle driver:trip_offer_expired, driver:trip_offer_retracted and message:received. After every reconnect, refetch active offers, active trips and messages.
Mutating requests should include a unique Idempotency-Key. Render API status and error codes explicitly, and refetch state after reconnecting.
REST response contract Every response is JSON: { success, data, error }. When success is true, read data. When it is false, use error.code for app logic and error.message for safe UI text.
HTTP Meaning Frontend action 200Request succeeded. Render data. 201Resource created. Persist its returned ID/state. 202Accepted for asynchronous work. Show pending; it is not authentication. 400Invalid request or business rule. Show error.message and field details. 401Token missing, expired or invalid. Refresh session or sign in. 403Access denied. Do not retry. 404Unavailable or hidden resource. Return safely and refresh state. 409State conflict/duplicate/expired resource. Refetch; do not blindly retry. 422Semantically invalid input. Highlight the field. 429Rate limited. Back off, respecting Retry-After. 500Unexpected server failure. Offer a safe retry.
Stable codes: VALIDATION_ERROR, UNAUTHORIZED, FORBIDDEN, NOT_FOUND, TRIP_ACCESS_DENIED, RIDER_ACTION_RATE_LIMITED and OTP_RATE_LIMITED. Each endpoint guide adds any relevant business codes.
POST /api/v1/auth/driver/onboarding/otp/request
Public
Request first-time driver OTP
Endpoint guide What to send, parse and expect Why it exists Starts first-time driver identity verification with the fleet-issued assigned ID.
Before you call Use only for a driver who has not set a passcode. Driver OTP is delivered by phone only.
Request fields assignedId uses CRZ-ABC-0001 format; channel must be phone.
What to parse Show the masked phone destination and the ten-minute countdown.
Expected result 202 accepts delivery. A completed driver receives DRIVER_ALREADY_ONBOARDED.
Important The response never exposes the production OTP.
Request structure and code samples Node.js · Python · PHP · cURL Replace angle-bracket values with returned values. Use the raw access token only in the Authorization header.
Node.js const response = await fetch(BASE_URL + '/api/v1/auth/driver/onboarding/otp/request', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Idempotency-Key': crypto.randomUUID()
},
body: JSON.stringify({"assignedId":"CRZ-ABC-0001","channel":"phone"})
});
const result = await response.json(); Python payload = json.loads(r'''{"assignedId":"CRZ-ABC-0001","channel":"phone"}''')
response = requests.post(BASE_URL + '/api/v1/auth/driver/onboarding/otp/request',
headers={'Idempotency-Key': str(uuid.uuid4())},
json=payload)
result = response.json() PHP $payload = <<<'JSON'
{"assignedId":"CRZ-ABC-0001","channel":"phone"}
JSON;
$ch = curl_init($baseUrl . '/api/v1/auth/driver/onboarding/otp/request');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Idempotency-Key: <uuid>'],
CURLOPT_POSTFIELDS => $payload,
CURLOPT_RETURNTRANSFER => true,
]); cURL curl -X POST '<base-url>/api/v1/auth/driver/onboarding/otp/request' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: <uuid>' \
--data '{"assignedId":"CRZ-ABC-0001","channel":"phone"}'
{
"success": true,
"data": {
"accepted": true,
"channel": "phone",
"destination": "+234 *** *** 692",
"expiresInSeconds": 600
},
"error": null
}
POST /api/v1/auth/driver/onboarding/otp/verify
Public
Verify OTP and receive passcode setup token
Endpoint guide What to send, parse and expect Why it exists Verifies the six-digit OTP and opens the passcode-setup step.
Before you call Request the OTP first.
Request fields Send assignedId and the six-digit code.
What to parse Keep setupToken only in memory, route to Set Passcode, then Confirm Passcode. Compare both entries locally and submit the passcode once.
Expected result 200 returns setupToken, expiresInSeconds and nextStep PASSCODE; it does not authenticate the driver.
Important The setup token expires after 15 minutes and is single-use.
Request structure and code samples Node.js · Python · PHP · cURL Replace angle-bracket values with returned values. Use the raw access token only in the Authorization header.
Node.js const response = await fetch(BASE_URL + '/api/v1/auth/driver/onboarding/otp/verify', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Idempotency-Key': crypto.randomUUID()
},
body: JSON.stringify({"assignedId":"CRZ-ABC-0001","code":"123456"})
});
const result = await response.json(); Python payload = json.loads(r'''{"assignedId":"CRZ-ABC-0001","code":"123456"}''')
response = requests.post(BASE_URL + '/api/v1/auth/driver/onboarding/otp/verify',
headers={'Idempotency-Key': str(uuid.uuid4())},
json=payload)
result = response.json() PHP $payload = <<<'JSON'
{"assignedId":"CRZ-ABC-0001","code":"123456"}
JSON;
$ch = curl_init($baseUrl . '/api/v1/auth/driver/onboarding/otp/verify');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Idempotency-Key: <uuid>'],
CURLOPT_POSTFIELDS => $payload,
CURLOPT_RETURNTRANSFER => true,
]); cURL curl -X POST '<base-url>/api/v1/auth/driver/onboarding/otp/verify' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: <uuid>' \
--data '{"assignedId":"CRZ-ABC-0001","code":"123456"}'
{
"success": true,
"data": {
"setupToken": "<driver-setup-token>",
"expiresInSeconds": 900,
"nextStep": "PASSCODE"
},
"error": null
}
POST /api/v1/auth/driver/onboarding/passcode
Public
Set confirmed six-digit passcode
Endpoint guide What to send, parse and expect Why it exists Sets the confirmed six-digit driver passcode and completes authentication setup.
Before you call Verify OTP, collect the passcode twice, and submit only after the two local entries match.
Request fields Send setupToken and one six-digit passcode. Never send a confirmation copy.
What to parse Store access/refresh tokens securely, request location permission, send the first location, then show setup success and open Driver Home.
Expected result 200 returns the driver session, nextStep LOCATION and status OFFLINE.
Important Only a bcrypt hash is stored; the setup token is consumed atomically.
Request structure and code samples Node.js · Python · PHP · cURL Replace angle-bracket values with returned values. Use the raw access token only in the Authorization header.
Node.js const response = await fetch(BASE_URL + '/api/v1/auth/driver/onboarding/passcode', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Idempotency-Key': crypto.randomUUID()
},
body: JSON.stringify({"setupToken":"<setup-token>","passcode":"246810"})
});
const result = await response.json(); Python payload = json.loads(r'''{"setupToken":"<setup-token>","passcode":"246810"}''')
response = requests.post(BASE_URL + '/api/v1/auth/driver/onboarding/passcode',
headers={'Idempotency-Key': str(uuid.uuid4())},
json=payload)
result = response.json() PHP $payload = <<<'JSON'
{"setupToken":"<setup-token>","passcode":"246810"}
JSON;
$ch = curl_init($baseUrl . '/api/v1/auth/driver/onboarding/passcode');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Idempotency-Key: <uuid>'],
CURLOPT_POSTFIELDS => $payload,
CURLOPT_RETURNTRANSFER => true,
]); cURL curl -X POST '<base-url>/api/v1/auth/driver/onboarding/passcode' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: <uuid>' \
--data '{"setupToken":"<setup-token>","passcode":"246810"}'
{
"success": true,
"data": {
"driver": {
"id": "DRV_2e3149da-835d-4fdc-8d5e-02a5d6c7d55e",
"assignedId": "CRZ-ABC-0001",
"status": "OFFLINE"
},
"nextStep": "LOCATION",
"accessToken": "<driver-access-token>",
"refreshToken": "<refresh-token>"
},
"error": null
}
POST /api/v1/auth/driver/login
Public
Returning driver passcode login
Endpoint guide What to send, parse and expect Why it exists Signs in a returning driver with their fleet-issued assigned ID and saved six-digit passcode.
Before you call Use after the splash/welcome screen for drivers who completed setup.
Request fields Send assignedId and passcode.
What to parse Store tokens in platform secure storage, load /driver/me and /driver/home, and keep the driver OFFLINE until they explicitly go online.
Expected result 200 returns a driver session. Invalid credentials use one generic response.
Important IP throttling and account-level failed-attempt lockout protect the six-digit credential.
Request structure and code samples Node.js · Python · PHP · cURL Replace angle-bracket values with returned values. Use the raw access token only in the Authorization header.
Node.js const response = await fetch(BASE_URL + '/api/v1/auth/driver/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Idempotency-Key': crypto.randomUUID()
},
body: JSON.stringify({"assignedId":"CRZ-ABC-0001","passcode":"246810"})
});
const result = await response.json(); Python payload = json.loads(r'''{"assignedId":"CRZ-ABC-0001","passcode":"246810"}''')
response = requests.post(BASE_URL + '/api/v1/auth/driver/login',
headers={'Idempotency-Key': str(uuid.uuid4())},
json=payload)
result = response.json() PHP $payload = <<<'JSON'
{"assignedId":"CRZ-ABC-0001","passcode":"246810"}
JSON;
$ch = curl_init($baseUrl . '/api/v1/auth/driver/login');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Idempotency-Key: <uuid>'],
CURLOPT_POSTFIELDS => $payload,
CURLOPT_RETURNTRANSFER => true,
]); cURL curl -X POST '<base-url>/api/v1/auth/driver/login' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: <uuid>' \
--data '{"assignedId":"CRZ-ABC-0001","passcode":"246810"}'
{
"success": true,
"data": {
"driver": {
"id": "DRV_2e3149da-835d-4fdc-8d5e-02a5d6c7d55e",
"assignedId": "CRZ-ABC-0001",
"status": "OFFLINE"
},
"accessToken": "<driver-access-token>",
"refreshToken": "<refresh-token>"
},
"error": null
}
POST /api/v1/auth/driver/passcode-reset/request
Public
Request forgotten-passcode OTP
Endpoint guide What to send, parse and expect Why it exists Starts forgotten-passcode recovery using the phone already linked to an eligible driver.
Before you call Use only after the driver selects Forgot passcode; never send a passcode reset to an unverified contact.
Request fields Send assignedId and channel phone.
What to parse Always show the same confirmation screen to avoid revealing account eligibility; start a ten-minute countdown.
Expected result 202 is intentionally generic.
Important OTP delivery is rate limited and recovery is logged without exposing the destination.
Request structure and code samples Node.js · Python · PHP · cURL Replace angle-bracket values with returned values. Use the raw access token only in the Authorization header.
Node.js const response = await fetch(BASE_URL + '/api/v1/auth/driver/passcode-reset/request', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Idempotency-Key': crypto.randomUUID()
},
body: JSON.stringify({"assignedId":"CRZ-ABC-0001","channel":"phone"})
});
const result = await response.json(); Python payload = json.loads(r'''{"assignedId":"CRZ-ABC-0001","channel":"phone"}''')
response = requests.post(BASE_URL + '/api/v1/auth/driver/passcode-reset/request',
headers={'Idempotency-Key': str(uuid.uuid4())},
json=payload)
result = response.json() PHP $payload = <<<'JSON'
{"assignedId":"CRZ-ABC-0001","channel":"phone"}
JSON;
$ch = curl_init($baseUrl . '/api/v1/auth/driver/passcode-reset/request');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Idempotency-Key: <uuid>'],
CURLOPT_POSTFIELDS => $payload,
CURLOPT_RETURNTRANSFER => true,
]); cURL curl -X POST '<base-url>/api/v1/auth/driver/passcode-reset/request' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: <uuid>' \
--data '{"assignedId":"CRZ-ABC-0001","channel":"phone"}'
{
"success": true,
"data": {
"accepted": true,
"channel": "phone",
"expiresInSeconds": 600
},
"error": null
}
POST /api/v1/auth/driver/passcode-reset/verify
Public
Verify recovery OTP
Endpoint guide What to send, parse and expect Why it exists Verifies the recovery OTP and opens the new-passcode step.
Before you call Request a recovery OTP first.
Request fields Send assignedId and six-digit code.
What to parse Keep resetToken only in memory, then collect and locally confirm the new six-digit passcode.
Expected result 200 returns a 15-minute single-use resetToken and nextStep RESET_PASSCODE.
Important The OTP is consumed atomically and cannot be reused.
Request structure and code samples Node.js · Python · PHP · cURL Replace angle-bracket values with returned values. Use the raw access token only in the Authorization header.
Node.js const response = await fetch(BASE_URL + '/api/v1/auth/driver/passcode-reset/verify', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Idempotency-Key': crypto.randomUUID()
},
body: JSON.stringify({"assignedId":"CRZ-ABC-0001","code":"123456"})
});
const result = await response.json(); Python payload = json.loads(r'''{"assignedId":"CRZ-ABC-0001","code":"123456"}''')
response = requests.post(BASE_URL + '/api/v1/auth/driver/passcode-reset/verify',
headers={'Idempotency-Key': str(uuid.uuid4())},
json=payload)
result = response.json() PHP $payload = <<<'JSON'
{"assignedId":"CRZ-ABC-0001","code":"123456"}
JSON;
$ch = curl_init($baseUrl . '/api/v1/auth/driver/passcode-reset/verify');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Idempotency-Key: <uuid>'],
CURLOPT_POSTFIELDS => $payload,
CURLOPT_RETURNTRANSFER => true,
]); cURL curl -X POST '<base-url>/api/v1/auth/driver/passcode-reset/verify' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: <uuid>' \
--data '{"assignedId":"CRZ-ABC-0001","code":"123456"}'
{
"success": true,
"data": {
"resetToken": "<driver-passcode-reset-token>",
"expiresInSeconds": 900,
"nextStep": "RESET_PASSCODE"
},
"error": null
}
POST /api/v1/auth/driver/passcode-reset/confirm
Public
Set recovered six-digit passcode
Endpoint guide What to send, parse and expect Why it exists Sets a recovered driver passcode and signs the recovered device in.
Before you call Verify the recovery OTP and compare both new passcode entries locally.
Request fields Send resetToken and one six-digit passcode.
What to parse Replace stored credentials with the returned session. Other devices must return to sign-in.
Expected result 200 returns a fresh driver session and nextStep LOCATION.
Important Prior sessions are revoked atomically; recovery is audited with device and IP context.
Request structure and code samples Node.js · Python · PHP · cURL Replace angle-bracket values with returned values. Use the raw access token only in the Authorization header.
Node.js const response = await fetch(BASE_URL + '/api/v1/auth/driver/passcode-reset/confirm', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Idempotency-Key': crypto.randomUUID()
},
body: JSON.stringify({"resetToken":"<reset-token>","passcode":"246810"})
});
const result = await response.json(); Python payload = json.loads(r'''{"resetToken":"<reset-token>","passcode":"246810"}''')
response = requests.post(BASE_URL + '/api/v1/auth/driver/passcode-reset/confirm',
headers={'Idempotency-Key': str(uuid.uuid4())},
json=payload)
result = response.json() PHP $payload = <<<'JSON'
{"resetToken":"<reset-token>","passcode":"246810"}
JSON;
$ch = curl_init($baseUrl . '/api/v1/auth/driver/passcode-reset/confirm');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Idempotency-Key: <uuid>'],
CURLOPT_POSTFIELDS => $payload,
CURLOPT_RETURNTRANSFER => true,
]); cURL curl -X POST '<base-url>/api/v1/auth/driver/passcode-reset/confirm' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: <uuid>' \
--data '{"resetToken":"<reset-token>","passcode":"246810"}'
{
"success": true,
"data": {
"driver": {
"id": "DRV_2e3149da-835d-4fdc-8d5e-02a5d6c7d55e",
"assignedId": "CRZ-ABC-0001",
"status": "OFFLINE"
},
"nextStep": "LOCATION",
"accessToken": "<driver-access-token>",
"refreshToken": "<refresh-token>"
},
"error": null
}
GET /api/v1/driver/me
Bearer token
Driver profile
Endpoint guide What to send, parse and expect Why it exists Use this endpoint to perform the action described above.
Before you call Use the method and authentication badge shown above. Replace every placeholder with a value returned by an earlier API call.
Request fields The JSON editor contains a runnable example. Required field rules are returned as error.details.fieldErrors when validation fails.
What to parse Check success first. On success, read data; on failure, render error.code and error.message.
Request structure and code samples Node.js · Python · PHP · cURL Replace angle-bracket values with returned values. Use the raw access token only in the Authorization header.
Node.js const response = await fetch(BASE_URL + '/api/v1/driver/me', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer <access-token>',
'Idempotency-Key': crypto.randomUUID()
},
body: JSON.stringify({})
});
const result = await response.json(); Python payload = json.loads(r'''{}''')
response = requests.get(BASE_URL + '/api/v1/driver/me',
headers={'Idempotency-Key': str(uuid.uuid4())},
json=payload)
result = response.json() PHP $payload = <<<'JSON'
{}
JSON;
$ch = curl_init($baseUrl . '/api/v1/driver/me');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Idempotency-Key: <uuid>'],
CURLOPT_POSTFIELDS => $payload,
CURLOPT_RETURNTRANSFER => true,
]); cURL curl -X GET '<base-url>/api/v1/driver/me' \
-H 'Authorization: Bearer <access-token>' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: <uuid>' \
--data '{}'
{
"success": true,
"data": {
"id": "a2454a62-cf67-476f-b52f-4eaea9978a83",
"assignedId": "CRZ-ZZZ-0001",
"fleetId": "fa840a12-3cad-4477-9a31-e9bfc2837c5b",
"firstName": "Onboard",
"lastName": "Driver",
"phone": "+2349054568692",
"status": "OFFLINE",
"profileImageKey": null,
"pickupRadiusKm": 8,
"usePickupRadius": true,
"offerMode": "MANUAL",
"dispatchScore": 500,
"ratingAverage": 5,
"ratingCount": 0,
"vehicle": {
"id": "2127456d-32d1-439d-9d01-070e959babf9",
"fleet_id": "fa840a12-3cad-4477-9a31-e9bfc2837c5b",
"vin": "CRUIZVIN1787920343407379",
"plate_number": "CRZ407379",
"brand": "ASTRA Ride",
"model": "EV Test",
"battery_capacity_kwh": null,
"battery_percent": 84,
"year": 2025,
"color": "Blue",
"status": "OFFLINE",
"odometer_km": null,
"current_lat": "4.8156",
"current_lng": "7.0498",
"last_seen_at": "2026-08-28T12:33:14.546Z",
"image_key": null,
"created_at": "2026-08-28T12:32:33.044Z",
"updated_at": "2026-08-28T12:33:14.546Z"
},
"paymentAccountConfigured": false
},
"error": null
}
GET /api/v1/driver/home
Bearer token
Driver home dashboard snapshot
Endpoint guide What to send, parse and expect Why it exists Returns the driver-home snapshot: readiness, active trip, earnings, completed rides, distance and rating.
Before you call Call after authentication and whenever the app resumes.
Request fields No JSON body; identity is derived from bearer authentication.
What to parse Render readiness.blockers before enabling Online. Monetary Minor values are kobo.
Expected result 200 returns the current dashboard source of truth.
Important The driver cannot calculate or modify this server-owned snapshot.
Request structure and code samples Node.js · Python · PHP · cURL Replace angle-bracket values with returned values. Use the raw access token only in the Authorization header.
Node.js const response = await fetch(BASE_URL + '/api/v1/driver/home', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer <access-token>',
'Idempotency-Key': crypto.randomUUID()
},
body: JSON.stringify({})
});
const result = await response.json(); Python payload = json.loads(r'''{}''')
response = requests.get(BASE_URL + '/api/v1/driver/home',
headers={'Idempotency-Key': str(uuid.uuid4())},
json=payload)
result = response.json() PHP $payload = <<<'JSON'
{}
JSON;
$ch = curl_init($baseUrl . '/api/v1/driver/home');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Idempotency-Key: <uuid>'],
CURLOPT_POSTFIELDS => $payload,
CURLOPT_RETURNTRANSFER => true,
]); cURL curl -X GET '<base-url>/api/v1/driver/home' \
-H 'Authorization: Bearer <access-token>' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: <uuid>' \
--data '{}'
{
"success": true,
"data": {
"status": "OFFLINE",
"readiness": {
"ready": true,
"blockers": [],
"vehicle": {
"id": "2127456d-32d1-439d-9d01-070e959babf9",
"batteryPercent": 84,
"locationRecordedAt": "2026-08-28T12:33:14.546Z"
},
"policy": {
"minBatteryPercent": 30,
"maxLocationAgeMinutes": 10
}
},
"activeTrip": null,
"today": {
"earningsMinor": 0,
"completedTrips": 0,
"totalDistanceKm": 0,
"ratingAverage": 5
},
"dispatch": {
"pickupRadiusKm": 8,
"usePickupRadius": true,
"offerMode": "MANUAL",
"score": 500
}
},
"error": null
}
GET /api/v1/driver/demand-forecast
Bearer token
Predictive demand cells for the driver map
Endpoint guide What to send, parse and expect Why it exists Returns privacy-aggregated cells predicting demand for the next 20 minutes.
Before you call Call when the driver opens the map, after app resume, and once per minute while the map is visible.
Request fields Optional minLatitude, minLongitude, maxLatitude and maxLongitude define a bounded viewport.
What to parse Draw polygons in longitude/latitude order and remove the overlay after expiresAt.
Expected result 200 returns methodologyVersion and fleet-scoped zones; an empty zones array is valid.
Important Only server-produced signals are used and cells with fewer than five distinct riders are suppressed.
Request structure and code samples Node.js · Python · PHP · cURL Replace angle-bracket values with returned values. Use the raw access token only in the Authorization header.
Node.js const response = await fetch(BASE_URL + '/api/v1/driver/demand-forecast', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer <access-token>',
'Idempotency-Key': crypto.randomUUID()
},
body: JSON.stringify({})
});
const result = await response.json(); Python payload = json.loads(r'''{}''')
response = requests.get(BASE_URL + '/api/v1/driver/demand-forecast',
headers={'Idempotency-Key': str(uuid.uuid4())},
json=payload)
result = response.json() PHP $payload = <<<'JSON'
{}
JSON;
$ch = curl_init($baseUrl . '/api/v1/driver/demand-forecast');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Idempotency-Key: <uuid>'],
CURLOPT_POSTFIELDS => $payload,
CURLOPT_RETURNTRANSFER => true,
]); cURL curl -X GET '<base-url>/api/v1/driver/demand-forecast' \
-H 'Authorization: Bearer <access-token>' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: <uuid>' \
--data '{}'
{
"success": true,
"data": {
"generatedAt": "2026-09-13T18:00:00.000Z",
"expiresAt": "2026-09-13T18:02:00.000Z",
"forecastWindowMinutes": 20,
"methodologyVersion": "cruiz-demand-v1",
"privacyThreshold": 5,
"zones": [
{
"id": "4.81:7.04",
"polygon": [
[
7.04,
4.81
],
[
7.05,
4.81
],
[
7.05,
4.82
],
[
7.04,
4.82
],
[
7.04,
4.81
]
],
"center": {
"latitude": 4.815,
"longitude": 7.045
},
"level": "HIGH",
"label": "High demand expected",
"confidence": "MEDIUM",
"score": 1.82
}
]
},
"error": null
}
POST /api/v1/driver/location
Bearer token
Send verified GPS location
Endpoint guide What to send, parse and expect Why it exists Use this endpoint to perform the action described above.
Before you call Use the method and authentication badge shown above. Replace every placeholder with a value returned by an earlier API call.
Request fields The JSON editor contains a runnable example. Required field rules are returned as error.details.fieldErrors when validation fails.
What to parse Check success first. On success, read data; on failure, render error.code and error.message.
Request structure and code samples Node.js · Python · PHP · cURL Replace angle-bracket values with returned values. Use the raw access token only in the Authorization header.
Node.js const response = await fetch(BASE_URL + '/api/v1/driver/location', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer <access-token>',
'Idempotency-Key': crypto.randomUUID()
},
body: JSON.stringify({"latitude":4.8156,"longitude":7.0498})
});
const result = await response.json(); Python payload = json.loads(r'''{"latitude":4.8156,"longitude":7.0498}''')
response = requests.post(BASE_URL + '/api/v1/driver/location',
headers={'Idempotency-Key': str(uuid.uuid4())},
json=payload)
result = response.json() PHP $payload = <<<'JSON'
{"latitude":4.8156,"longitude":7.0498}
JSON;
$ch = curl_init($baseUrl . '/api/v1/driver/location');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Idempotency-Key: <uuid>'],
CURLOPT_POSTFIELDS => $payload,
CURLOPT_RETURNTRANSFER => true,
]); cURL curl -X POST '<base-url>/api/v1/driver/location' \
-H 'Authorization: Bearer <access-token>' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: <uuid>' \
--data '{"latitude":4.8156,"longitude":7.0498}'
{
"success": true,
"data": {
"id": "driver-location-1",
"driver_id": "DRV_2e3149da-835d-4fdc-8d5e-02a5d6c7d55e",
"trip_id": null,
"latitude": "4.8156",
"longitude": "7.0498",
"speed_kph": "0",
"heading": "0",
"recorded_at": "2026-08-28T18:00:00.000Z",
"received_at": "2026-08-28T18:00:00.000Z"
},
"error": null
}
PATCH /api/v1/driver/dispatch-preferences
Bearer token
Set manual offers or range-bound auto-accept
Endpoint guide What to send, parse and expect Why it exists Sets driver-controlled pickup range and offer behaviour. Auto-accept is permitted only inside an enabled pickup range.
Before you call Pickup range and auto-accept are off by default. Before going online, send current GPS, save this preference, check readiness, then set ONLINE. The driver, not the fleet, controls this setting.
Request fields MANUAL: { offerMode:"MANUAL", usePickupRadius:false } receives normal offers without a self-set range. AUTO: send { offerMode:"AUTO", usePickupRadius:true, pickupRadiusKm:1-50 }. To disable range while AUTO is enabled, send offerMode:"MANUAL" in that same request.
What to parse With an enabled range, this driver is eligible only when pickup distance is within pickupRadiusKm. AUTO accepts an eligible offer immediately; MANUAL sends driver:trip_offer and requires POST /driver/offers/:id/respond. A legacy AUTO record without a range fails closed and behaves as MANUAL until corrected.
Expected result 200 confirms the saved pickup-radius and offer-mode preferences. 409 AUTO_ACCEPT_REQUIRES_PICKUP_RANGE explains an invalid AUTO-without-range update and returns the current setting.
Important The backend merges partial updates with the saved preference before validating them, so a client cannot enable unbounded auto-accept by omitting fields.
Request structure and code samples Node.js · Python · PHP · cURL Replace angle-bracket values with returned values. Use the raw access token only in the Authorization header.
Node.js const response = await fetch(BASE_URL + '/api/v1/driver/dispatch-preferences', {
method: 'PATCH',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer <access-token>',
'Idempotency-Key': crypto.randomUUID()
},
body: JSON.stringify({"pickupRadiusKm":10,"usePickupRadius":true,"offerMode":"AUTO"})
});
const result = await response.json(); Python payload = json.loads(r'''{"pickupRadiusKm":10,"usePickupRadius":true,"offerMode":"AUTO"}''')
response = requests.patch(BASE_URL + '/api/v1/driver/dispatch-preferences',
headers={'Idempotency-Key': str(uuid.uuid4())},
json=payload)
result = response.json() PHP $payload = <<<'JSON'
{"pickupRadiusKm":10,"usePickupRadius":true,"offerMode":"AUTO"}
JSON;
$ch = curl_init($baseUrl . '/api/v1/driver/dispatch-preferences');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'PATCH',
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Idempotency-Key: <uuid>'],
CURLOPT_POSTFIELDS => $payload,
CURLOPT_RETURNTRANSFER => true,
]); cURL curl -X PATCH '<base-url>/api/v1/driver/dispatch-preferences' \
-H 'Authorization: Bearer <access-token>' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: <uuid>' \
--data '{"pickupRadiusKm":10,"usePickupRadius":true,"offerMode":"AUTO"}'
{
"success": true,
"data": {
"pickupRadiusKm": 12,
"usePickupRadius": true,
"offerMode": "AUTO"
},
"error": null
}
GET /api/v1/driver/readiness
Bearer token
Check online eligibility and blockers
Endpoint guide What to send, parse and expect Why it exists Explains whether a driver can go online and every blocker preventing it.
Before you call Call before displaying/enabling the Online switch.
Request fields No body. The server checks approved documents, active vehicle, battery and fresh location.
What to parse If ready is false, render each blocker message and resolve it before PATCH status.
Expected result 200 returns readiness whether or not the driver is eligible.
Important The same checks are enforced again when the driver requests ONLINE.
Request structure and code samples Node.js · Python · PHP · cURL Replace angle-bracket values with returned values. Use the raw access token only in the Authorization header.
Node.js const response = await fetch(BASE_URL + '/api/v1/driver/readiness', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer <access-token>',
'Idempotency-Key': crypto.randomUUID()
},
body: JSON.stringify({})
});
const result = await response.json(); Python payload = json.loads(r'''{}''')
response = requests.get(BASE_URL + '/api/v1/driver/readiness',
headers={'Idempotency-Key': str(uuid.uuid4())},
json=payload)
result = response.json() PHP $payload = <<<'JSON'
{}
JSON;
$ch = curl_init($baseUrl . '/api/v1/driver/readiness');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Idempotency-Key: <uuid>'],
CURLOPT_POSTFIELDS => $payload,
CURLOPT_RETURNTRANSFER => true,
]); cURL curl -X GET '<base-url>/api/v1/driver/readiness' \
-H 'Authorization: Bearer <access-token>' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: <uuid>' \
--data '{}'
{
"success": true,
"data": {
"ready": true,
"blockers": [],
"vehicle": {
"id": "2127456d-32d1-439d-9d01-070e959babf9",
"batteryPercent": 84,
"locationRecordedAt": "2026-08-28T12:33:14.546Z"
},
"policy": {
"minBatteryPercent": 30,
"maxLocationAgeMinutes": 10
}
},
"error": null
}
PATCH /api/v1/driver/status
Bearer token
Set ONLINE or OFFLINE
Endpoint guide What to send, parse and expect Why it exists Use this endpoint to perform the action described above.
Before you call Use the method and authentication badge shown above. Replace every placeholder with a value returned by an earlier API call.
Request fields The JSON editor contains a runnable example. Required field rules are returned as error.details.fieldErrors when validation fails.
What to parse Check success first. On success, read data; on failure, render error.code and error.message.
Request structure and code samples Node.js · Python · PHP · cURL Replace angle-bracket values with returned values. Use the raw access token only in the Authorization header.
Node.js const response = await fetch(BASE_URL + '/api/v1/driver/status', {
method: 'PATCH',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer <access-token>',
'Idempotency-Key': crypto.randomUUID()
},
body: JSON.stringify({"status":"ONLINE"})
});
const result = await response.json(); Python payload = json.loads(r'''{"status":"ONLINE"}''')
response = requests.patch(BASE_URL + '/api/v1/driver/status',
headers={'Idempotency-Key': str(uuid.uuid4())},
json=payload)
result = response.json() PHP $payload = <<<'JSON'
{"status":"ONLINE"}
JSON;
$ch = curl_init($baseUrl . '/api/v1/driver/status');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'PATCH',
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Idempotency-Key: <uuid>'],
CURLOPT_POSTFIELDS => $payload,
CURLOPT_RETURNTRANSFER => true,
]); cURL curl -X PATCH '<base-url>/api/v1/driver/status' \
-H 'Authorization: Bearer <access-token>' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: <uuid>' \
--data '{"status":"ONLINE"}'
{
"success": true,
"data": {
"id": "DRV_2e3149da-835d-4fdc-8d5e-02a5d6c7d55e",
"status": "ONLINE",
"pickup_radius_km": "12",
"uses_pickup_radius": false,
"offer_mode": "MANUAL"
},
"error": null
}
GET /api/v1/driver/offers
Bearer token
Read current expiring driver offers
Endpoint guide What to send, parse and expect Why it exists Lists only active, unexpired offers created for the authenticated driver.
Before you call Set driver status ONLINE. Connect Socket.IO first and handle driver:trip_offer, then use this endpoint after reconnecting or app resume.
Request fields No request body. The API derives the driver from the bearer token.
What to parse On driver:trip_offer, fetch this endpoint for the safe pickup/drop-off/fare preview and count down to expiresAt. On driver:trip_offer_expired, close the offer and disable both response buttons. Refetch this endpoint after reconnecting.
Expected result 200 returns the current driver-owned offers.
Important An offer is not a trip assignment; only the assigned driver may view or respond to it.
Request structure and code samples Node.js · Python · PHP · cURL Replace angle-bracket values with returned values. Use the raw access token only in the Authorization header.
Node.js const response = await fetch(BASE_URL + '/api/v1/driver/offers', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer <access-token>',
'Idempotency-Key': crypto.randomUUID()
},
body: JSON.stringify({})
});
const result = await response.json(); Python payload = json.loads(r'''{}''')
response = requests.get(BASE_URL + '/api/v1/driver/offers',
headers={'Idempotency-Key': str(uuid.uuid4())},
json=payload)
result = response.json() PHP $payload = <<<'JSON'
{}
JSON;
$ch = curl_init($baseUrl . '/api/v1/driver/offers');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Idempotency-Key: <uuid>'],
CURLOPT_POSTFIELDS => $payload,
CURLOPT_RETURNTRANSFER => true,
]); cURL curl -X GET '<base-url>/api/v1/driver/offers' \
-H 'Authorization: Bearer <access-token>' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: <uuid>' \
--data '{}'
{
"success": true,
"data": [],
"error": null
}
POST /api/v1/driver/offers/:id/respond
Bearer token
Accept or decline an expiring driver offer
Endpoint guide What to send, parse and expect Why it exists Atomically accepts or declines a single expiring trip offer.
Before you call Call only from an offer returned by GET offers or a driver:trip_offer socket event. Disable both buttons once tapped.
Request fields Replace :id with OFF_<uuid>. Raw UUIDs are also accepted. decision is ACCEPT or DECLINE.
What to parse On ACCEPT render assigned trip details; on DECLINE discard the offer. OFFER_EXPIRED and OFFER_NOT_AVAILABLE mean refetch offers.
Expected result 200 ACCEPT returns kind: ACCEPTED, tripId, riderId, fleetId, driver preview, and rider { id, firstName, lastName, phone, profileImageKey } after atomically assigning the trip and recording its assignment event. 200 DECLINE returns kind: DECLINED and the next matching state. 409 prevents a late, duplicate or unavailable response.
Important The server rechecks offer owner, expiry, driver availability and vehicle availability within one transaction.
Request structure and code samples Node.js · Python · PHP · cURL Replace angle-bracket values with returned values. Use the raw access token only in the Authorization header.
Node.js const response = await fetch(BASE_URL + '/api/v1/driver/offers/:id/respond', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer <access-token>',
'Idempotency-Key': crypto.randomUUID()
},
body: JSON.stringify({"decision":"ACCEPT"})
});
const result = await response.json(); Python payload = json.loads(r'''{"decision":"ACCEPT"}''')
response = requests.post(BASE_URL + '/api/v1/driver/offers/:id/respond',
headers={'Idempotency-Key': str(uuid.uuid4())},
json=payload)
result = response.json() PHP $payload = <<<'JSON'
{"decision":"ACCEPT"}
JSON;
$ch = curl_init($baseUrl . '/api/v1/driver/offers/:id/respond');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Idempotency-Key: <uuid>'],
CURLOPT_POSTFIELDS => $payload,
CURLOPT_RETURNTRANSFER => true,
]); cURL curl -X POST '<base-url>/api/v1/driver/offers/:id/respond' \
-H 'Authorization: Bearer <access-token>' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: <uuid>' \
--data '{"decision":"ACCEPT"}'
{
"success": true,
"data": {
"kind": "ACCEPTED",
"tripId": "TRIP_a40cd66e-e88f-4729-9f03-49d66aad7a12",
"riderId": "RDR_32f265f3-efee-4bbc-86d5-ed50c21c0267",
"fleetId": "FLT_b1fe6573-3a25-4d13-b41e-55143176d849",
"selectedDriver": {
"id": "DRV_2e3149da-835d-4fdc-8d5e-02a5d6c7d55e",
"firstName": "Browser",
"lastName": "Driver"
},
"trip": {
"id": "TRIP_a40cd66e-e88f-4729-9f03-49d66aad7a12",
"status": "DRIVER_ASSIGNED"
}
},
"error": null
}
GET /api/v1/driver/trips/active
Bearer token
Active trips
Endpoint guide What to send, parse and expect Why it exists Use this endpoint to perform the action described above.
Before you call Use the method and authentication badge shown above. Replace every placeholder with a value returned by an earlier API call.
Request fields The JSON editor contains a runnable example. Required field rules are returned as error.details.fieldErrors when validation fails.
What to parse Check success first. On success, read data; on failure, render error.code and error.message.
Request structure and code samples Node.js · Python · PHP · cURL Replace angle-bracket values with returned values. Use the raw access token only in the Authorization header.
Node.js const response = await fetch(BASE_URL + '/api/v1/driver/trips/active', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer <access-token>',
'Idempotency-Key': crypto.randomUUID()
},
body: JSON.stringify({})
});
const result = await response.json(); Python payload = json.loads(r'''{}''')
response = requests.get(BASE_URL + '/api/v1/driver/trips/active',
headers={'Idempotency-Key': str(uuid.uuid4())},
json=payload)
result = response.json() PHP $payload = <<<'JSON'
{}
JSON;
$ch = curl_init($baseUrl . '/api/v1/driver/trips/active');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Idempotency-Key: <uuid>'],
CURLOPT_POSTFIELDS => $payload,
CURLOPT_RETURNTRANSFER => true,
]); cURL curl -X GET '<base-url>/api/v1/driver/trips/active' \
-H 'Authorization: Bearer <access-token>' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: <uuid>' \
--data '{}'
{
"success": true,
"data": [],
"error": null
}
GET /api/v1/driver/trips/history
Bearer token
Completed and cancelled ride history
Endpoint guide What to send, parse and expect Why it exists Use this endpoint to perform the action described above.
Before you call Use the method and authentication badge shown above. Replace every placeholder with a value returned by an earlier API call.
Request fields The JSON editor contains a runnable example. Required field rules are returned as error.details.fieldErrors when validation fails.
What to parse Check success first. On success, read data; on failure, render error.code and error.message.
Request structure and code samples Node.js · Python · PHP · cURL Replace angle-bracket values with returned values. Use the raw access token only in the Authorization header.
Node.js const response = await fetch(BASE_URL + '/api/v1/driver/trips/history', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer <access-token>',
'Idempotency-Key': crypto.randomUUID()
},
body: JSON.stringify({})
});
const result = await response.json(); Python payload = json.loads(r'''{}''')
response = requests.get(BASE_URL + '/api/v1/driver/trips/history',
headers={'Idempotency-Key': str(uuid.uuid4())},
json=payload)
result = response.json() PHP $payload = <<<'JSON'
{}
JSON;
$ch = curl_init($baseUrl . '/api/v1/driver/trips/history');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Idempotency-Key: <uuid>'],
CURLOPT_POSTFIELDS => $payload,
CURLOPT_RETURNTRANSFER => true,
]); cURL curl -X GET '<base-url>/api/v1/driver/trips/history' \
-H 'Authorization: Bearer <access-token>' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: <uuid>' \
--data '{}'
{
"success": true,
"data": {
"id": "<resource-id>",
"status": "OK"
},
"error": null
}
GET /api/v1/driver/trips/:id
Bearer token
Read assigned trip and pickup verification policy
Endpoint guide What to send, parse and expect Why it exists Reads one assigned driver trip, including whether pickup verification is required for its fleet.
Before you call Use after accepting an offer or after reconnecting, before rendering the pickup controls.
Request fields Replace :id with the assigned TRIP_<uuid>. No request body.
What to parse Read pickupVerification.required. When false, after DRIVER_ARRIVED call the normal state endpoint with PASSENGER_ONBOARD; when true, obtain the rider PIN/QR and call pickup/verify.
Expected result 200 returns only a trip assigned to this driver plus pickupVerification { required, mode }. 403 means the trip is not assigned to this driver.
Important This response exposes policy only, never the rider pickup PIN or QR.
Request structure and code samples Node.js · Python · PHP · cURL Replace angle-bracket values with returned values. Use the raw access token only in the Authorization header.
Node.js const response = await fetch(BASE_URL + '/api/v1/driver/trips/:id', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer <access-token>',
'Idempotency-Key': crypto.randomUUID()
},
body: JSON.stringify({})
});
const result = await response.json(); Python payload = json.loads(r'''{}''')
response = requests.get(BASE_URL + '/api/v1/driver/trips/:id',
headers={'Idempotency-Key': str(uuid.uuid4())},
json=payload)
result = response.json() PHP $payload = <<<'JSON'
{}
JSON;
$ch = curl_init($baseUrl . '/api/v1/driver/trips/:id');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Idempotency-Key: <uuid>'],
CURLOPT_POSTFIELDS => $payload,
CURLOPT_RETURNTRANSFER => true,
]); cURL curl -X GET '<base-url>/api/v1/driver/trips/:id' \
-H 'Authorization: Bearer <access-token>' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: <uuid>' \
--data '{}'
{
"success": true,
"data": {
"id": "<resource-id>",
"status": "OK"
},
"error": null
}
POST /api/v1/driver/trips/:id/state
Bearer token
Transition a driver trip state
Endpoint guide What to send, parse and expect Why it exists Use this endpoint to perform the action described above.
Before you call Use the method and authentication badge shown above. Replace every placeholder with a value returned by an earlier API call.
Request fields The JSON editor contains a runnable example. Required field rules are returned as error.details.fieldErrors when validation fails.
What to parse Check success first. On success, read data; on failure, render error.code and error.message.
Request structure and code samples Node.js · Python · PHP · cURL Replace angle-bracket values with returned values. Use the raw access token only in the Authorization header.
Node.js const response = await fetch(BASE_URL + '/api/v1/driver/trips/:id/state', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer <access-token>',
'Idempotency-Key': crypto.randomUUID()
},
body: JSON.stringify({"status":"DRIVER_EN_ROUTE"})
});
const result = await response.json(); Python payload = json.loads(r'''{"status":"DRIVER_EN_ROUTE"}''')
response = requests.post(BASE_URL + '/api/v1/driver/trips/:id/state',
headers={'Idempotency-Key': str(uuid.uuid4())},
json=payload)
result = response.json() PHP $payload = <<<'JSON'
{"status":"DRIVER_EN_ROUTE"}
JSON;
$ch = curl_init($baseUrl . '/api/v1/driver/trips/:id/state');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Idempotency-Key: <uuid>'],
CURLOPT_POSTFIELDS => $payload,
CURLOPT_RETURNTRANSFER => true,
]); cURL curl -X POST '<base-url>/api/v1/driver/trips/:id/state' \
-H 'Authorization: Bearer <access-token>' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: <uuid>' \
--data '{"status":"DRIVER_EN_ROUTE"}'
{
"success": true,
"data": {
"id": "a40cd66e-e88f-4729-9f03-49d66aad7a12",
"status": "DRIVER_EN_ROUTE",
"tripVersion": 2
},
"error": null
}
POST /api/v1/driver/trips/:id/pickup/verify
Bearer token
Verify rider pickup PIN or QR
Endpoint guide What to send, parse and expect Why it exists Verifies the rider's PIN or QR at pickup and atomically advances the ride to PASSENGER_ONBOARD.
Before you call This is available only when the fleet has pickup verification enabled and the driver has already set DRIVER_ARRIVED.
Request fields Replace :id with the assigned trip UUID. Send either pin (four digits) or qrPayload read by the driver's scanner.
What to parse Use data.trip.status as the new source of truth. A repeat tap returns alreadyVerified:true and is safe.
Expected result 200 confirms boarding. 400 is an invalid PIN/QR; 409 identifies an unavailable state, disabled feature or missing arrival.
Important The rider-only credential never appears in driver detail APIs and the driver cannot choose another trip's PIN.
Request structure and code samples Node.js · Python · PHP · cURL Replace angle-bracket values with returned values. Use the raw access token only in the Authorization header.
Node.js const response = await fetch(BASE_URL + '/api/v1/driver/trips/:id/pickup/verify', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer <access-token>',
'Idempotency-Key': crypto.randomUUID()
},
body: JSON.stringify({"pin":"1234"})
});
const result = await response.json(); Python payload = json.loads(r'''{"pin":"1234"}''')
response = requests.post(BASE_URL + '/api/v1/driver/trips/:id/pickup/verify',
headers={'Idempotency-Key': str(uuid.uuid4())},
json=payload)
result = response.json() PHP $payload = <<<'JSON'
{"pin":"1234"}
JSON;
$ch = curl_init($baseUrl . '/api/v1/driver/trips/:id/pickup/verify');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Idempotency-Key: <uuid>'],
CURLOPT_POSTFIELDS => $payload,
CURLOPT_RETURNTRANSFER => true,
]); cURL curl -X POST '<base-url>/api/v1/driver/trips/:id/pickup/verify' \
-H 'Authorization: Bearer <access-token>' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: <uuid>' \
--data '{"pin":"1234"}'
{
"success": true,
"data": {
"verified": true,
"alreadyVerified": false,
"trip": {
"id": "TRIP_a40cd66e-e88f-4729-9f03-49d66aad7a12",
"status": "PASSENGER_ONBOARD"
}
},
"error": null
}
GET /api/v1/driver/earnings
Bearer token
Driver earnings and commission
Endpoint guide What to send, parse and expect Why it exists Returns server-calculated gross, commission, net and completed trips.
Before you call Optionally add ?period=TODAY, LAST_7_DAYS or LAST_30_DAYS.
Request fields No JSON body. Values ending in Minor are kobo.
What to parse Show gross, commission and net separately; this is not a payout instruction.
Expected result 200 returns summary and trip rows.
Important Only the caller's completed trips are included.
Request structure and code samples Node.js · Python · PHP · cURL Replace angle-bracket values with returned values. Use the raw access token only in the Authorization header.
Node.js const response = await fetch(BASE_URL + '/api/v1/driver/earnings', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer <access-token>',
'Idempotency-Key': crypto.randomUUID()
},
body: JSON.stringify({})
});
const result = await response.json(); Python payload = json.loads(r'''{}''')
response = requests.get(BASE_URL + '/api/v1/driver/earnings',
headers={'Idempotency-Key': str(uuid.uuid4())},
json=payload)
result = response.json() PHP $payload = <<<'JSON'
{}
JSON;
$ch = curl_init($baseUrl . '/api/v1/driver/earnings');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Idempotency-Key: <uuid>'],
CURLOPT_POSTFIELDS => $payload,
CURLOPT_RETURNTRANSFER => true,
]); cURL curl -X GET '<base-url>/api/v1/driver/earnings' \
-H 'Authorization: Bearer <access-token>' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: <uuid>' \
--data '{}'
{
"success": true,
"data": {
"period": "LAST_7_DAYS",
"summary": {
"grossEarningsMinor": 0,
"commissionMinor": 0,
"netEarningsMinor": 0,
"currency": "NGN",
"completedTrips": 0
},
"trips": []
},
"error": null
}
GET /api/v1/driver/score
Bearer token
Driver dispatch score and audit events
Endpoint guide What to send, parse and expect Why it exists Shows dispatch score, rider rating and an immutable score-event history.
Before you call Use this for transparent driver education.
What to parse Score is 0-1000; ranking weights reliability 55%, rating 25% and proximity 20%.
Expected result 200 returns score and events.
Important Only trusted backend actions write score events.
Request structure and code samples Node.js · Python · PHP · cURL Replace angle-bracket values with returned values. Use the raw access token only in the Authorization header.
Node.js const response = await fetch(BASE_URL + '/api/v1/driver/score', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer <access-token>',
'Idempotency-Key': crypto.randomUUID()
},
body: JSON.stringify({})
});
const result = await response.json(); Python payload = json.loads(r'''{}''')
response = requests.get(BASE_URL + '/api/v1/driver/score',
headers={'Idempotency-Key': str(uuid.uuid4())},
json=payload)
result = response.json() PHP $payload = <<<'JSON'
{}
JSON;
$ch = curl_init($baseUrl . '/api/v1/driver/score');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Idempotency-Key: <uuid>'],
CURLOPT_POSTFIELDS => $payload,
CURLOPT_RETURNTRANSFER => true,
]); cURL curl -X GET '<base-url>/api/v1/driver/score' \
-H 'Authorization: Bearer <access-token>' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: <uuid>' \
--data '{}'
{
"success": true,
"data": {
"score": 500,
"ratingAverage": 5,
"ratingCount": 0,
"weighting": {
"dispatchReliability": 55,
"riderRating": 25,
"pickupProximity": 20
},
"events": []
},
"error": null
}
GET /api/v1/driver/fraud-signals
Bearer token
Driver-visible risk signals
Endpoint guide What to send, parse and expect Why it exists Lists non-sensitive fraud/operational flags affecting the signed-in driver.
Before you call Use for transparent account-health and support screens.
What to parse Render status and safe detail. Do not infer internal fraud thresholds.
Expected result 200 returns caller-owned records.
Important Drivers cannot create, clear or alter signals.
Request structure and code samples Node.js · Python · PHP · cURL Replace angle-bracket values with returned values. Use the raw access token only in the Authorization header.
Node.js const response = await fetch(BASE_URL + '/api/v1/driver/fraud-signals', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer <access-token>',
'Idempotency-Key': crypto.randomUUID()
},
body: JSON.stringify({})
});
const result = await response.json(); Python payload = json.loads(r'''{}''')
response = requests.get(BASE_URL + '/api/v1/driver/fraud-signals',
headers={'Idempotency-Key': str(uuid.uuid4())},
json=payload)
result = response.json() PHP $payload = <<<'JSON'
{}
JSON;
$ch = curl_init($baseUrl . '/api/v1/driver/fraud-signals');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Idempotency-Key: <uuid>'],
CURLOPT_POSTFIELDS => $payload,
CURLOPT_RETURNTRANSFER => true,
]); cURL curl -X GET '<base-url>/api/v1/driver/fraud-signals' \
-H 'Authorization: Bearer <access-token>' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: <uuid>' \
--data '{}'
{
"success": true,
"data": [],
"error": null
}
GET /api/v1/driver/messages
Bearer token
Read authorised driver messages
Endpoint guide What to send, parse and expect Why it exists Lets the assigned driver read and send messages only within an authorised active trip.
Before you call The rider must be assigned to the driver. Use the trip id from the driver active-trips response.
Request fields POST accepts tripId and body; the server derives the rider recipient, so do not send recipientId.
What to parse Render messages only in the matching trip conversation and subscribe to message:received for delivery.
Expected result GET 200 returns the driver message inbox; POST 201 creates the trip message.
Important The backend rejects messages for a trip assigned to another driver.
Request structure and code samples Node.js · Python · PHP · cURL Replace angle-bracket values with returned values. Use the raw access token only in the Authorization header.
Node.js const response = await fetch(BASE_URL + '/api/v1/driver/messages', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer <access-token>',
'Idempotency-Key': crypto.randomUUID()
},
body: JSON.stringify({})
});
const result = await response.json(); Python payload = json.loads(r'''{}''')
response = requests.get(BASE_URL + '/api/v1/driver/messages',
headers={'Idempotency-Key': str(uuid.uuid4())},
json=payload)
result = response.json() PHP $payload = <<<'JSON'
{}
JSON;
$ch = curl_init($baseUrl . '/api/v1/driver/messages');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Idempotency-Key: <uuid>'],
CURLOPT_POSTFIELDS => $payload,
CURLOPT_RETURNTRANSFER => true,
]); cURL curl -X GET '<base-url>/api/v1/driver/messages' \
-H 'Authorization: Bearer <access-token>' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: <uuid>' \
--data '{}'
{
"success": true,
"data": [],
"error": null
}
POST /api/v1/driver/messages
Bearer token
Send an authorised message to active rider
Endpoint guide What to send, parse and expect Why it exists Lets the assigned driver read and send messages only within an authorised active trip.
Before you call The rider must be assigned to the driver. Use the trip id from the driver active-trips response.
Request fields POST accepts tripId and body; the server derives the rider recipient, so do not send recipientId.
What to parse Render messages only in the matching trip conversation and subscribe to message:received for delivery.
Expected result GET 200 returns the driver message inbox; POST 201 creates the trip message.
Important The backend rejects messages for a trip assigned to another driver.
Request structure and code samples Node.js · Python · PHP · cURL Replace angle-bracket values with returned values. Use the raw access token only in the Authorization header.
Node.js const response = await fetch(BASE_URL + '/api/v1/driver/messages', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer <access-token>',
'Idempotency-Key': crypto.randomUUID()
},
body: JSON.stringify({"tripId":"TRIP_<uuid>","body":"I am approaching pickup."})
});
const result = await response.json(); Python payload = json.loads(r'''{"tripId":"TRIP_<uuid>","body":"I am approaching pickup."}''')
response = requests.post(BASE_URL + '/api/v1/driver/messages',
headers={'Idempotency-Key': str(uuid.uuid4())},
json=payload)
result = response.json() PHP $payload = <<<'JSON'
{"tripId":"TRIP_<uuid>","body":"I am approaching pickup."}
JSON;
$ch = curl_init($baseUrl . '/api/v1/driver/messages');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Idempotency-Key: <uuid>'],
CURLOPT_POSTFIELDS => $payload,
CURLOPT_RETURNTRANSFER => true,
]); cURL curl -X POST '<base-url>/api/v1/driver/messages' \
-H 'Authorization: Bearer <access-token>' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: <uuid>' \
--data '{"tripId":"TRIP_<uuid>","body":"I am approaching pickup."}'
{
"success": true,
"data": {
"id": "driver-msg-1",
"trip_id": "TRIP_a40cd66e-e88f-4729-9f03-49d66aad7a12",
"sender_id": "USR_0cc3dcfc-ce9c-4e79-bf09-3c77a0b6ac34",
"recipient_id": "USR_32f265f3-efee-4bbc-86d5-ed50c21c0267",
"body": "I am approaching pickup.",
"type": "TRIP",
"created_at": "2026-08-28T18:03:00.000Z"
},
"error": null
}
GET /api/v1/driver/support/tickets
Bearer token
List driver support tickets
Endpoint guide What to send, parse and expect Why it exists Creates/lists driver-owned support tickets for non-emergency issues.
Before you call Use for payment, vehicle, account or rider issues.
Request fields POST accepts category, subject, details, priority and optional owned tripId.
What to parse Persist the returned ticket id/status for support UI.
Expected result GET 200; POST 201.
Important A driver can attach only their own trip.
Request structure and code samples Node.js · Python · PHP · cURL Replace angle-bracket values with returned values. Use the raw access token only in the Authorization header.
Node.js const response = await fetch(BASE_URL + '/api/v1/driver/support/tickets', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer <access-token>',
'Idempotency-Key': crypto.randomUUID()
},
body: JSON.stringify({})
});
const result = await response.json(); Python payload = json.loads(r'''{}''')
response = requests.get(BASE_URL + '/api/v1/driver/support/tickets',
headers={'Idempotency-Key': str(uuid.uuid4())},
json=payload)
result = response.json() PHP $payload = <<<'JSON'
{}
JSON;
$ch = curl_init($baseUrl . '/api/v1/driver/support/tickets');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Idempotency-Key: <uuid>'],
CURLOPT_POSTFIELDS => $payload,
CURLOPT_RETURNTRANSFER => true,
]); cURL curl -X GET '<base-url>/api/v1/driver/support/tickets' \
-H 'Authorization: Bearer <access-token>' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: <uuid>' \
--data '{}'
{
"success": true,
"data": [
{
"id": "4b531f71-78d7-4bf9-895f-3c8240127eef",
"driver_id": "a2454a62-cf67-476f-b52f-4eaea9978a83",
"trip_id": null,
"category": "ACCOUNT",
"subject": "Controlled support test",
"details": "Testing the driver support endpoint.",
"priority": "NORMAL",
"status": "OPEN",
"created_at": "2026-08-28T12:33:17.613Z",
"updated_at": "2026-08-28T12:33:17.611Z"
}
],
"error": null
}
POST /api/v1/driver/support/tickets
Bearer token
Open a driver support ticket
Endpoint guide What to send, parse and expect Why it exists Creates/lists driver-owned support tickets for non-emergency issues.
Before you call Use for payment, vehicle, account or rider issues.
Request fields POST accepts category, subject, details, priority and optional owned tripId.
What to parse Persist the returned ticket id/status for support UI.
Expected result GET 200; POST 201.
Important A driver can attach only their own trip.
Request structure and code samples Node.js · Python · PHP · cURL Replace angle-bracket values with returned values. Use the raw access token only in the Authorization header.
Node.js const response = await fetch(BASE_URL + '/api/v1/driver/support/tickets', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer <access-token>',
'Idempotency-Key': crypto.randomUUID()
},
body: JSON.stringify({"category":"PAYMENT","subject":"Transfer pending","details":"Trip payment has not appeared.","priority":"HIGH"})
});
const result = await response.json(); Python payload = json.loads(r'''{"category":"PAYMENT","subject":"Transfer pending","details":"Trip payment has not appeared.","priority":"HIGH"}''')
response = requests.post(BASE_URL + '/api/v1/driver/support/tickets',
headers={'Idempotency-Key': str(uuid.uuid4())},
json=payload)
result = response.json() PHP $payload = <<<'JSON'
{"category":"PAYMENT","subject":"Transfer pending","details":"Trip payment has not appeared.","priority":"HIGH"}
JSON;
$ch = curl_init($baseUrl . '/api/v1/driver/support/tickets');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Idempotency-Key: <uuid>'],
CURLOPT_POSTFIELDS => $payload,
CURLOPT_RETURNTRANSFER => true,
]); cURL curl -X POST '<base-url>/api/v1/driver/support/tickets' \
-H 'Authorization: Bearer <access-token>' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: <uuid>' \
--data '{"category":"PAYMENT","subject":"Transfer pending","details":"Trip payment has not appeared.","priority":"HIGH"}'
{
"success": true,
"data": {
"id": "driver-ticket-1",
"status": "OPEN",
"priority": "HIGH",
"createdAt": "2026-08-28T18:03:00.000Z"
},
"error": null
}
GET /api/v1/driver/support/tickets/:id
Bearer token
Read an owned support ticket conversation
Endpoint guide What to send, parse and expect Why it exists Use this endpoint to perform the action described above.
Before you call Use the method and authentication badge shown above. Replace every placeholder with a value returned by an earlier API call.
Request fields The JSON editor contains a runnable example. Required field rules are returned as error.details.fieldErrors when validation fails.
What to parse Check success first. On success, read data; on failure, render error.code and error.message.
Request structure and code samples Node.js · Python · PHP · cURL Replace angle-bracket values with returned values. Use the raw access token only in the Authorization header.
Node.js const response = await fetch(BASE_URL + '/api/v1/driver/support/tickets/:id', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer <access-token>',
'Idempotency-Key': crypto.randomUUID()
},
body: JSON.stringify({})
});
const result = await response.json(); Python payload = json.loads(r'''{}''')
response = requests.get(BASE_URL + '/api/v1/driver/support/tickets/:id',
headers={'Idempotency-Key': str(uuid.uuid4())},
json=payload)
result = response.json() PHP $payload = <<<'JSON'
{}
JSON;
$ch = curl_init($baseUrl . '/api/v1/driver/support/tickets/:id');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Idempotency-Key: <uuid>'],
CURLOPT_POSTFIELDS => $payload,
CURLOPT_RETURNTRANSFER => true,
]); cURL curl -X GET '<base-url>/api/v1/driver/support/tickets/:id' \
-H 'Authorization: Bearer <access-token>' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: <uuid>' \
--data '{}'
{
"success": true,
"data": {
"id": "driver-ticket-1",
"subject": "Transfer pending",
"status": "PENDING_CUSTOMER",
"messages": []
},
"error": null
}
POST /api/v1/driver/support/tickets/:id/messages
Bearer token
Reply to an owned support ticket
Endpoint guide What to send, parse and expect Why it exists Use this endpoint to perform the action described above.
Before you call Use the method and authentication badge shown above. Replace every placeholder with a value returned by an earlier API call.
Request fields The JSON editor contains a runnable example. Required field rules are returned as error.details.fieldErrors when validation fails.
What to parse Check success first. On success, read data; on failure, render error.code and error.message.
Request structure and code samples Node.js · Python · PHP · cURL Replace angle-bracket values with returned values. Use the raw access token only in the Authorization header.
Node.js const response = await fetch(BASE_URL + '/api/v1/driver/support/tickets/:id/messages', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer <access-token>',
'Idempotency-Key': crypto.randomUUID()
},
body: JSON.stringify({"body":"Here is the requested information."})
});
const result = await response.json(); Python payload = json.loads(r'''{"body":"Here is the requested information."}''')
response = requests.post(BASE_URL + '/api/v1/driver/support/tickets/:id/messages',
headers={'Idempotency-Key': str(uuid.uuid4())},
json=payload)
result = response.json() PHP $payload = <<<'JSON'
{"body":"Here is the requested information."}
JSON;
$ch = curl_init($baseUrl . '/api/v1/driver/support/tickets/:id/messages');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Idempotency-Key: <uuid>'],
CURLOPT_POSTFIELDS => $payload,
CURLOPT_RETURNTRANSFER => true,
]); cURL curl -X POST '<base-url>/api/v1/driver/support/tickets/:id/messages' \
-H 'Authorization: Bearer <access-token>' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: <uuid>' \
--data '{"body":"Here is the requested information."}'
{
"success": true,
"data": {
"replayed": false,
"status": "IN_PROGRESS",
"message": {
"id": "driver-reply-1",
"body": "The trip was completed yesterday.",
"author": "CUSTOMER",
"createdAt": "2026-08-28T18:05:00.000Z"
}
},
"error": null
}
POST /api/v1/driver/safety/incidents
Bearer token
Raise driver SOS or safety incident
Endpoint guide What to send, parse and expect Why it exists Raises a driver SOS or safety incident for fleet operations.
Before you call In immediate danger call emergency services first, then send current coordinates where available.
Request fields POST type, description and optional own trip/location. SOS/collision are CRITICAL.
What to parse After 201 confirm, retain the emergency action and await operational follow-up.
Expected result 201 creates a durable auditable incident.
Important Trip ownership is verified and severity is server determined.
Request structure and code samples Node.js · Python · PHP · cURL Replace angle-bracket values with returned values. Use the raw access token only in the Authorization header.
Node.js const response = await fetch(BASE_URL + '/api/v1/driver/safety/incidents', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer <access-token>',
'Idempotency-Key': crypto.randomUUID()
},
body: JSON.stringify({"type":"SOS","description":"I need urgent help","latitude":4.8156,"longitude":7.0498})
});
const result = await response.json(); Python payload = json.loads(r'''{"type":"SOS","description":"I need urgent help","latitude":4.8156,"longitude":7.0498}''')
response = requests.post(BASE_URL + '/api/v1/driver/safety/incidents',
headers={'Idempotency-Key': str(uuid.uuid4())},
json=payload)
result = response.json() PHP $payload = <<<'JSON'
{"type":"SOS","description":"I need urgent help","latitude":4.8156,"longitude":7.0498}
JSON;
$ch = curl_init($baseUrl . '/api/v1/driver/safety/incidents');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Idempotency-Key: <uuid>'],
CURLOPT_POSTFIELDS => $payload,
CURLOPT_RETURNTRANSFER => true,
]); cURL curl -X POST '<base-url>/api/v1/driver/safety/incidents' \
-H 'Authorization: Bearer <access-token>' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: <uuid>' \
--data '{"type":"SOS","description":"I need urgent help","latitude":4.8156,"longitude":7.0498}'
{
"success": true,
"data": {
"id": "driver-incident-1",
"status": "OPEN",
"severity": "CRITICAL",
"createdAt": "2026-08-28T18:03:00.000Z"
},
"error": null
}
GET /api/v1/driver/remittance-balance
Bearer token
Read cash commission debt and online block state
Endpoint guide What to send, parse and expect Why it exists Calculates the authenticated driver cash-trip commission debt to their fleet and tells the app if ONLINE is blocked.
Before you call Call before enabling Online and after a fleet reviews a payment.
Request fields No body. All values ending in Minor are kobo.
What to parse Use outstandingMinor and blocked. The server, not the app, rejects ONLINE when the policy threshold is reached.
Expected result 200 returns the debt, submitted remittances and policy.
Important Only confirmed cash collections and APPROVED remittances affect the balance.
Request structure and code samples Node.js · Python · PHP · cURL Replace angle-bracket values with returned values. Use the raw access token only in the Authorization header.
Node.js const response = await fetch(BASE_URL + '/api/v1/driver/remittance-balance', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer <access-token>',
'Idempotency-Key': crypto.randomUUID()
},
body: JSON.stringify({})
});
const result = await response.json(); Python payload = json.loads(r'''{}''')
response = requests.get(BASE_URL + '/api/v1/driver/remittance-balance',
headers={'Idempotency-Key': str(uuid.uuid4())},
json=payload)
result = response.json() PHP $payload = <<<'JSON'
{}
JSON;
$ch = curl_init($baseUrl . '/api/v1/driver/remittance-balance');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Idempotency-Key: <uuid>'],
CURLOPT_POSTFIELDS => $payload,
CURLOPT_RETURNTRANSFER => true,
]); cURL curl -X GET '<base-url>/api/v1/driver/remittance-balance' \
-H 'Authorization: Bearer <access-token>' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: <uuid>' \
--data '{}'
{
"success": true,
"data": {
"currency": "NGN",
"policy": {
"enabled": false,
"thresholdMinor": 500000,
"blockOnline": true
},
"commissionRateBps": 0,
"accruedCommissionMinor": 0,
"approvedRemittanceMinor": 0,
"submittedRemittanceMinor": 0,
"outstandingMinor": 0,
"blocked": false
},
"error": null
}
GET /api/v1/driver/remittances
Bearer token
List driver remittances
Endpoint guide What to send, parse and expect Why it exists Lists or submits a driver-to-fleet cash commission remittance for fleet finance review.
Before you call The driver pays the fleet, then submits its payment reference. A fleet approval is required before debt reduces.
Request fields POST amountMinor, paymentReference and optional note. Amount must not exceed outstanding debt.
What to parse Render SUBMITTED as pending review and APPROVED as settled.
Expected result GET 200; POST 201.
Important The backend owns the debt calculation and rejects over-remittance.
Request structure and code samples Node.js · Python · PHP · cURL Replace angle-bracket values with returned values. Use the raw access token only in the Authorization header.
Node.js const response = await fetch(BASE_URL + '/api/v1/driver/remittances', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer <access-token>',
'Idempotency-Key': crypto.randomUUID()
},
body: JSON.stringify({})
});
const result = await response.json(); Python payload = json.loads(r'''{}''')
response = requests.get(BASE_URL + '/api/v1/driver/remittances',
headers={'Idempotency-Key': str(uuid.uuid4())},
json=payload)
result = response.json() PHP $payload = <<<'JSON'
{}
JSON;
$ch = curl_init($baseUrl . '/api/v1/driver/remittances');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Idempotency-Key: <uuid>'],
CURLOPT_POSTFIELDS => $payload,
CURLOPT_RETURNTRANSFER => true,
]); cURL curl -X GET '<base-url>/api/v1/driver/remittances' \
-H 'Authorization: Bearer <access-token>' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: <uuid>' \
--data '{}'
{
"success": true,
"data": [],
"error": null
}
POST /api/v1/driver/remittances
Bearer token
Submit cash commission remittance
Endpoint guide What to send, parse and expect Why it exists Lists or submits a driver-to-fleet cash commission remittance for fleet finance review.
Before you call The driver pays the fleet, then submits its payment reference. A fleet approval is required before debt reduces.
Request fields POST amountMinor, paymentReference and optional note. Amount must not exceed outstanding debt.
What to parse Render SUBMITTED as pending review and APPROVED as settled.
Expected result GET 200; POST 201.
Important The backend owns the debt calculation and rejects over-remittance.
Request structure and code samples Node.js · Python · PHP · cURL Replace angle-bracket values with returned values. Use the raw access token only in the Authorization header.
Node.js const response = await fetch(BASE_URL + '/api/v1/driver/remittances', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer <access-token>',
'Idempotency-Key': crypto.randomUUID()
},
body: JSON.stringify({"amountMinor":50000,"paymentReference":"TRF-12345"})
});
const result = await response.json(); Python payload = json.loads(r'''{"amountMinor":50000,"paymentReference":"TRF-12345"}''')
response = requests.post(BASE_URL + '/api/v1/driver/remittances',
headers={'Idempotency-Key': str(uuid.uuid4())},
json=payload)
result = response.json() PHP $payload = <<<'JSON'
{"amountMinor":50000,"paymentReference":"TRF-12345"}
JSON;
$ch = curl_init($baseUrl . '/api/v1/driver/remittances');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Idempotency-Key: <uuid>'],
CURLOPT_POSTFIELDS => $payload,
CURLOPT_RETURNTRANSFER => true,
]); cURL curl -X POST '<base-url>/api/v1/driver/remittances' \
-H 'Authorization: Bearer <access-token>' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: <uuid>' \
--data '{"amountMinor":50000,"paymentReference":"TRF-12345"}'
{
"success": true,
"data": {
"id": "RMT_6d87456d-32d1-439d-9d01-070e959babf9",
"amountMinor": 50000,
"paymentReference": "TRF-12345",
"status": "SUBMITTED",
"createdAt": "2026-08-28T18:04:00.000Z"
},
"error": null
}
GET /api/v1/driver/trips/:id/rider-locationNEW
Bearer token
Recover the rider’s latest shared pickup position
Endpoint guide What to send, parse and expect Why it exists Fetches a fresh rider GPS position after reconnect.
Before you call Use the method and authentication badge shown above. Replace every placeholder with a value returned by an earlier API call.
Request fields Replace :id with an assigned trip ID. No body.
What to parse data.location is null if the rider has not shared recently or pickup is complete. The trip pickup coordinate remains available separately.
Expected result 200 returns tripId and location.
Important Only the currently assigned driver may read this position before pickup.
Request structure and code samples Node.js · Python · PHP · cURL Replace angle-bracket values with returned values. Use the raw access token only in the Authorization header.
Node.js const response = await fetch(BASE_URL + '/api/v1/driver/trips/:id/rider-location', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer <access-token>',
'Idempotency-Key': crypto.randomUUID()
},
body: JSON.stringify({})
});
const result = await response.json(); Python payload = json.loads(r'''{}''')
response = requests.get(BASE_URL + '/api/v1/driver/trips/:id/rider-location',
headers={'Idempotency-Key': str(uuid.uuid4())},
json=payload)
result = response.json() PHP $payload = <<<'JSON'
{}
JSON;
$ch = curl_init($baseUrl . '/api/v1/driver/trips/:id/rider-location');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Idempotency-Key: <uuid>'],
CURLOPT_POSTFIELDS => $payload,
CURLOPT_RETURNTRANSFER => true,
]); cURL curl -X GET '<base-url>/api/v1/driver/trips/:id/rider-location' \
-H 'Authorization: Bearer <access-token>' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: <uuid>' \
--data '{}'
{
"success": true,
"data": {
"tripId": "TRIP_a40cd66e-e88f-4729-9f03-49d66aad7a12",
"location": {
"latitude": 4.8156,
"longitude": 7.0498,
"accuracyM": 12,
"recordedAt": "2026-08-28T18:04:00.000Z"
}
},
"error": null
}
PATCH /api/v1/driver/profile
Bearer token
Update the signed-in driver profile
Endpoint guide What to send, parse and expect Why it exists Updates the driver name in both the driver and account records.
Before you call Use the method and authentication badge shown above. Replace every placeholder with a value returned by an earlier API call.
Request fields Send at least firstName or lastName.
What to parse Check success first. On success, read data; on failure, render error.code and error.message.
Expected result 200 returns the refreshed profile.
Request structure and code samples Node.js · Python · PHP · cURL Replace angle-bracket values with returned values. Use the raw access token only in the Authorization header.
Node.js const response = await fetch(BASE_URL + '/api/v1/driver/profile', {
method: 'PATCH',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer <access-token>',
'Idempotency-Key': crypto.randomUUID()
},
body: JSON.stringify({"firstName":"Jane","lastName":"Doe"})
});
const result = await response.json(); Python payload = json.loads(r'''{"firstName":"Jane","lastName":"Doe"}''')
response = requests.patch(BASE_URL + '/api/v1/driver/profile',
headers={'Idempotency-Key': str(uuid.uuid4())},
json=payload)
result = response.json() PHP $payload = <<<'JSON'
{"firstName":"Jane","lastName":"Doe"}
JSON;
$ch = curl_init($baseUrl . '/api/v1/driver/profile');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'PATCH',
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Idempotency-Key: <uuid>'],
CURLOPT_POSTFIELDS => $payload,
CURLOPT_RETURNTRANSFER => true,
]); cURL curl -X PATCH '<base-url>/api/v1/driver/profile' \
-H 'Authorization: Bearer <access-token>' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: <uuid>' \
--data '{"firstName":"Jane","lastName":"Doe"}'
{
"success": true,
"data": {
"id": "2e3149da-835d-4fdc-8d5e-02a5d6c7d55e",
"firstName": "Jane",
"lastName": "Doe",
"phone": "+2349054568692"
},
"error": null
}
GET /api/v1/driver/devices
Bearer token
List registered driver devices
Endpoint guide What to send, parse and expect Why it exists Lists only devices registered by the signed-in driver.
Before you call Use the method and authentication badge shown above. Replace every placeholder with a value returned by an earlier API call.
What to parse Check success first. On success, read data; on failure, render error.code and error.message.
Expected result 200 returns device settings.
Request structure and code samples Node.js · Python · PHP · cURL Replace angle-bracket values with returned values. Use the raw access token only in the Authorization header.
Node.js const response = await fetch(BASE_URL + '/api/v1/driver/devices', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer <access-token>',
'Idempotency-Key': crypto.randomUUID()
},
body: JSON.stringify({})
});
const result = await response.json(); Python payload = json.loads(r'''{}''')
response = requests.get(BASE_URL + '/api/v1/driver/devices',
headers={'Idempotency-Key': str(uuid.uuid4())},
json=payload)
result = response.json() PHP $payload = <<<'JSON'
{}
JSON;
$ch = curl_init($baseUrl . '/api/v1/driver/devices');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Idempotency-Key: <uuid>'],
CURLOPT_POSTFIELDS => $payload,
CURLOPT_RETURNTRANSFER => true,
]); cURL curl -X GET '<base-url>/api/v1/driver/devices' \
-H 'Authorization: Bearer <access-token>' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: <uuid>' \
--data '{}'
{
"success": true,
"data": [
{
"id": "device-1",
"driverId": "DRV_2e3149da-835d-4fdc-8d5e-02a5d6c7d55e",
"deviceId": "ios-installation-id",
"platform": "IOS",
"notificationsEnabled": true,
"lastSeenAt": "2026-08-28T18:05:00.000Z"
}
],
"error": null
}
GET /api/v1/driver/notifications
Bearer token
Read durable driver notifications
Endpoint guide What to send, parse and expect Why it exists Returns the signed-in driver notification history.
Before you call Use the method and authentication badge shown above. Replace every placeholder with a value returned by an earlier API call.
What to parse Check success first. On success, read data; on failure, render error.code and error.message.
Expected result 200 returns newest-first messages.
Important Recovery source after launch or socket reconnect.
Request structure and code samples Node.js · Python · PHP · cURL Replace angle-bracket values with returned values. Use the raw access token only in the Authorization header.
Node.js const response = await fetch(BASE_URL + '/api/v1/driver/notifications', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer <access-token>',
'Idempotency-Key': crypto.randomUUID()
},
body: JSON.stringify({})
});
const result = await response.json(); Python payload = json.loads(r'''{}''')
response = requests.get(BASE_URL + '/api/v1/driver/notifications',
headers={'Idempotency-Key': str(uuid.uuid4())},
json=payload)
result = response.json() PHP $payload = <<<'JSON'
{}
JSON;
$ch = curl_init($baseUrl . '/api/v1/driver/notifications');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Idempotency-Key: <uuid>'],
CURLOPT_POSTFIELDS => $payload,
CURLOPT_RETURNTRANSFER => true,
]); cURL curl -X GET '<base-url>/api/v1/driver/notifications' \
-H 'Authorization: Bearer <access-token>' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: <uuid>' \
--data '{}'
{
"success": true,
"data": {
"id": "<resource-id>",
"status": "OK"
},
"error": null
}
POST /api/v1/driver/notifications/:id/read
Bearer token
Mark a driver notification read
Endpoint guide What to send, parse and expect Why it exists Acknowledges an owned notification.
Before you call Use the method and authentication badge shown above. Replace every placeholder with a value returned by an earlier API call.
Request fields Replace :id with the notification id.
What to parse Check success first. On success, read data; on failure, render error.code and error.message.
Expected result 200 returns read true.
Request structure and code samples Node.js · Python · PHP · cURL Replace angle-bracket values with returned values. Use the raw access token only in the Authorization header.
Node.js const response = await fetch(BASE_URL + '/api/v1/driver/notifications/:id/read', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer <access-token>',
'Idempotency-Key': crypto.randomUUID()
},
body: JSON.stringify({})
});
const result = await response.json(); Python payload = json.loads(r'''{}''')
response = requests.post(BASE_URL + '/api/v1/driver/notifications/:id/read',
headers={'Idempotency-Key': str(uuid.uuid4())},
json=payload)
result = response.json() PHP $payload = <<<'JSON'
{}
JSON;
$ch = curl_init($baseUrl . '/api/v1/driver/notifications/:id/read');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Idempotency-Key: <uuid>'],
CURLOPT_POSTFIELDS => $payload,
CURLOPT_RETURNTRANSFER => true,
]); cURL curl -X POST '<base-url>/api/v1/driver/notifications/:id/read' \
-H 'Authorization: Bearer <access-token>' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: <uuid>' \
--data '{}'
{
"success": true,
"data": {
"id": "<created-id>",
"status": "CREATED"
},
"error": null
}
PUT /api/v1/driver/devices
Bearer token
Register/update push-notification device
Endpoint guide What to send, parse and expect Why it exists Safely upserts a device registration for notifications.
Before you call Use the method and authentication badge shown above. Replace every placeholder with a value returned by an earlier API call.
Request fields deviceId, platform and optional pushToken.
What to parse Check success first. On success, read data; on failure, render error.code and error.message.
Expected result 200 returns the registered device.
Request structure and code samples Node.js · Python · PHP · cURL Replace angle-bracket values with returned values. Use the raw access token only in the Authorization header.
Node.js const response = await fetch(BASE_URL + '/api/v1/driver/devices', {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer <access-token>',
'Idempotency-Key': crypto.randomUUID()
},
body: JSON.stringify({"deviceId":"ios-installation-id","platform":"IOS","notificationsEnabled":true})
});
const result = await response.json(); Python payload = json.loads(r'''{"deviceId":"ios-installation-id","platform":"IOS","notificationsEnabled":true}''')
response = requests.put(BASE_URL + '/api/v1/driver/devices',
headers={'Idempotency-Key': str(uuid.uuid4())},
json=payload)
result = response.json() PHP $payload = <<<'JSON'
{"deviceId":"ios-installation-id","platform":"IOS","notificationsEnabled":true}
JSON;
$ch = curl_init($baseUrl . '/api/v1/driver/devices');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Idempotency-Key: <uuid>'],
CURLOPT_POSTFIELDS => $payload,
CURLOPT_RETURNTRANSFER => true,
]); cURL curl -X PUT '<base-url>/api/v1/driver/devices' \
-H 'Authorization: Bearer <access-token>' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: <uuid>' \
--data '{"deviceId":"ios-installation-id","platform":"IOS","notificationsEnabled":true}'
{
"success": true,
"data": {
"status": "OK"
},
"error": null
}
POST /api/v1/driver/trips/:id/feedback
Bearer token
Rate a rider with comment
Endpoint guide What to send, parse and expect Why it exists Stores one driver-to-rider rating after a completed trip.
Before you call Use the method and authentication badge shown above. Replace every placeholder with a value returned by an earlier API call.
Request fields score is 1-5; comment is optional.
What to parse Check success first. On success, read data; on failure, render error.code and error.message.
Expected result 201 creates feedback; 409 prevents duplicate ratings.
Request structure and code samples Node.js · Python · PHP · cURL Replace angle-bracket values with returned values. Use the raw access token only in the Authorization header.
Node.js const response = await fetch(BASE_URL + '/api/v1/driver/trips/:id/feedback', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer <access-token>',
'Idempotency-Key': crypto.randomUUID()
},
body: JSON.stringify({"score":5,"comment":"Respectful rider"})
});
const result = await response.json(); Python payload = json.loads(r'''{"score":5,"comment":"Respectful rider"}''')
response = requests.post(BASE_URL + '/api/v1/driver/trips/:id/feedback',
headers={'Idempotency-Key': str(uuid.uuid4())},
json=payload)
result = response.json() PHP $payload = <<<'JSON'
{"score":5,"comment":"Respectful rider"}
JSON;
$ch = curl_init($baseUrl . '/api/v1/driver/trips/:id/feedback');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Idempotency-Key: <uuid>'],
CURLOPT_POSTFIELDS => $payload,
CURLOPT_RETURNTRANSFER => true,
]); cURL curl -X POST '<base-url>/api/v1/driver/trips/:id/feedback' \
-H 'Authorization: Bearer <access-token>' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: <uuid>' \
--data '{"score":5,"comment":"Respectful rider"}'
{
"success": true,
"data": {
"id": "feedback-1",
"score": 5,
"comment": "Respectful rider",
"createdAt": "2026-08-28T18:10:00.000Z"
},
"error": null
}
GET /api/v1/driver/trips/:id/waiting-fee
Bearer token
Preview waiting fee after 3-minute grace period
Endpoint guide What to send, parse and expect Why it exists Returns the server-calculated waiting-time fee and no-show eligibility.
Before you call Use the method and authentication badge shown above. Replace every placeholder with a value returned by an earlier API call.
Request fields No body. Fleet/admin owns the policy; money is kobo.
What to parse Check success first. On success, read data; on failure, render error.code and error.message.
Expected result 200 returns waited minutes, billable minutes and fee.
Request structure and code samples Node.js · Python · PHP · cURL Replace angle-bracket values with returned values. Use the raw access token only in the Authorization header.
Node.js const response = await fetch(BASE_URL + '/api/v1/driver/trips/:id/waiting-fee', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer <access-token>',
'Idempotency-Key': crypto.randomUUID()
},
body: JSON.stringify({})
});
const result = await response.json(); Python payload = json.loads(r'''{}''')
response = requests.get(BASE_URL + '/api/v1/driver/trips/:id/waiting-fee',
headers={'Idempotency-Key': str(uuid.uuid4())},
json=payload)
result = response.json() PHP $payload = <<<'JSON'
{}
JSON;
$ch = curl_init($baseUrl . '/api/v1/driver/trips/:id/waiting-fee');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Idempotency-Key: <uuid>'],
CURLOPT_POSTFIELDS => $payload,
CURLOPT_RETURNTRANSFER => true,
]); cURL curl -X GET '<base-url>/api/v1/driver/trips/:id/waiting-fee' \
-H 'Authorization: Bearer <access-token>' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: <uuid>' \
--data '{}'
{
"success": true,
"data": {
"eligible": true,
"feeMinor": 1000,
"policy": {
"enabled": true,
"graceMinutes": 3,
"perMinuteMinor": 500,
"noShowAfterMinutes": 10
},
"waitedMinutes": 5,
"billableMinutes": 2
},
"error": null
}
GET /api/v1/driver/trips/:id/location-replay
Bearer token
Replay own authorised trip location points
Endpoint guide What to send, parse and expect Why it exists Restores driver route points after reconnect.
Before you call Use the method and authentication badge shown above. Replace every placeholder with a value returned by an earlier API call.
Request fields Optional ?since=ISO timestamp.
What to parse Check success first. On success, read data; on failure, render error.code and error.message.
Expected result 200 returns up to 2,000 ordered points.
Request structure and code samples Node.js · Python · PHP · cURL Replace angle-bracket values with returned values. Use the raw access token only in the Authorization header.
Node.js const response = await fetch(BASE_URL + '/api/v1/driver/trips/:id/location-replay', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer <access-token>',
'Idempotency-Key': crypto.randomUUID()
},
body: JSON.stringify({})
});
const result = await response.json(); Python payload = json.loads(r'''{}''')
response = requests.get(BASE_URL + '/api/v1/driver/trips/:id/location-replay',
headers={'Idempotency-Key': str(uuid.uuid4())},
json=payload)
result = response.json() PHP $payload = <<<'JSON'
{}
JSON;
$ch = curl_init($baseUrl . '/api/v1/driver/trips/:id/location-replay');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Idempotency-Key: <uuid>'],
CURLOPT_POSTFIELDS => $payload,
CURLOPT_RETURNTRANSFER => true,
]); cURL curl -X GET '<base-url>/api/v1/driver/trips/:id/location-replay' \
-H 'Authorization: Bearer <access-token>' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: <uuid>' \
--data '{}'
{
"success": true,
"data": [
{
"latitude": 4.8156,
"longitude": 7.0498,
"recordedAt": "2026-08-28T18:01:00.000Z"
},
{
"latitude": 4.817,
"longitude": 7.048,
"recordedAt": "2026-08-28T18:02:00.000Z"
}
],
"error": null
}
POST /api/v1/trips/:id/calls
Bearer token
Start an in-trip voice call
Endpoint guide What to send, parse and expect Why it exists Ring the assigned rider or driver for this active trip.
Before you call Use the assigned TRIP_<uuid> and a bearer session. Send Idempotency-Key for safe retries.
Request fields Optional `{ ringTimeoutSeconds }` integer: 10-300 seconds; omitted uses 120 seconds. The backend chooses the recipient and LiveKit room.
What to parse Render RINGING and expiresAt. Wait for call:state_changed before requesting a join token.
Expected result 201 returns callId, tripId, status, version, participant IDs and timestamps. 409 means the trip is not eligible; 503 means LiveKit is disabled.
Important Only the current assigned driver and rider can initiate. No LiveKit token is issued before answer.
Request structure and code samples Node.js · Python · PHP · cURL Replace angle-bracket values with returned values. Use the raw access token only in the Authorization header.
Node.js const response = await fetch(BASE_URL + '/api/v1/trips/:id/calls', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer <access-token>',
'Idempotency-Key': crypto.randomUUID()
},
body: JSON.stringify({ "ringTimeoutSeconds": 120 })
});
const result = await response.json(); Python payload = json.loads(r'''{ "ringTimeoutSeconds": 120 }''')
response = requests.post(BASE_URL + '/api/v1/trips/:id/calls',
headers={'Idempotency-Key': str(uuid.uuid4())},
json=payload)
result = response.json() PHP $payload = <<<'JSON'
{ "ringTimeoutSeconds": 120 }
JSON;
$ch = curl_init($baseUrl . '/api/v1/trips/:id/calls');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Idempotency-Key: <uuid>'],
CURLOPT_POSTFIELDS => $payload,
CURLOPT_RETURNTRANSFER => true,
]); cURL curl -X POST '<base-url>/api/v1/trips/:id/calls' \
-H 'Authorization: Bearer <access-token>' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: <uuid>' \
--data '{ "ringTimeoutSeconds": 120 }'
{
"success": true,
"data": {
"callId": "CAL_bbd4b8e1-e3b6-4dbb-bc7d-ea5df8592cbc",
"tripId": "TRIP_a40cd66e-e88f-4729-9f03-49d66aad7a12",
"status": "RINGING",
"version": 1,
"callerUserId": "USR_32f265f3-efee-4bbc-86d5-ed50c21c0267",
"recipientUserId": "USR_0cc3dcfc-ce9c-4e79-bf09-3c77a0b6ac34",
"expiresAt": "2026-10-02T18:00:30.000Z",
"acceptedAt": null,
"activeAt": null,
"endedAt": null,
"createdAt": "2026-10-02T18:00:00.000Z"
},
"error": null
}
GET /api/v1/trips/:id/calls/active
Bearer token
Recover active call state
Endpoint guide What to send, parse and expect Why it exists Read the current call after app resume or socket reconnect.
Before you call Use the method and authentication badge shown above. Replace every placeholder with a value returned by an earlier API call.
What to parse Check success first. On success, read data; on failure, render error.code and error.message.
Expected result 200 returns a call summary or null.
Important Restricted to the assigned trip pair.
Request structure and code samples Node.js · Python · PHP · cURL Replace angle-bracket values with returned values. Use the raw access token only in the Authorization header.
Node.js const response = await fetch(BASE_URL + '/api/v1/trips/:id/calls/active', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer <access-token>',
'Idempotency-Key': crypto.randomUUID()
},
body: JSON.stringify({})
});
const result = await response.json(); Python payload = json.loads(r'''{}''')
response = requests.get(BASE_URL + '/api/v1/trips/:id/calls/active',
headers={'Idempotency-Key': str(uuid.uuid4())},
json=payload)
result = response.json() PHP $payload = <<<'JSON'
{}
JSON;
$ch = curl_init($baseUrl . '/api/v1/trips/:id/calls/active');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Idempotency-Key: <uuid>'],
CURLOPT_POSTFIELDS => $payload,
CURLOPT_RETURNTRANSFER => true,
]); cURL curl -X GET '<base-url>/api/v1/trips/:id/calls/active' \
-H 'Authorization: Bearer <access-token>' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: <uuid>' \
--data '{}'
{
"success": true,
"data": {
"callId": "CAL_bbd4b8e1-e3b6-4dbb-bc7d-ea5df8592cbc",
"tripId": "TRIP_a40cd66e-e88f-4729-9f03-49d66aad7a12",
"status": "RINGING",
"version": 1,
"callerUserId": "USR_32f265f3-efee-4bbc-86d5-ed50c21c0267",
"recipientUserId": "USR_0cc3dcfc-ce9c-4e79-bf09-3c77a0b6ac34",
"expiresAt": "2026-10-02T18:00:30.000Z",
"acceptedAt": null,
"activeAt": null,
"endedAt": null,
"createdAt": "2026-10-02T18:00:00.000Z"
},
"error": null
}
POST /api/v1/trips/:id/calls/:callId/accept
Bearer token
Accept an incoming call
Endpoint guide What to send, parse and expect Why it exists The recipient accepts before the call response deadline in expiresAt.
Before you call Use the method and authentication badge shown above. Replace every placeholder with a value returned by an earlier API call.
Request fields Use CAL_<uuid> from call:incoming; no body.
What to parse Check success first. On success, read data; on failure, render error.code and error.message.
Expected result 200 returns CONNECTING; 409 means timed out or already decided.
Important Caller cannot accept their own call.
Request structure and code samples Node.js · Python · PHP · cURL Replace angle-bracket values with returned values. Use the raw access token only in the Authorization header.
Node.js const response = await fetch(BASE_URL + '/api/v1/trips/:id/calls/:callId/accept', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer <access-token>',
'Idempotency-Key': crypto.randomUUID()
},
body: JSON.stringify({})
});
const result = await response.json(); Python payload = json.loads(r'''{}''')
response = requests.post(BASE_URL + '/api/v1/trips/:id/calls/:callId/accept',
headers={'Idempotency-Key': str(uuid.uuid4())},
json=payload)
result = response.json() PHP $payload = <<<'JSON'
{}
JSON;
$ch = curl_init($baseUrl . '/api/v1/trips/:id/calls/:callId/accept');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Idempotency-Key: <uuid>'],
CURLOPT_POSTFIELDS => $payload,
CURLOPT_RETURNTRANSFER => true,
]); cURL curl -X POST '<base-url>/api/v1/trips/:id/calls/:callId/accept' \
-H 'Authorization: Bearer <access-token>' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: <uuid>' \
--data '{}'
{
"success": true,
"data": {
"callId": "CAL_bbd4b8e1-e3b6-4dbb-bc7d-ea5df8592cbc",
"tripId": "TRIP_a40cd66e-e88f-4729-9f03-49d66aad7a12",
"status": "CONNECTING",
"version": 2,
"callerUserId": "USR_32f265f3-efee-4bbc-86d5-ed50c21c0267",
"recipientUserId": "USR_0cc3dcfc-ce9c-4e79-bf09-3c77a0b6ac34",
"expiresAt": "2026-10-02T18:00:30.000Z",
"acceptedAt": "2026-10-02T18:00:12.000Z",
"activeAt": null,
"endedAt": null,
"createdAt": "2026-10-02T18:00:00.000Z"
},
"error": null
}
POST /api/v1/trips/:id/calls/:callId/decline
Bearer token
Decline an incoming call
Endpoint guide What to send, parse and expect Why it exists The recipient declines the ringing call.
Before you call Use the method and authentication badge shown above. Replace every placeholder with a value returned by an earlier API call.
What to parse Check success first. On success, read data; on failure, render error.code and error.message.
Expected result 200 returns DECLINED and emits call:ended.
Request structure and code samples Node.js · Python · PHP · cURL Replace angle-bracket values with returned values. Use the raw access token only in the Authorization header.
Node.js const response = await fetch(BASE_URL + '/api/v1/trips/:id/calls/:callId/decline', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer <access-token>',
'Idempotency-Key': crypto.randomUUID()
},
body: JSON.stringify({})
});
const result = await response.json(); Python payload = json.loads(r'''{}''')
response = requests.post(BASE_URL + '/api/v1/trips/:id/calls/:callId/decline',
headers={'Idempotency-Key': str(uuid.uuid4())},
json=payload)
result = response.json() PHP $payload = <<<'JSON'
{}
JSON;
$ch = curl_init($baseUrl . '/api/v1/trips/:id/calls/:callId/decline');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Idempotency-Key: <uuid>'],
CURLOPT_POSTFIELDS => $payload,
CURLOPT_RETURNTRANSFER => true,
]); cURL curl -X POST '<base-url>/api/v1/trips/:id/calls/:callId/decline' \
-H 'Authorization: Bearer <access-token>' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: <uuid>' \
--data '{}'
{
"success": true,
"data": {
"callId": "CAL_bbd4b8e1-e3b6-4dbb-bc7d-ea5df8592cbc",
"tripId": "TRIP_a40cd66e-e88f-4729-9f03-49d66aad7a12",
"status": "DECLINED",
"version": 2,
"callerUserId": "USR_32f265f3-efee-4bbc-86d5-ed50c21c0267",
"recipientUserId": "USR_0cc3dcfc-ce9c-4e79-bf09-3c77a0b6ac34",
"expiresAt": "2026-10-02T18:00:30.000Z",
"acceptedAt": null,
"activeAt": null,
"endedAt": "2026-10-02T18:00:12.000Z",
"createdAt": "2026-10-02T18:00:00.000Z"
},
"error": null
}
POST /api/v1/trips/:id/calls/:callId/join-token
Bearer token
Get own LiveKit microphone token
Endpoint guide What to send, parse and expect Why it exists After acceptance, get a short-lived credential for this device only.
Before you call Use the method and authentication badge shown above. Replace every placeholder with a value returned by an earlier API call.
Request fields No body. Call separately on the rider and driver app.
What to parse Pass serverUrl and token to the LiveKit SDK room.connect; then enable microphone. Never persist the token.
Expected result 200 returns callId, serverUrl, token, identity and expiresAt; Cache-Control: no-store.
Important Server signs one-room, microphone-only, non-admin grants after rechecking assignment and call status.
Request structure and code samples Node.js · Python · PHP · cURL Replace angle-bracket values with returned values. Use the raw access token only in the Authorization header.
Node.js const response = await fetch(BASE_URL + '/api/v1/trips/:id/calls/:callId/join-token', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer <access-token>',
'Idempotency-Key': crypto.randomUUID()
},
body: JSON.stringify({})
});
const result = await response.json(); Python payload = json.loads(r'''{}''')
response = requests.post(BASE_URL + '/api/v1/trips/:id/calls/:callId/join-token',
headers={'Idempotency-Key': str(uuid.uuid4())},
json=payload)
result = response.json() PHP $payload = <<<'JSON'
{}
JSON;
$ch = curl_init($baseUrl . '/api/v1/trips/:id/calls/:callId/join-token');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Idempotency-Key: <uuid>'],
CURLOPT_POSTFIELDS => $payload,
CURLOPT_RETURNTRANSFER => true,
]); cURL curl -X POST '<base-url>/api/v1/trips/:id/calls/:callId/join-token' \
-H 'Authorization: Bearer <access-token>' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: <uuid>' \
--data '{}'
{
"success": true,
"data": {
"callId": "CAL_bbd4b8e1-e3b6-4dbb-bc7d-ea5df8592cbc",
"serverUrl": "wss://your-project.livekit.cloud",
"token": "<short-lived-livekit-token>",
"identity": "rider:bbd4b8e1-e3b6-4dbb-bc7d-ea5df8592cbc",
"expiresAt": "2026-10-02T18:02:00.000Z"
},
"error": null
}
POST /api/v1/trips/:id/calls/:callId/end
Bearer token
End an in-trip voice call
Endpoint guide What to send, parse and expect Why it exists Either participant terminates the call.
Before you call Use the method and authentication badge shown above. Replace every placeholder with a value returned by an earlier API call.
What to parse Check success first. On success, read data; on failure, render error.code and error.message.
Expected result 200 returns ENDED and emits call:ended; repeated end is idempotent.
Request structure and code samples Node.js · Python · PHP · cURL Replace angle-bracket values with returned values. Use the raw access token only in the Authorization header.
Node.js const response = await fetch(BASE_URL + '/api/v1/trips/:id/calls/:callId/end', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer <access-token>',
'Idempotency-Key': crypto.randomUUID()
},
body: JSON.stringify({})
});
const result = await response.json(); Python payload = json.loads(r'''{}''')
response = requests.post(BASE_URL + '/api/v1/trips/:id/calls/:callId/end',
headers={'Idempotency-Key': str(uuid.uuid4())},
json=payload)
result = response.json() PHP $payload = <<<'JSON'
{}
JSON;
$ch = curl_init($baseUrl . '/api/v1/trips/:id/calls/:callId/end');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Idempotency-Key: <uuid>'],
CURLOPT_POSTFIELDS => $payload,
CURLOPT_RETURNTRANSFER => true,
]); cURL curl -X POST '<base-url>/api/v1/trips/:id/calls/:callId/end' \
-H 'Authorization: Bearer <access-token>' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: <uuid>' \
--data '{}'
{
"success": true,
"data": {
"callId": "CAL_bbd4b8e1-e3b6-4dbb-bc7d-ea5df8592cbc",
"tripId": "TRIP_a40cd66e-e88f-4729-9f03-49d66aad7a12",
"status": "ENDED",
"version": 2,
"callerUserId": "USR_32f265f3-efee-4bbc-86d5-ed50c21c0267",
"recipientUserId": "USR_0cc3dcfc-ce9c-4e79-bf09-3c77a0b6ac34",
"expiresAt": "2026-10-02T18:00:30.000Z",
"acceptedAt": null,
"activeAt": null,
"endedAt": "2026-10-02T18:00:12.000Z",
"createdAt": "2026-10-02T18:00:00.000Z"
},
"error": null
}
Errors and safety Responses use JSON with a stable error code. Mutating requests receive an automatic idempotency key in the test console. Never paste production credentials here.