Rider API

Onboarding, Cruz Pass, fare quotes, booking and rider support.

Interactive test consolePaste a dedicated development token below. It stays in this browser tab and is sent only to the API endpoint you test.
Frontend integration guide

Base URL: use the environment-specific backend URL. The mobile app should never call the Cruz Pass Supabase database directly.

Authentication: onboarding OTP verification returns an onboarding token. After profile completion, persist the access token in secure device storage and send it as Authorization: Bearer <token>. Refresh tokens must also stay in secure storage.

Booking order: request location permission, resolve pickup and destination coordinates, call POST /api/v1/rider/quotes, show the returned server price, then call POST /api/v1/rider/trips with the quote ID. Never calculate or trust the fare in the app.

Cruz Pass: call GET /passes/active to display balanceNaira. A ride can use at most ₦1,000 even if the card balance is higher. The backend owns balance decrement, restoration on cancellation, and source synchronisation.

Safe retries: send a fresh UUID in Idempotency-Key for every new mutation. Reuse the same key only when retrying the exact same request. Disable buttons while a request is pending and treat 409 duplicate/request-in-progress responses as non-fatal UI states.

State rendering: use the trip status returned by the API as the source of truth. Subscribe to socket events when available, but refetch the dashboard after reconnecting or when the app resumes.

Errors: read the stable code and user-safe message fields. Do not display stack traces or raw provider errors.

Minimal booking example
const quote = await api.post('/api/v1/rider/quotes', quoteInput, { idempotencyKey: crypto.randomUUID() });
const trip = await api.post('/api/v1/rider/trips', { quoteId: quote.data.id }, { idempotencyKey: crypto.randomUUID() });
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.

HTTPMeaningFrontend 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.

Money and JSON format

All NGN monetary fields ending in Minor are expressed in kobo, not naira. For example, 246500 means ₦2,465; divide by 100 for display. JSON body editors are automatically pretty-printed when valid JSON is entered.

Capability status and endpoint map

This table is the source of truth for frontend planning. Live means the endpoint is implemented and testable. Partial means only the first phase exists. Planned is a documented contract, not a live endpoint yet.

CapabilityStatusFrontend endpoint(s)
Fare quote, distance, ETA and service areaPartialPOST /api/v1/rider/quotes; provider-backed geocoding/routing still pending
Driver offers, accept/decline, timeout, reassignmentPartialPOST /api/v1/trips/:id/dispatch; offer lifecycle endpoints pending
Live driver location and socket recoveryPartialPOST /api/v1/driver/location; reconnect/replay contract pending
Pickup PIN or QR confirmationPlannedPOST /api/v1/trips/:id/pickup/verify
Cancellation, no-show fees and previewPartialPOST /api/v1/rider/trips/:id/cancel; fee preview/rules pending
Checkout, webhooks, receipts, refunds, disputesPartial/api/v1/payments/intents; receipt/refund/dispute surface pending
Trip history, invoices and saved placesPartialPOST /api/v1/rider/places; history/invoice GET endpoints pending
SOS, trusted contacts, trip sharing and escalationPlanned/api/v1/rider/safety/*
Masked calling and authorized in-trip chatPartial/api/v1/communication/*; provider authorization and trip scoping pending
Driver/vehicle details, blocking and extra-money reportsPartialGET /api/v1/driver/me, POST /trips/:id/reports
Support tickets, lost items, attachments and ops queuePartialPOST /api/v1/rider/trips/:id/reports; ticket/attachment endpoints pending
Fraud, velocity, payment risk and route anomaly controlsPlanned/api/v1/risk/* is backend-internal; frontend receives safe challenge/decline codes
POST/api/v1/auth/refresh
Public

Refresh and rotate an access session

Endpoint guide What to send, parse and expect

Why it exists

Rotates an authenticated rider session after an access token expires.

Before you call

Read the refresh token from secure device storage. Never send it to ordinary rider endpoints.

Request fields

refreshToken is the opaque token returned by onboarding completion or a previous refresh.

What to parse

Replace both stored tokens. Retry the original request once, then sign out if refresh fails.

Expected result

200 returns a new accessToken, refreshToken and expiry.

Important

Refresh tokens are rotated and the previous token is revoked server-side.

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/refresh', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Idempotency-Key': crypto.randomUUID()
  },
  body: JSON.stringify({"refreshToken":"..."})
});
const result = await response.json();

Python

payload = json.loads(r'''{"refreshToken":"..."}''')
response = requests.post(BASE_URL + '/api/v1/auth/refresh',
    headers={'Idempotency-Key': str(uuid.uuid4())},
    json=payload)
result = response.json()

PHP

$payload = <<<'JSON'
{"refreshToken":"..."}
JSON;
$ch = curl_init($baseUrl . '/api/v1/auth/refresh');
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/refresh' \
+  -H 'Content-Type: application/json' \
+  -H 'Idempotency-Key: <uuid>' \
+  --data '{"refreshToken":"..."}'
Request
Response
Run the request to see the response.
POST/api/v1/rider/auth/otp/request
Public

Request OTP for existing-rider sign in (planned)

Endpoint guide What to send, parse and expect

Why it exists

Starts OTP sign-in for an existing rider who lost local app credentials.

Before you call

Use this for sign-in, not account creation. The phone must already belong to a rider.

Request fields

phone is an E.164 Nigerian mobile number.

What to parse

Show the masked destination and countdown, then collect the six-digit code.

Expected result

202 accepts the sign-in challenge.

Important

Live endpoint. It never creates a new account; unknown phone numbers return RIDER_NOT_FOUND.

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/rider/auth/otp/request', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Idempotency-Key': crypto.randomUUID()
  },
  body: JSON.stringify({"phone":"+2348000000000"})
});
const result = await response.json();

Python

payload = json.loads(r'''{"phone":"+2348000000000"}''')
response = requests.post(BASE_URL + '/api/v1/rider/auth/otp/request',
    headers={'Idempotency-Key': str(uuid.uuid4())},
    json=payload)
result = response.json()

PHP

$payload = <<<'JSON'
{"phone":"+2348000000000"}
JSON;
$ch = curl_init($baseUrl . '/api/v1/rider/auth/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/rider/auth/otp/request' \
+  -H 'Content-Type: application/json' \
+  -H 'Idempotency-Key: <uuid>' \
+  --data '{"phone":"+2348000000000"}'
Request
Response
Run the request to see the response.
POST/api/v1/rider/auth/otp/verify
Public

Verify existing-rider sign in OTP (planned)

Endpoint guide What to send, parse and expect

Why it exists

Verifies an existing rider sign-in OTP and issues an authenticated session.

Before you call

Call the rider auth OTP request first.

Request fields

phone and six-digit code are required.

What to parse

Store accessToken and refreshToken in secure storage; do not create onboarding profile data.

Expected result

200 returns a rider session.

Important

Live endpoint. It authenticates an existing rider and cannot create a 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/rider/auth/otp/verify', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Idempotency-Key': crypto.randomUUID()
  },
  body: JSON.stringify({"phone":"+2348000000000","code":"123456"})
});
const result = await response.json();

Python

payload = json.loads(r'''{"phone":"+2348000000000","code":"123456"}''')
response = requests.post(BASE_URL + '/api/v1/rider/auth/otp/verify',
    headers={'Idempotency-Key': str(uuid.uuid4())},
    json=payload)
result = response.json()

PHP

$payload = <<<'JSON'
{"phone":"+2348000000000","code":"123456"}
JSON;
$ch = curl_init($baseUrl . '/api/v1/rider/auth/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/rider/auth/otp/verify' \
+  -H 'Content-Type: application/json' \
+  -H 'Idempotency-Key: <uuid>' \
+  --data '{"phone":"+2348000000000","code":"123456"}'
Request
Response
Run the request to see the response.
POST/api/v1/rider/profile/phone/change/request
Bearer token

Request authenticated phone change (planned)

Endpoint guide What to send, parse and expect

Why it exists

Starts a verified phone-number change for an authenticated rider.

Before you call

Require the current access token and confirm the rider intends to change their number.

Request fields

phone is the new E.164 number.

What to parse

Show the masked new destination and countdown.

Expected result

202 accepts the phone-change challenge.

Important

This endpoint is planned; the old phone remains authoritative until verification succeeds.

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/rider/profile/phone/change/request', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    Authorization: 'Bearer <access-token>',
    'Idempotency-Key': crypto.randomUUID()
  },
  body: JSON.stringify({"phone":"+2348000000000"})
});
const result = await response.json();

Python

payload = json.loads(r'''{"phone":"+2348000000000"}''')
response = requests.post(BASE_URL + '/api/v1/rider/profile/phone/change/request',
    headers={'Idempotency-Key': str(uuid.uuid4())},
    json=payload)
result = response.json()

PHP

$payload = <<<'JSON'
{"phone":"+2348000000000"}
JSON;
$ch = curl_init($baseUrl . '/api/v1/rider/profile/phone/change/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/rider/profile/phone/change/request' \
+  -H 'Authorization: Bearer <access-token>' \
+  -H 'Content-Type: application/json' \
+  -H 'Idempotency-Key: <uuid>' \
+  --data '{"phone":"+2348000000000"}'
Request
Response
Run the request to see the response.
POST/api/v1/rider/profile/phone/change/verify
Bearer token

Verify authenticated phone change (planned)

Endpoint guide What to send, parse and expect

Why it exists

Completes a phone-number change after verifying the new phone.

Before you call

Use the authenticated rider session and the challenge code.

Request fields

phone and six-digit code are required.

What to parse

Refresh the dashboard/session identity after success.

Expected result

200 confirms the changed phone.

Important

This endpoint is planned; never update the phone locally before this response.

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/rider/profile/phone/change/verify', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    Authorization: 'Bearer <access-token>',
    'Idempotency-Key': crypto.randomUUID()
  },
  body: JSON.stringify({"phone":"+2348000000000","code":"123456"})
});
const result = await response.json();

Python

payload = json.loads(r'''{"phone":"+2348000000000","code":"123456"}''')
response = requests.post(BASE_URL + '/api/v1/rider/profile/phone/change/verify',
    headers={'Idempotency-Key': str(uuid.uuid4())},
    json=payload)
result = response.json()

PHP

$payload = <<<'JSON'
{"phone":"+2348000000000","code":"123456"}
JSON;
$ch = curl_init($baseUrl . '/api/v1/rider/profile/phone/change/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/rider/profile/phone/change/verify' \
+  -H 'Authorization: Bearer <access-token>' \
+  -H 'Content-Type: application/json' \
+  -H 'Idempotency-Key: <uuid>' \
+  --data '{"phone":"+2348000000000","code":"123456"}'
Request
Response
Run the request to see the response.
POST/api/v1/rider/onboarding/otp/request
Public

Request rider phone OTP

Endpoint guide What to send, parse and expect

Why it exists

Starts phone-number verification before any rider record or session is created.

Before you call

Normalize the phone to E.164, for example +2348000000000. This is public; do not send a bearer token.

Request fields

phone is the full international mobile number. The playground adds idempotencyKey automatically.

What to parse

Store expiresInSeconds to drive the OTP countdown and display destination only in its masked form.

Expected result

202 Accepted means a challenge was created; it does not mean the rider is authenticated.

Important

The OTP is sent by SMS in production. It is never part of a normal API response.

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/rider/onboarding/otp/request', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Idempotency-Key': crypto.randomUUID()
  },
  body: JSON.stringify({"phone":"+2348000000000"})
});
const result = await response.json();

Python

payload = json.loads(r'''{"phone":"+2348000000000"}''')
response = requests.post(BASE_URL + '/api/v1/rider/onboarding/otp/request',
    headers={'Idempotency-Key': str(uuid.uuid4())},
    json=payload)
result = response.json()

PHP

$payload = <<<'JSON'
{"phone":"+2348000000000"}
JSON;
$ch = curl_init($baseUrl . '/api/v1/rider/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/rider/onboarding/otp/request' \
+  -H 'Content-Type: application/json' \
+  -H 'Idempotency-Key: <uuid>' \
+  --data '{"phone":"+2348000000000"}'
Request
Response
Run the request to see the response.
POST/api/v1/rider/onboarding/otp/verify
Public

Verify OTP and receive onboarding token

Endpoint guide What to send, parse and expect

Why it exists

Validates the six-digit SMS code and creates a short-lived onboarding session.

Before you call

Call OTP request first. Enter the exact phone and six-digit code. This is still public.

Request fields

phone and code are required. The playground automatically saves data.onboardingToken into the Onboarding token field on success.

What to parse

Read data.onboardingToken. It is an opaque value used only in later onboarding JSON bodies, not in Authorization.

Expected result

200 returns the token and the next onboarding step.

Important

Do not persist this token after account completion; it expires and is not a bearer access token.

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/rider/onboarding/otp/verify', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Idempotency-Key': crypto.randomUUID()
  },
  body: JSON.stringify({"phone":"+2348000000000","code":"123456"})
});
const result = await response.json();

Python

payload = json.loads(r'''{"phone":"+2348000000000","code":"123456"}''')
response = requests.post(BASE_URL + '/api/v1/rider/onboarding/otp/verify',
    headers={'Idempotency-Key': str(uuid.uuid4())},
    json=payload)
result = response.json()

PHP

$payload = <<<'JSON'
{"phone":"+2348000000000","code":"123456"}
JSON;
$ch = curl_init($baseUrl . '/api/v1/rider/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/rider/onboarding/otp/verify' \
+  -H 'Content-Type: application/json' \
+  -H 'Idempotency-Key: <uuid>' \
+  --data '{"phone":"+2348000000000","code":"123456"}'
Request
Response
Run the request to see the response.
POST/api/v1/rider/onboarding/status
Public

Resume onboarding and read its current step

Endpoint guide What to send, parse and expect

Why it exists

Lets the app resume an interrupted signup at the correct screen.

Before you call

Verify the OTP first or paste the raw onboarding token in the Onboarding token field above.

Request fields

onboardingToken is injected automatically by this page. Mobile clients put it in JSON exactly as shown.

What to parse

Read the completed step flags and route the rider to the first incomplete screen.

Expected result

200 returns the current onboarding state.

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/rider/onboarding/status', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Idempotency-Key': crypto.randomUUID()
  },
  body: JSON.stringify({"onboardingToken":"..."})
});
const result = await response.json();

Python

payload = json.loads(r'''{"onboardingToken":"..."}''')
response = requests.post(BASE_URL + '/api/v1/rider/onboarding/status',
    headers={'Idempotency-Key': str(uuid.uuid4())},
    json=payload)
result = response.json()

PHP

$payload = <<<'JSON'
{"onboardingToken":"..."}
JSON;
$ch = curl_init($baseUrl . '/api/v1/rider/onboarding/status');
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/rider/onboarding/status' \
+  -H 'Content-Type: application/json' \
+  -H 'Idempotency-Key: <uuid>' \
+  --data '{"onboardingToken":"..."}'
Request
Response
Run the request to see the response.
PATCH/api/v1/rider/onboarding/profile
Public

Save rider profile

Endpoint guide What to send, parse and expect

Why it exists

Stores the legal profile details used to create the rider account.

Before you call

A valid onboarding token is required. Ask for consent before sending personal data.

Request fields

firstName, lastName, email, gender and birthDate use ISO YYYY-MM-DD. onboardingToken is auto-injected here.

What to parse

Use returned profile/onboarding state to decide whether to request location or a photo next.

Expected result

200 confirms the profile was saved.

Important

Do not use display names in place of legal name fields or trust client-side age checks.

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/rider/onboarding/profile', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/json',
    'Idempotency-Key': crypto.randomUUID()
  },
  body: JSON.stringify({"onboardingToken":"...","firstName":"Ada","lastName":"Okafor","email":"ada@example.test","gender":"FEMALE","birthDate":"1995-08-18"})
});
const result = await response.json();

Python

payload = json.loads(r'''{"onboardingToken":"...","firstName":"Ada","lastName":"Okafor","email":"ada@example.test","gender":"FEMALE","birthDate":"1995-08-18"}''')
response = requests.patch(BASE_URL + '/api/v1/rider/onboarding/profile',
    headers={'Idempotency-Key': str(uuid.uuid4())},
    json=payload)
result = response.json()

PHP

$payload = <<<'JSON'
{"onboardingToken":"...","firstName":"Ada","lastName":"Okafor","email":"ada@example.test","gender":"FEMALE","birthDate":"1995-08-18"}
JSON;
$ch = curl_init($baseUrl . '/api/v1/rider/onboarding/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/rider/onboarding/profile' \
+  -H 'Content-Type: application/json' \
+  -H 'Idempotency-Key: <uuid>' \
+  --data '{"onboardingToken":"...","firstName":"Ada","lastName":"Okafor","email":"ada@example.test","gender":"FEMALE","birthDate":"1995-08-18"}'
Request
Response
Run the request to see the response.
POST/api/v1/rider/onboarding/profile-photo
Public

Upload a validated profile image (multipart form field: file)

Endpoint guide What to send, parse and expect

Why it exists

Uploads and validates the rider profile image for account recognition and safety.

Before you call

Choose a JPEG, PNG or WebP image using the Profile image chooser below. Do not base64-encode it.

Request fields

This is multipart/form-data, not JSON. The browser sends the selected file in field file and sends onboardingToken as a form field automatically.

What to parse

Read the returned photo URL/key and display only the approved server result.

Expected result

200 confirms the uploaded photo.

Important

The backend validates file type and size; the frontend should also show an upload-progress and retry state.

Request structure and code samples Node.js · Python · PHP · cURL

This endpoint uses multipart/form-data. Send the selected image using the exact field name file; do not manually set the multipart Content-Type boundary.

Node.js

const form = new FormData();
form.append('onboardingToken', '<onboarding-token>');
form.append('file', fileInput.files[0]);
const response = await fetch('/api/v1/rider/onboarding/profile-photo', { method: 'POST', body: form });
const result = await response.json();

Python

with open('profile.jpg', 'rb') as photo:
    response = requests.post(BASE_URL + '/api/v1/rider/onboarding/profile-photo',
        data={'onboardingToken': '<onboarding-token>'},
        files={'file': ('profile.jpg', photo, 'image/jpeg')})
result = response.json()

PHP

$payload = [
  'onboardingToken' => '<onboarding-token>',
  'file' => new CURLFile('/path/to/profile.jpg', 'image/jpeg'),
];
$ch = curl_init($baseUrl . '/api/v1/rider/onboarding/profile-photo');
curl_setopt_array($ch, [CURLOPT_POST => true, CURLOPT_POSTFIELDS => $payload, CURLOPT_RETURNTRANSFER => true]);

cURL

curl -X POST '<base-url>/api/v1/rider/onboarding/profile-photo' \
+  -F 'onboardingToken=<onboarding-token>' \
+  -F 'file=@/path/to/profile.jpg;type=image/jpeg'
Request
Response
Run the request to see the response.
POST/api/v1/rider/onboarding/complete
Public

Create account and issue tokens

Endpoint guide What to send, parse and expect

Why it exists

Creates the rider account and exchanges the onboarding session for authenticated tokens.

Before you call

Complete all required onboarding steps, then call once. Do not call repeatedly from double taps.

Request fields

onboardingToken is injected automatically. No bearer token is used for this call.

What to parse

Persist data.accessToken and refresh token only in secure mobile storage. This page automatically places accessToken in the Access token field.

Expected result

201 Created means the rider is now authenticated.

Important

Use the raw access token in the page field; the playground adds Authorization: Bearer automatically.

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/rider/onboarding/complete', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Idempotency-Key': crypto.randomUUID()
  },
  body: JSON.stringify({"onboardingToken":"..."})
});
const result = await response.json();

Python

payload = json.loads(r'''{"onboardingToken":"..."}''')
response = requests.post(BASE_URL + '/api/v1/rider/onboarding/complete',
    headers={'Idempotency-Key': str(uuid.uuid4())},
    json=payload)
result = response.json()

PHP

$payload = <<<'JSON'
{"onboardingToken":"..."}
JSON;
$ch = curl_init($baseUrl . '/api/v1/rider/onboarding/complete');
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/rider/onboarding/complete' \
+  -H 'Content-Type: application/json' \
+  -H 'Idempotency-Key: <uuid>' \
+  --data '{"onboardingToken":"..."}'
Request
Response
Run the request to see the response.
GET/api/v1/rider/dashboard
Bearer token

Rider dashboard, active trip, saved places and Cruz Pass

Endpoint guide What to send, parse and expect

Why it exists

Provides the authenticated home-screen snapshot: rider state, active ride, saved places and pass summary.

Before you call

Complete onboarding and paste the raw access token once in the Access token field above.

Request fields

No JSON body. The page automatically sends Authorization: Bearer <accessToken>.

What to parse

Render the returned active-trip status as the source of truth; refetch after app resume or socket reconnect.

Expected result

200 returns the current dashboard model.

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/rider/dashboard', {
  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/rider/dashboard',
    headers={'Idempotency-Key': str(uuid.uuid4())},
    json=payload)
result = response.json()

PHP

$payload = <<<'JSON'
{}
JSON;
$ch = curl_init($baseUrl . '/api/v1/rider/dashboard');
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/rider/dashboard' \
+  -H 'Authorization: Bearer <access-token>' \
+  -H 'Content-Type: application/json' \
+  -H 'Idempotency-Key: <uuid>' \
+  --data '{}'
Request
Response
Run the request to see the response.
GET/api/v1/rider/profile
Bearer token

Read the authenticated rider 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/rider/profile', {
  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/rider/profile',
    headers={'Idempotency-Key': str(uuid.uuid4())},
    json=payload)
result = response.json()

PHP

$payload = <<<'JSON'
{}
JSON;
$ch = curl_init($baseUrl . '/api/v1/rider/profile');
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/rider/profile' \
+  -H 'Authorization: Bearer <access-token>' \
+  -H 'Content-Type: application/json' \
+  -H 'Idempotency-Key: <uuid>' \
+  --data '{}'
Request
Response
Run the request to see the response.
PATCH/api/v1/rider/profile
Bearer token

Update editable rider profile fields

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/rider/profile', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/json',
    Authorization: 'Bearer <access-token>',
    'Idempotency-Key': crypto.randomUUID()
  },
  body: JSON.stringify({"firstName":"Ada","lastName":"Okafor","email":"ada@example.test"})
});
const result = await response.json();

Python

payload = json.loads(r'''{"firstName":"Ada","lastName":"Okafor","email":"ada@example.test"}''')
response = requests.patch(BASE_URL + '/api/v1/rider/profile',
    headers={'Idempotency-Key': str(uuid.uuid4())},
    json=payload)
result = response.json()

PHP

$payload = <<<'JSON'
{"firstName":"Ada","lastName":"Okafor","email":"ada@example.test"}
JSON;
$ch = curl_init($baseUrl . '/api/v1/rider/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/rider/profile' \
+  -H 'Authorization: Bearer <access-token>' \
+  -H 'Content-Type: application/json' \
+  -H 'Idempotency-Key: <uuid>' \
+  --data '{"firstName":"Ada","lastName":"Okafor","email":"ada@example.test"}'
Request
Response
Run the request to see the response.
GET/api/v1/rider/notifications
Bearer token

List rider notifications

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/rider/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/rider/notifications',
    headers={'Idempotency-Key': str(uuid.uuid4())},
    json=payload)
result = response.json()

PHP

$payload = <<<'JSON'
{}
JSON;
$ch = curl_init($baseUrl . '/api/v1/rider/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/rider/notifications' \
+  -H 'Authorization: Bearer <access-token>' \
+  -H 'Content-Type: application/json' \
+  -H 'Idempotency-Key: <uuid>' \
+  --data '{}'
Request
Response
Run the request to see the response.
POST/api/v1/rider/notifications/:id/read
Bearer token

Mark one notification as read

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/rider/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/rider/notifications/:id/read',
    headers={'Idempotency-Key': str(uuid.uuid4())},
    json=payload)
result = response.json()

PHP

$payload = <<<'JSON'
{}
JSON;
$ch = curl_init($baseUrl . '/api/v1/rider/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/rider/notifications/:id/read' \
+  -H 'Authorization: Bearer <access-token>' \
+  -H 'Content-Type: application/json' \
+  -H 'Idempotency-Key: <uuid>' \
+  --data '{}'
Request
Response
Run the request to see the response.
GET/api/v1/rider/referral
Bearer token

Read the rider referral code and share payload

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/rider/referral', {
  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/rider/referral',
    headers={'Idempotency-Key': str(uuid.uuid4())},
    json=payload)
result = response.json()

PHP

$payload = <<<'JSON'
{}
JSON;
$ch = curl_init($baseUrl . '/api/v1/rider/referral');
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/rider/referral' \
+  -H 'Authorization: Bearer <access-token>' \
+  -H 'Content-Type: application/json' \
+  -H 'Idempotency-Key: <uuid>' \
+  --data '{}'
Request
Response
Run the request to see the response.
GET/api/v1/rider/passes/active
Bearer token

Read the authenticated rider Cruz Pass balance

Endpoint guide What to send, parse and expect

Why it exists

Returns the rider Cruz Pass balance and whether it can be applied to a quote.

Before you call

Requires an authenticated rider. Sync once after account creation if an external pass may exist.

Request fields

No body. Access token only.

What to parse

Use balanceNaira for display. The maximum discount per eligible ride is ₦1,000 even when balance is higher.

Expected result

200 returns a zero balance when no linked pass exists.

Important

Never reduce balance in the mobile app; the server owns all debits and reversals.

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/rider/passes/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/rider/passes/active',
    headers={'Idempotency-Key': str(uuid.uuid4())},
    json=payload)
result = response.json()

PHP

$payload = <<<'JSON'
{}
JSON;
$ch = curl_init($baseUrl . '/api/v1/rider/passes/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/rider/passes/active' \
+  -H 'Authorization: Bearer <access-token>' \
+  -H 'Content-Type: application/json' \
+  -H 'Idempotency-Key: <uuid>' \
+  --data '{}'
Request
Response
Run the request to see the response.
POST/api/v1/rider/passes/sync
Bearer token

Sync eligible Cruz Pass credit from the source database

Endpoint guide What to send, parse and expect

Why it exists

Looks up an eligible Cruz Pass in the server-side source database using the rider identity and credits it safely.

Before you call

Requires an authenticated rider. Call sparingly, such as after onboarding or a manual refresh.

Request fields

No business fields are needed. The playground adds an idempotency key.

What to parse

Read match/credit outcome and then refresh passes/active. A no-match is a normal successful result.

Expected result

200 confirms source lookup/synchronisation.

Important

The frontend never receives Supabase credentials or performs the source lookup.

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/rider/passes/sync', {
  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/rider/passes/sync',
    headers={'Idempotency-Key': str(uuid.uuid4())},
    json=payload)
result = response.json()

PHP

$payload = <<<'JSON'
{}
JSON;
$ch = curl_init($baseUrl . '/api/v1/rider/passes/sync');
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/rider/passes/sync' \
+  -H 'Authorization: Bearer <access-token>' \
+  -H 'Content-Type: application/json' \
+  -H 'Idempotency-Key: <uuid>' \
+  --data '{}'
Request
Response
Run the request to see the response.
POST/api/v1/rider/quotes
Bearer token

Create a server-calculated fare quote

Endpoint guide What to send, parse and expect

Why it exists

Calculates a time-limited, server-owned fare before the rider books.

Before you call

Obtain real coordinates from your maps/geocoding provider. The frontend must never compute or alter fare values.

Request fields

pickup/dropoff each need latitude, longitude and label; distanceKm and durationMinutes are current routing inputs; usePass requests eligible Cruz Pass use.

What to parse

Read quote id, expiry, fare breakdown and any pass discount. Show the exact server price and expiry.

Expected result

201 creates an unexpired quote.

Important

Discard expired quotes and obtain a new quote; do not reuse one for a different route.

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/rider/quotes', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    Authorization: 'Bearer <access-token>',
    'Idempotency-Key': crypto.randomUUID()
  },
  body: JSON.stringify({"pickup":{"latitude":4.8156,"longitude":7.0498,"label":"Pickup"},"dropoff":{"latitude":4.83,"longitude":7.02,"label":"Destination"},"distanceKm":4.2,"durationMinutes":18,"usePass":true})
});
const result = await response.json();

Python

payload = json.loads(r'''{"pickup":{"latitude":4.8156,"longitude":7.0498,"label":"Pickup"},"dropoff":{"latitude":4.83,"longitude":7.02,"label":"Destination"},"distanceKm":4.2,"durationMinutes":18,"usePass":true}''')
response = requests.post(BASE_URL + '/api/v1/rider/quotes',
    headers={'Idempotency-Key': str(uuid.uuid4())},
    json=payload)
result = response.json()

PHP

$payload = <<<'JSON'
{"pickup":{"latitude":4.8156,"longitude":7.0498,"label":"Pickup"},"dropoff":{"latitude":4.83,"longitude":7.02,"label":"Destination"},"distanceKm":4.2,"durationMinutes":18,"usePass":true}
JSON;
$ch = curl_init($baseUrl . '/api/v1/rider/quotes');
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/rider/quotes' \
+  -H 'Authorization: Bearer <access-token>' \
+  -H 'Content-Type: application/json' \
+  -H 'Idempotency-Key: <uuid>' \
+  --data '{"pickup":{"latitude":4.8156,"longitude":7.0498,"label":"Pickup"},"dropoff":{"latitude":4.83,"longitude":7.02,"label":"Destination"},"distanceKm":4.2,"durationMinutes":18,"usePass":true}'
Request
Response
Run the request to see the response.
POST/api/v1/rider/trips
Bearer token

Book a ride from an unexpired quote

Endpoint guide What to send, parse and expect

Why it exists

Books a rider-owned trip from one unexpired quote.

Before you call

Call quotes first and ensure the rider confirms the returned price. Disable the confirm button while this request is in flight.

Request fields

quoteId is the UUID returned by quotes. The Idempotency-Key prevents accidental duplicate bookings.

What to parse

Read trip id and status; use them to render matching/driver-assignment UI.

Expected result

201 creates the trip or returns a safe business error if it cannot be booked.

Important

Never construct a trip directly from pickup/dropoff or client-provided money amounts.

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/rider/trips', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    Authorization: 'Bearer <access-token>',
    'Idempotency-Key': crypto.randomUUID()
  },
  body: JSON.stringify({"quoteId":"uuid"})
});
const result = await response.json();

Python

payload = json.loads(r'''{"quoteId":"uuid"}''')
response = requests.post(BASE_URL + '/api/v1/rider/trips',
    headers={'Idempotency-Key': str(uuid.uuid4())},
    json=payload)
result = response.json()

PHP

$payload = <<<'JSON'
{"quoteId":"uuid"}
JSON;
$ch = curl_init($baseUrl . '/api/v1/rider/trips');
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/rider/trips' \
+  -H 'Authorization: Bearer <access-token>' \
+  -H 'Content-Type: application/json' \
+  -H 'Idempotency-Key: <uuid>' \
+  --data '{"quoteId":"uuid"}'
Request
Response
Run the request to see the response.
POST/api/v1/rider/trips/:id/matching
Bearer token

Start or safely retry driver matching

Endpoint guide What to send, parse and expect

Why it exists

Starts or reads durable driver matching for a rider-owned searching trip.

Before you call

Book from a server quote first. The booking response begins matching automatically; use POST only for a safe retry.

Request fields

Replace :id with the searching trip UUID. No business body is required. The server makes one expiring driver offer at a time.

What to parse

matchingState is OFFERED or NO_DRIVER_FOUND. When OFFERED, show matching UI and listen for trip:state_updated; never display the internal offer to the rider.

Expected result

POST 202 accepts matching; GET 200 returns current matching outcome.

Important

The backend decides availability, assignment and reassignment. Riders cannot choose or assign drivers.

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/rider/trips/:id/matching', {
  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/rider/trips/:id/matching',
    headers={'Idempotency-Key': str(uuid.uuid4())},
    json=payload)
result = response.json()

PHP

$payload = <<<'JSON'
{}
JSON;
$ch = curl_init($baseUrl . '/api/v1/rider/trips/:id/matching');
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/rider/trips/:id/matching' \
+  -H 'Authorization: Bearer <access-token>' \
+  -H 'Content-Type: application/json' \
+  -H 'Idempotency-Key: <uuid>' \
+  --data '{}'
Request
Response
Run the request to see the response.
GET/api/v1/rider/trips/:id/matching
Bearer token

Read current driver-matching outcome

Endpoint guide What to send, parse and expect

Why it exists

Starts or reads durable driver matching for a rider-owned searching trip.

Before you call

Book from a server quote first. The booking response begins matching automatically; use POST only for a safe retry.

Request fields

Replace :id with the searching trip UUID. No business body is required. The server makes one expiring driver offer at a time.

What to parse

matchingState is OFFERED or NO_DRIVER_FOUND. When OFFERED, show matching UI and listen for trip:state_updated; never display the internal offer to the rider.

Expected result

POST 202 accepts matching; GET 200 returns current matching outcome.

Important

The backend decides availability, assignment and reassignment. Riders cannot choose or assign drivers.

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/rider/trips/:id/matching', {
  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/rider/trips/:id/matching',
    headers={'Idempotency-Key': str(uuid.uuid4())},
    json=payload)
result = response.json()

PHP

$payload = <<<'JSON'
{}
JSON;
$ch = curl_init($baseUrl . '/api/v1/rider/trips/:id/matching');
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/rider/trips/:id/matching' \
+  -H 'Authorization: Bearer <access-token>' \
+  -H 'Content-Type: application/json' \
+  -H 'Idempotency-Key: <uuid>' \
+  --data '{}'
Request
Response
Run the request to see the response.
POST/api/v1/rider/trips/:id/cancel
Bearer token

Cancel a rider-owned active ride

Endpoint guide What to send, parse and expect

Why it exists

Cancels an active trip belonging to the authenticated rider.

Before you call

Use the active trip id from dashboard or booking response. Confirm intent in the UI before sending.

Request fields

Replace :id in Test URL with the trip UUID. reason must be one allowed cancellation reason.

What to parse

Render the returned cancelled state and refresh dashboard/pass data; any pass hold/reversal is handled server-side.

Expected result

200 confirms cancellation; an invalid state is a business error.

Important

The server verifies ownership and current state, so a rider cannot cancel another rider’s 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/rider/trips/:id/cancel', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    Authorization: 'Bearer <access-token>',
    'Idempotency-Key': crypto.randomUUID()
  },
  body: JSON.stringify({"reason":"CHANGED_PLANS"})
});
const result = await response.json();

Python

payload = json.loads(r'''{"reason":"CHANGED_PLANS"}''')
response = requests.post(BASE_URL + '/api/v1/rider/trips/:id/cancel',
    headers={'Idempotency-Key': str(uuid.uuid4())},
    json=payload)
result = response.json()

PHP

$payload = <<<'JSON'
{"reason":"CHANGED_PLANS"}
JSON;
$ch = curl_init($baseUrl . '/api/v1/rider/trips/:id/cancel');
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/rider/trips/:id/cancel' \
+  -H 'Authorization: Bearer <access-token>' \
+  -H 'Content-Type: application/json' \
+  -H 'Idempotency-Key: <uuid>' \
+  --data '{"reason":"CHANGED_PLANS"}'
Request
Response
Run the request to see the response.
POST/api/v1/rider/places
Bearer token

Save a Home, Work or favourite place

Endpoint guide What to send, parse and expect

Why it exists

Stores a Home, Work or favourite address for quicker future trip entry.

Before you call

Requires an authenticated rider and a geocoded, rider-confirmed address.

Request fields

kind, label, address, latitude and longitude describe the saved place. Use the API result rather than a local-only copy.

What to parse

Read the saved-place id and updated place data for the dashboard.

Expected result

201 creates the saved place.

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/rider/places', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    Authorization: 'Bearer <access-token>',
    'Idempotency-Key': crypto.randomUUID()
  },
  body: JSON.stringify({"kind":"HOME","label":"Home","address":"12 Ricewood Estate","latitude":6.431,"longitude":3.492})
});
const result = await response.json();

Python

payload = json.loads(r'''{"kind":"HOME","label":"Home","address":"12 Ricewood Estate","latitude":6.431,"longitude":3.492}''')
response = requests.post(BASE_URL + '/api/v1/rider/places',
    headers={'Idempotency-Key': str(uuid.uuid4())},
    json=payload)
result = response.json()

PHP

$payload = <<<'JSON'
{"kind":"HOME","label":"Home","address":"12 Ricewood Estate","latitude":6.431,"longitude":3.492}
JSON;
$ch = curl_init($baseUrl . '/api/v1/rider/places');
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/rider/places' \
+  -H 'Authorization: Bearer <access-token>' \
+  -H 'Content-Type: application/json' \
+  -H 'Idempotency-Key: <uuid>' \
+  --data '{"kind":"HOME","label":"Home","address":"12 Ricewood Estate","latitude":6.431,"longitude":3.492}'
Request
Response
Run the request to see the response.
POST/api/v1/rider/trips/:id/reports
Bearer token

Submit a trip issue report

Endpoint guide What to send, parse and expect

Why it exists

Creates a support/operations report tied to a rider-owned trip.

Before you call

Use a completed or relevant trip id. For immediate danger, use emergency services; this is not an SOS channel.

Request fields

Replace :id with the trip UUID. category identifies the issue; details gives the operations team context.

What to parse

Read the report id/status, show the confirmation UI, and avoid exposing internal investigation notes.

Expected result

201 acknowledges the report.

Important

The backend confirms trip ownership and keeps reports available to authorised operations staff only.

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/rider/trips/:id/reports', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    Authorization: 'Bearer <access-token>',
    'Idempotency-Key': crypto.randomUUID()
  },
  body: JSON.stringify({"category":"INCORRECT_FARE","details":"Please review."})
});
const result = await response.json();

Python

payload = json.loads(r'''{"category":"INCORRECT_FARE","details":"Please review."}''')
response = requests.post(BASE_URL + '/api/v1/rider/trips/:id/reports',
    headers={'Idempotency-Key': str(uuid.uuid4())},
    json=payload)
result = response.json()

PHP

$payload = <<<'JSON'
{"category":"INCORRECT_FARE","details":"Please review."}
JSON;
$ch = curl_init($baseUrl . '/api/v1/rider/trips/:id/reports');
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/rider/trips/:id/reports' \
+  -H 'Authorization: Bearer <access-token>' \
+  -H 'Content-Type: application/json' \
+  -H 'Idempotency-Key: <uuid>' \
+  --data '{"category":"INCORRECT_FARE","details":"Please review."}'
Request
Response
Run the request to see the response.
GET/api/v1/trips/mine
Bearer token

List the authenticated rider’s trips

Endpoint guide What to send, parse and expect

Why it exists

Lists trips owned by the authenticated rider for a history screen.

Before you call

Complete onboarding and provide an access token.

Request fields

No JSON body. The server determines ownership from the bearer token.

What to parse

Render only the returned records; do not merge another rider’s locally cached trip data.

Expected result

200 returns the caller’s trips.

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/mine', {
  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/mine',
    headers={'Idempotency-Key': str(uuid.uuid4())},
    json=payload)
result = response.json()

PHP

$payload = <<<'JSON'
{}
JSON;
$ch = curl_init($baseUrl . '/api/v1/trips/mine');
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/mine' \
+  -H 'Authorization: Bearer <access-token>' \
+  -H 'Content-Type: application/json' \
+  -H 'Idempotency-Key: <uuid>' \
+  --data '{}'
Request
Response
Run the request to see the response.
GET/api/v1/trips/:id
Bearer token

Read an authorised trip

Endpoint guide What to send, parse and expect

Why it exists

Reads one trip that the authenticated rider is permitted to view.

Before you call

Replace :id with an id from a booking, dashboard or trip-history result.

Request fields

No JSON body. Bearer authentication is required.

What to parse

Use current status and trip fields to refresh a trip-detail screen.

Expected result

200 returns the trip or a safe access/not-found error.

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', {
  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',
    headers={'Idempotency-Key': str(uuid.uuid4())},
    json=payload)
result = response.json()

PHP

$payload = <<<'JSON'
{}
JSON;
$ch = curl_init($baseUrl . '/api/v1/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/trips/:id' \
+  -H 'Authorization: Bearer <access-token>' \
+  -H 'Content-Type: application/json' \
+  -H 'Idempotency-Key: <uuid>' \
+  --data '{}'
Request
Response
Run the request to see the response.
POST/api/v1/trips/:id/rating
Bearer token

Rate a completed trip

Endpoint guide What to send, parse and expect

Why it exists

Submits rider feedback after a trip.

Before you call

Use a completed trip id and show this only when rating is allowed by the backend state.

Request fields

Replace :id with the trip UUID. rating is a whole-number star score; comment is optional feedback.

What to parse

Show the submitted confirmation and prevent a second submission according to the response.

Expected result

200 confirms the feedback or returns a state/ownership error.

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/rating', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    Authorization: 'Bearer <access-token>',
    'Idempotency-Key': crypto.randomUUID()
  },
  body: JSON.stringify({"score":5,"comment":"Great ride"})
});
const result = await response.json();

Python

payload = json.loads(r'''{"score":5,"comment":"Great ride"}''')
response = requests.post(BASE_URL + '/api/v1/trips/:id/rating',
    headers={'Idempotency-Key': str(uuid.uuid4())},
    json=payload)
result = response.json()

PHP

$payload = <<<'JSON'
{"score":5,"comment":"Great ride"}
JSON;
$ch = curl_init($baseUrl . '/api/v1/trips/:id/rating');
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/rating' \
+  -H 'Authorization: Bearer <access-token>' \
+  -H 'Content-Type: application/json' \
+  -H 'Idempotency-Key: <uuid>' \
+  --data '{"score":5,"comment":"Great ride"}'
Request
Response
Run the request to see the response.
POST/api/v1/payments/intents
Bearer token

Create payment instructions for a completed trip

Endpoint guide What to send, parse and expect

Why it exists

Creates the payment instruction for a completed rider trip.

Before you call

The trip must be completed and unpaid. Use the trip id from the final trip state.

Request fields

tripId is the rider-owned trip UUID. method is BANK_TRANSFER or CASH.

What to parse

For BANK_TRANSFER, render paymentInstructions exactly as returned; for CASH, show the amount due and wait for driver confirmation.

Expected result

201 returns the payment intent.

Important

Never accept account details, amount or payment status from a client-side calculation.

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/payments/intents', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    Authorization: 'Bearer <access-token>',
    'Idempotency-Key': crypto.randomUUID()
  },
  body: JSON.stringify({"tripId":"uuid","method":"BANK_TRANSFER"})
});
const result = await response.json();

Python

payload = json.loads(r'''{"tripId":"uuid","method":"BANK_TRANSFER"}''')
response = requests.post(BASE_URL + '/api/v1/payments/intents',
    headers={'Idempotency-Key': str(uuid.uuid4())},
    json=payload)
result = response.json()

PHP

$payload = <<<'JSON'
{"tripId":"uuid","method":"BANK_TRANSFER"}
JSON;
$ch = curl_init($baseUrl . '/api/v1/payments/intents');
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/payments/intents' \
+  -H 'Authorization: Bearer <access-token>' \
+  -H 'Content-Type: application/json' \
+  -H 'Idempotency-Key: <uuid>' \
+  --data '{"tripId":"uuid","method":"BANK_TRANSFER"}'
Request
Response
Run the request to see the response.
GET/api/v1/payments/intents/:id
Bearer token

Read a payment intent

Endpoint guide What to send, parse and expect

Why it exists

Retrieves the current payment-intent state for the rider’s payment screen.

Before you call

Replace :id with the payment-intent UUID from intent creation.

Request fields

No JSON body. Bearer authentication enforces rider ownership.

What to parse

Use status, amountMinor and paymentInstructions to render the payment state.

Expected result

200 returns the intent or an access error.

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/payments/intents/: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/payments/intents/:id',
    headers={'Idempotency-Key': str(uuid.uuid4())},
    json=payload)
result = response.json()

PHP

$payload = <<<'JSON'
{}
JSON;
$ch = curl_init($baseUrl . '/api/v1/payments/intents/: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/payments/intents/:id' \
+  -H 'Authorization: Bearer <access-token>' \
+  -H 'Content-Type: application/json' \
+  -H 'Idempotency-Key: <uuid>' \
+  --data '{}'
Request
Response
Run the request to see the response.
POST/api/v1/payments/intents/:id/verify
Bearer token

Verify a payment intent

Endpoint guide What to send, parse and expect

Why it exists

Asks the server to verify a provider-backed payment intent safely.

Before you call

Use only after the rider has made the instructed payment; the server, not the frontend, decides whether it is paid.

Request fields

Replace :id with the payment-intent UUID. No JSON business fields are required.

What to parse

Render returned status. Treat pending/failed states as server truth and offer a refresh/retry UI.

Expected result

200 returns the verified payment state.

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/payments/intents/:id/verify', {
  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/payments/intents/:id/verify',
    headers={'Idempotency-Key': str(uuid.uuid4())},
    json=payload)
result = response.json()

PHP

$payload = <<<'JSON'
{}
JSON;
$ch = curl_init($baseUrl . '/api/v1/payments/intents/:id/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/payments/intents/:id/verify' \
+  -H 'Authorization: Bearer <access-token>' \
+  -H 'Content-Type: application/json' \
+  -H 'Idempotency-Key: <uuid>' \
+  --data '{}'
Request
Response
Run the request to see the response.
GET/api/v1/rider/safety/trusted-contacts
Bearer token

List trusted safety contacts

Endpoint guide What to send, parse and expect

Why it exists

Manages people the rider trusts for safety-related trip sharing.

Before you call

Requires an access token. Display contacts only to their owner.

Request fields

POST uses name, E.164 phone and idempotencyKey. GET has no body. DELETE replaces :id with a returned contact id.

What to parse

Use id/name/phone from the response; never expose this list in shared-trip data.

Expected result

POST 201 creates or updates; GET 200 lists; DELETE 200 confirms removal.

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/rider/safety/trusted-contacts', {
  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/rider/safety/trusted-contacts',
    headers={'Idempotency-Key': str(uuid.uuid4())},
    json=payload)
result = response.json()

PHP

$payload = <<<'JSON'
{}
JSON;
$ch = curl_init($baseUrl . '/api/v1/rider/safety/trusted-contacts');
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/rider/safety/trusted-contacts' \
+  -H 'Authorization: Bearer <access-token>' \
+  -H 'Content-Type: application/json' \
+  -H 'Idempotency-Key: <uuid>' \
+  --data '{}'
Request
Response
Run the request to see the response.
POST/api/v1/rider/safety/trusted-contacts
Bearer token

Add or update a trusted safety contact

Endpoint guide What to send, parse and expect

Why it exists

Manages people the rider trusts for safety-related trip sharing.

Before you call

Requires an access token. Display contacts only to their owner.

Request fields

POST uses name, E.164 phone and idempotencyKey. GET has no body. DELETE replaces :id with a returned contact id.

What to parse

Use id/name/phone from the response; never expose this list in shared-trip data.

Expected result

POST 201 creates or updates; GET 200 lists; DELETE 200 confirms removal.

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/rider/safety/trusted-contacts', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    Authorization: 'Bearer <access-token>',
    'Idempotency-Key': crypto.randomUUID()
  },
  body: JSON.stringify({"name":"Ada’s sister","phone":"+2348000000000"})
});
const result = await response.json();

Python

payload = json.loads(r'''{"name":"Ada’s sister","phone":"+2348000000000"}''')
response = requests.post(BASE_URL + '/api/v1/rider/safety/trusted-contacts',
    headers={'Idempotency-Key': str(uuid.uuid4())},
    json=payload)
result = response.json()

PHP

$payload = <<<'JSON'
{"name":"Ada’s sister","phone":"+2348000000000"}
JSON;
$ch = curl_init($baseUrl . '/api/v1/rider/safety/trusted-contacts');
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/rider/safety/trusted-contacts' \
+  -H 'Authorization: Bearer <access-token>' \
+  -H 'Content-Type: application/json' \
+  -H 'Idempotency-Key: <uuid>' \
+  --data '{"name":"Ada’s sister","phone":"+2348000000000"}'
Request
Response
Run the request to see the response.
DELETE/api/v1/rider/safety/trusted-contacts/:id
Bearer token

Remove a trusted safety contact

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/rider/safety/trusted-contacts/:id', {
  method: 'DELETE',
  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.delete(BASE_URL + '/api/v1/rider/safety/trusted-contacts/:id',
    headers={'Idempotency-Key': str(uuid.uuid4())},
    json=payload)
result = response.json()

PHP

$payload = <<<'JSON'
{}
JSON;
$ch = curl_init($baseUrl . '/api/v1/rider/safety/trusted-contacts/:id');
curl_setopt_array($ch, [
  CURLOPT_CUSTOMREQUEST => 'DELETE',
  CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Idempotency-Key: <uuid>'],
  CURLOPT_POSTFIELDS => $payload,
  CURLOPT_RETURNTRANSFER => true,
]);

cURL

curl -X DELETE '<base-url>/api/v1/rider/safety/trusted-contacts/:id' \
+  -H 'Authorization: Bearer <access-token>' \
+  -H 'Content-Type: application/json' \
+  -H 'Idempotency-Key: <uuid>' \
+  --data '{}'
Request
Response
Run the request to see the response.
GET/api/v1/rider/shared-trips/:token
Public

Open a public, limited trip-share view

Endpoint guide What to send, parse and expect

Why it exists

Returns the deliberately limited live trip view for a holder of an unexpired share link.

Before you call

This is public and must only be opened with a token received through a trusted sharing channel.

Request fields

Replace :token with the opaque token from share-link creation. No bearer token or JSON body.

What to parse

Render the returned status, route labels, limited driver/vehicle details and fresh location. Do not request rider contact data.

Expected result

200 returns an unexpired share; 404 hides whether a link ever existed.

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/rider/shared-trips/:token', {
  method: 'GET',
  headers: {
    'Content-Type': 'application/json',
    'Idempotency-Key': crypto.randomUUID()
  },
  body: JSON.stringify({})
});
const result = await response.json();

Python

payload = json.loads(r'''{}''')
response = requests.get(BASE_URL + '/api/v1/rider/shared-trips/:token',
    headers={'Idempotency-Key': str(uuid.uuid4())},
    json=payload)
result = response.json()

PHP

$payload = <<<'JSON'
{}
JSON;
$ch = curl_init($baseUrl . '/api/v1/rider/shared-trips/:token');
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/rider/shared-trips/:token' \
+  -H 'Content-Type: application/json' \
+  -H 'Idempotency-Key: <uuid>' \
+  --data '{}'
Request
Response
Run the request to see the response.
POST/api/v1/rider/trips/:id/safety-incidents
Bearer token

Raise SOS or another trip safety incident

Endpoint guide What to send, parse and expect

Why it exists

Raises a safety incident, including SOS and extra-money requests, to authorised operations staff.

Before you call

The rider must own the trip. In a life-threatening emergency, the app must also direct the rider to local emergency services.

Request fields

type, description, optional coordinates and idempotencyKey. Replace :id with the trip UUID.

What to parse

Read incident id, status and severity, then show a clear submitted/ongoing-safety state.

Expected result

201 opens the incident with HIGH or CRITICAL severity.

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/rider/trips/:id/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 help","latitude":6.431,"longitude":3.492})
});
const result = await response.json();

Python

payload = json.loads(r'''{"type":"SOS","description":"I need help","latitude":6.431,"longitude":3.492}''')
response = requests.post(BASE_URL + '/api/v1/rider/trips/:id/safety-incidents',
    headers={'Idempotency-Key': str(uuid.uuid4())},
    json=payload)
result = response.json()

PHP

$payload = <<<'JSON'
{"type":"SOS","description":"I need help","latitude":6.431,"longitude":3.492}
JSON;
$ch = curl_init($baseUrl . '/api/v1/rider/trips/:id/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/rider/trips/:id/safety-incidents' \
+  -H 'Authorization: Bearer <access-token>' \
+  -H 'Content-Type: application/json' \
+  -H 'Idempotency-Key: <uuid>' \
+  --data '{"type":"SOS","description":"I need help","latitude":6.431,"longitude":3.492}'
Request
Response
Run the request to see the response.
GET/api/v1/rider/trips/:id/driver-details
Bearer token

Read assigned driver, vehicle and latest location

Endpoint guide What to send, parse and expect

Why it exists

Safely exposes the assigned driver, vehicle and latest trip-scoped location to the trip’s rider.

Before you call

Call only after assignment. The rider must own the trip.

Request fields

Replace :id with the trip UUID. No JSON body.

What to parse

Render name, approved profile image, aggregate rating, vehicle details and last location timestamp.

Expected result

200 returns details; 409 means no driver is assigned yet.

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/rider/trips/:id/driver-details', {
  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/rider/trips/:id/driver-details',
    headers={'Idempotency-Key': str(uuid.uuid4())},
    json=payload)
result = response.json()

PHP

$payload = <<<'JSON'
{}
JSON;
$ch = curl_init($baseUrl . '/api/v1/rider/trips/:id/driver-details');
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/rider/trips/:id/driver-details' \
+  -H 'Authorization: Bearer <access-token>' \
+  -H 'Content-Type: application/json' \
+  -H 'Idempotency-Key: <uuid>' \
+  --data '{}'
Request
Response
Run the request to see the response.
GET/api/v1/rider/places
Bearer token

List saved Home, Work and favourite places

Endpoint guide What to send, parse and expect

Why it exists

Stores a Home, Work or favourite address for quicker future trip entry.

Before you call

Requires an authenticated rider and a geocoded, rider-confirmed address.

Request fields

kind, label, address, latitude and longitude describe the saved place. Use the API result rather than a local-only copy.

What to parse

Read the saved-place id and updated place data for the dashboard.

Expected result

201 creates the saved place.

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/rider/places', {
  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/rider/places',
    headers={'Idempotency-Key': str(uuid.uuid4())},
    json=payload)
result = response.json()

PHP

$payload = <<<'JSON'
{}
JSON;
$ch = curl_init($baseUrl . '/api/v1/rider/places');
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/rider/places' \
+  -H 'Authorization: Bearer <access-token>' \
+  -H 'Content-Type: application/json' \
+  -H 'Idempotency-Key: <uuid>' \
+  --data '{}'
Request
Response
Run the request to see the response.
DELETE/api/v1/rider/places/:id
Bearer token

Remove a saved place

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/rider/places/:id', {
  method: 'DELETE',
  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.delete(BASE_URL + '/api/v1/rider/places/:id',
    headers={'Idempotency-Key': str(uuid.uuid4())},
    json=payload)
result = response.json()

PHP

$payload = <<<'JSON'
{}
JSON;
$ch = curl_init($baseUrl . '/api/v1/rider/places/:id');
curl_setopt_array($ch, [
  CURLOPT_CUSTOMREQUEST => 'DELETE',
  CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Idempotency-Key: <uuid>'],
  CURLOPT_POSTFIELDS => $payload,
  CURLOPT_RETURNTRANSFER => true,
]);

cURL

curl -X DELETE '<base-url>/api/v1/rider/places/:id' \
+  -H 'Authorization: Bearer <access-token>' \
+  -H 'Content-Type: application/json' \
+  -H 'Idempotency-Key: <uuid>' \
+  --data '{}'
Request
Response
Run the request to see the response.
GET/api/v1/rider/support/tickets
Bearer token

List rider-owned support tickets

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/rider/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/rider/support/tickets',
    headers={'Idempotency-Key': str(uuid.uuid4())},
    json=payload)
result = response.json()

PHP

$payload = <<<'JSON'
{}
JSON;
$ch = curl_init($baseUrl . '/api/v1/rider/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/rider/support/tickets' \
+  -H 'Authorization: Bearer <access-token>' \
+  -H 'Content-Type: application/json' \
+  -H 'Idempotency-Key: <uuid>' \
+  --data '{}'
Request
Response
Run the request to see the response.
POST/api/v1/rider/support/tickets
Bearer token

Open a support or lost-item 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/rider/support/tickets', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    Authorization: 'Bearer <access-token>',
    'Idempotency-Key': crypto.randomUUID()
  },
  body: JSON.stringify({"category":"LOST_ITEM","subject":"Phone left in vehicle","details":"Black phone on the rear seat","priority":"HIGH"})
});
const result = await response.json();

Python

payload = json.loads(r'''{"category":"LOST_ITEM","subject":"Phone left in vehicle","details":"Black phone on the rear seat","priority":"HIGH"}''')
response = requests.post(BASE_URL + '/api/v1/rider/support/tickets',
    headers={'Idempotency-Key': str(uuid.uuid4())},
    json=payload)
result = response.json()

PHP

$payload = <<<'JSON'
{"category":"LOST_ITEM","subject":"Phone left in vehicle","details":"Black phone on the rear seat","priority":"HIGH"}
JSON;
$ch = curl_init($baseUrl . '/api/v1/rider/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/rider/support/tickets' \
+  -H 'Authorization: Bearer <access-token>' \
+  -H 'Content-Type: application/json' \
+  -H 'Idempotency-Key: <uuid>' \
+  --data '{"category":"LOST_ITEM","subject":"Phone left in vehicle","details":"Black phone on the rear seat","priority":"HIGH"}'
Request
Response
Run the request to see the response.
GET/api/v1/rider/trips/:id/messages
Bearer token

Read authorised rider-driver trip chat

Endpoint guide What to send, parse and expect

Why it exists

Provides an authorised, trip-scoped conversation between the rider and assigned driver.

Before you call

Call only while an assigned trip is active.

Request fields

GET has no body. POST requires body (1–2,000 characters) and an idempotency key. Replace :id with the active trip UUID.

What to parse

Render messages in created-time order. Subscribe to message:received for live delivery and refetch this endpoint after reconnecting.

Expected result

GET 200 lists the rider messages; POST 201 creates one. 409 means chat is unavailable.

Important

The backend checks rider ownership, driver assignment and active trip status; the rider cannot supply a recipient id.

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/rider/trips/:id/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/rider/trips/:id/messages',
    headers={'Idempotency-Key': str(uuid.uuid4())},
    json=payload)
result = response.json()

PHP

$payload = <<<'JSON'
{}
JSON;
$ch = curl_init($baseUrl . '/api/v1/rider/trips/:id/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/rider/trips/:id/messages' \
+  -H 'Authorization: Bearer <access-token>' \
+  -H 'Content-Type: application/json' \
+  -H 'Idempotency-Key: <uuid>' \
+  --data '{}'
Request
Response
Run the request to see the response.
POST/api/v1/rider/trips/:id/messages
Bearer token

Send an authorised message to the assigned driver

Endpoint guide What to send, parse and expect

Why it exists

Provides an authorised, trip-scoped conversation between the rider and assigned driver.

Before you call

Call only while an assigned trip is active.

Request fields

GET has no body. POST requires body (1–2,000 characters) and an idempotency key. Replace :id with the active trip UUID.

What to parse

Render messages in created-time order. Subscribe to message:received for live delivery and refetch this endpoint after reconnecting.

Expected result

GET 200 lists the rider messages; POST 201 creates one. 409 means chat is unavailable.

Important

The backend checks rider ownership, driver assignment and active trip status; the rider cannot supply a recipient id.

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/rider/trips/:id/messages', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    Authorization: 'Bearer <access-token>',
    'Idempotency-Key': crypto.randomUUID()
  },
  body: JSON.stringify({"body":"I will be outside in two minutes."})
});
const result = await response.json();

Python

payload = json.loads(r'''{"body":"I will be outside in two minutes."}''')
response = requests.post(BASE_URL + '/api/v1/rider/trips/:id/messages',
    headers={'Idempotency-Key': str(uuid.uuid4())},
    json=payload)
result = response.json()

PHP

$payload = <<<'JSON'
{"body":"I will be outside in two minutes."}
JSON;
$ch = curl_init($baseUrl . '/api/v1/rider/trips/: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/rider/trips/:id/messages' \
+  -H 'Authorization: Bearer <access-token>' \
+  -H 'Content-Type: application/json' \
+  -H 'Idempotency-Key: <uuid>' \
+  --data '{"body":"I will be outside in two minutes."}'
Request
Response
Run the request to see the response.
GET/api/v1/rider/trips/:id/pickup-verification
Bearer token

Read the private pickup PIN or QR payload

Endpoint guide What to send, parse and expect

Why it exists

Shows the rider-only four-digit pickup PIN, or a signed QR payload when that fleet has enabled QR pickup confirmation.

Before you call

Use only after a driver is assigned. This capability is fleet-admin controlled; required:false means the normal trip-state flow remains active.

Request fields

Replace :id with the current rider-owned trip UUID. There is no request body.

What to parse

When required is true, render pin only on the private rider screen. For QR mode, render qrPayload as a QR code; never log, share or persist it.

Expected result

200 returns required, mode, pin and optional qrPayload. 409 means there is no assigned driver or the trip is not in a pickup state.

Important

The PIN is derived server-side and its bcrypt verifier is stored instead of plaintext. Drivers cannot retrieve this endpoint.

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/rider/trips/:id/pickup-verification', {
  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/rider/trips/:id/pickup-verification',
    headers={'Idempotency-Key': str(uuid.uuid4())},
    json=payload)
result = response.json()

PHP

$payload = <<<'JSON'
{}
JSON;
$ch = curl_init($baseUrl . '/api/v1/rider/trips/:id/pickup-verification');
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/rider/trips/:id/pickup-verification' \
+  -H 'Authorization: Bearer <access-token>' \
+  -H 'Content-Type: application/json' \
+  -H 'Idempotency-Key: <uuid>' \
+  --data '{}'
Request
Response
Run the request to see the response.
Errors and safetyResponses use JSON with a stable error code. Mutating requests receive an automatic idempotency key in the test console. Never paste production credentials here.