← Developer home

DOEH Rider API (0.1.0)

Download OpenAPI specification:

First-party fulfillment API. This is the rider/delivery operational API used by the DOEH rider app. It is not part of the public integration SDK (sk_/edge) — it uses Sanctum bearer-token auth against the POS shop domain. Money is integer minor units.

First-party rider fulfillment API consumed by the DOEH rider app (doeh-rider-app). This is the rider stack, distinct from the @beyondplusmm/doehpos-sdk integration stack:

  • Audience: delivery riders (a rider is a users row with role='rider'), not third-party integrators.
  • Auth: the rider logs in with email + password and receives a personal Laravel Sanctum bearer token. There is no sk_ API key and no edge gateway in this path — the app calls pos-shop directly.
  • Scope (INV-RIDER-2): a token represents exactly one shop context; shop_id is derived from the authenticated user, never sent by the client, and there is no cross-shop data access. A rider registered in multiple shops uses a separate login/token per shop.

Money is integer minor units (*_minor) on this public contract, matching the Orders convention. The internal Laravel aggregate stores float major units; a backend float⇄minor adapter is the authority that converts at the boundary (parallel to the Orders MoneyCodec). This document is therefore a governed projection of the already-authoritative API implemented in RiderDeliveryController / RiderNotificationController: it documents the public-facing surface, not the raw internal field shapes. Exception — the rider wallet is not yet on this minor-units ABI. Its fields (balance, total_collected, total_settled) are emitted as raw major-unit floats. The wallet aggregates COD across deliveries that may span branches and currencies, so it has no single currency to attribute and no canonical minor-units projection is defined for it yet (deferred — INV-RIDER-1b).

auth

Rider account login, registration, email verification, password.

Rider login (multi-shop)

Authenticates by email + password and returns a Sanctum token plus the list of shops where the rider is registered. The same email may exist in multiple shops; the password is tried against all of them.

Request Body schema: application/json
required
email
required
string <email>
password
required
string

Responses

Request samples

Content type
application/json
{}

Response samples

Content type
application/json
{
  • "token": "12|abcdefghijklmnopqrstuvwxyz0123456789",
  • "rider": {
    },
  • "shops": [
    ]
}

Rider self-registration

Creates a rider user (no shop yet) and emails a 6-digit verification OTP.

Request Body schema: application/json
required
name
required
string <= 100 characters
email
required
string <email> <= 255 characters
phone
required
string <= 20 characters
password
required
string >= 6 characters

Responses

Request samples

Content type
application/json
{}

Response samples

Content type
application/json
{
  • "token": "string",
  • "rider": {
    },
  • "verification": {
    }
}

Request a password-reset OTP

Always returns success to prevent email enumeration.

Request Body schema: application/json
required
email
required
string <email>

Responses

Request samples

Content type
application/json
{}

Response samples

Content type
application/json
{
  • "message": "string",
  • "expires_in": 0
}

Reset password with OTP

Request Body schema: application/json
required
email
required
string <email>
otp
required
string = 6 characters
password
required
string >= 6 characters
password_confirmation
required
string

Responses

Request samples

Content type
application/json
{
  • "email": "[email protected]",
  • "otp": "string",
  • "password": "string",
  • "password_confirmation": "string"
}

Response samples

Content type
application/json
{
  • "message": "string"
}

Verify email with OTP

Authorizations:
riderToken
Request Body schema: application/json
required
otp
required
string = 6 characters

Responses

Request samples

Content type
application/json
{
  • "otp": "string"
}

Response samples

Content type
application/json
{
  • "message": "string",
  • "email_verified_at": "2019-08-24T14:15:22Z"
}

Resend the email verification OTP

Authorizations:
riderToken

Responses

Response samples

Content type
application/json
{
  • "message": "string",
  • "expires_in": 0
}

Change password (authenticated)

Authorizations:
riderToken
Request Body schema: application/json
required
current_password
required
string
password
required
string >= 6 characters
password_confirmation
required
string

Responses

Request samples

Content type
application/json
{
  • "current_password": "string",
  • "password": "string",
  • "password_confirmation": "string"
}

Response samples

Content type
application/json
{
  • "message": "string"
}

deliveries

Assigned deliveries, lifecycle transitions, COD, QR scan/claim.

List the rider's deliveries

The authenticated rider's deliveries within the token's shop (INV-RIDER-2 — a token represents exactly one shop context). Pass history=1 for terminal deliveries (Delivered/Cancelled/Failed) within the last days (default 7, max 90).

Authorizations:
riderToken
query Parameters
history
boolean

Return terminal deliveries instead of active.

days
integer [ 1 .. 90 ]
Default: 7

History window in days.

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Look up a delivery by its code (QR scan)

Looks up a delivery by code within the token's shop (INV-RIDER-2); a code from another shop returns 404. Use can_claim / is_assigned_to_me to decide the next action.

Authorizations:
riderToken
path Parameters
code
required
string

The delivery_code from the QR.

Responses

Response samples

Content type
application/json
{
  • "id": 0,
  • "delivery_code": "string",
  • "pickup_address": "string",
  • "drop_address": "string",
  • "delivery_fee_minor": 0,
  • "cod_amount_minor": 0,
  • "cod_collected": true,
  • "is_cod": true,
  • "status": 1,
  • "status_label": "string",
  • "customer_phone": "string",
  • "customer_name": "string",
  • "order_number": "string",
  • "shop_id": 0,
  • "shop_name": "string",
  • "rider_id": 0,
  • "is_assigned_to_me": true,
  • "can_claim": true,
  • "created_at": "2019-08-24T14:15:22Z"
}

Delivery detail

Full detail for a delivery assigned to the authenticated rider, including order items and customer contact.

Authorizations:
riderToken
path Parameters
id
required
integer

DeliveryOrder id.

Responses

Response samples

Content type
application/json
{
  • "id": 1001,
  • "delivery_code": "DL-A3B7-2026",
  • "pickup_address": "Sandbox Demo Shop, Yangon",
  • "drop_address": "No. 5, Demo Street, Yangon",
  • "delivery_lat": 16.8409,
  • "delivery_lng": 96.1735,
  • "delivery_fee_minor": 2500,
  • "cod_amount_minor": 18000,
  • "cod_collected": false,
  • "is_cod": true,
  • "status": 5,
  • "status_label": "Out for Delivery",
  • "customer_phone": 998765432,
  • "customer_name": "Demo Customer",
  • "order_number": "ORD-2026-0001",
  • "items": [
    ],
  • "accepted_at": "2026-06-21T08:32:00Z",
  • "picked_up_at": "2026-06-21T08:45:00Z",
  • "delivered_at": null,
  • "created_at": "2026-06-21T08:30:00Z"
}

Advance the delivery status

Applies a rider-allowed transition. Transitions are linear: Pending→Accepted→Preparing→ReadyPickup→OutForDelivery→Delivered (or →Failed from OutForDelivery). Riders cannot cancel — only the shop can. Marking Delivered auto-collects COD into the rider wallet.

Authorizations:
riderToken
path Parameters
id
required
integer

DeliveryOrder id.

Request Body schema: application/json
required
status
required
integer (DeliveryStatus)
Enum: 1 2 3 4 5 6 7 8

1=Pending, 2=Accepted, 3=Preparing, 4=ReadyPickup, 5=OutForDelivery, 6=Delivered, 7=Cancelled, 8=Failed.

note
string or null <= 300 characters

Responses

Request samples

Content type
application/json
Example
{
  • "status": 2
}

Response samples

Content type
application/json
Example
{
  • "id": 1001,
  • "status": 2,
  • "status_label": "Accepted",
  • "cod_collected": false
}

Claim an unassigned delivery

Succeeds only when the delivery has no rider and is not terminal.

Authorizations:
riderToken
path Parameters
id
required
integer

DeliveryOrder id.

Responses

Response samples

Content type
application/json
{
  • "id": 0,
  • "rider_id": 0,
  • "status": 1,
  • "status_label": "string",
  • "message": "string"
}

Quick deliver (claim-if-needed + mark Delivered)

One-shot used at the delivery point after a QR scan. Claims the delivery if unassigned, marks it Delivered, and auto-collects COD.

Authorizations:
riderToken
path Parameters
id
required
integer

DeliveryOrder id.

Responses

Response samples

Content type
application/json
{
  • "id": 0,
  • "status": 1,
  • "status_label": "string",
  • "cod_collected": true,
  • "message": "string"
}

Mark COD as collected

Explicit COD collection for cases where auto-collect on delivery was skipped. Only valid for a COD delivery already marked Delivered and not yet collected.

Authorizations:
riderToken
path Parameters
id
required
integer

DeliveryOrder id.

Responses

Response samples

Content type
application/json
{
  • "cod_collected": true,
  • "amount_minor": 18000
}

profile

Rider profile and wallet.

Rider profile

Authorizations:
riderToken

Responses

Response samples

Content type
application/json
{
  • "id": 0,
  • "name": "string",
  • "phone": "string",
  • "vehicle_type": "string",
  • "is_active": true,
  • "last_seen_at": "2019-08-24T14:15:22Z"
}

Rider wallet

COD balance owed to the shop, plus lifetime collected / settled totals. Unlike the rest of this contract these are raw major-unit floats, NOT minor units: the wallet aggregates COD across branches/currencies and has no single currency to project into a canonical minor-units ABI yet (deferred — INV-RIDER-1b).

Authorizations:
riderToken

Responses

Response samples

Content type
application/json
{
  • "balance": 3250,
  • "total_collected": 5400,
  • "total_settled": 2150
}

location

Live GPS position updates.

Update live GPS position

Server throttles writes to ~20s resolution; a throttled call still returns ok.

Authorizations:
riderToken
Request Body schema: application/json
required
lat
required
number [ -90 .. 90 ]
lng
required
number [ -180 .. 180 ]

Responses

Request samples

Content type
application/json
{
  • "lat": -90,
  • "lng": -180
}

Response samples

Content type
application/json
{
  • "ok": true,
  • "throttled": true
}

notifications

In-app notifications and FCM device registration.

List notifications (paginated)

Authorizations:
riderToken

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "meta": {
    }
}

Unread notification count

Authorizations:
riderToken

Responses

Response samples

Content type
application/json
{
  • "unread_count": 0
}

Mark a notification read

Authorizations:
riderToken
path Parameters
id
required
integer

Responses

Response samples

Content type
application/json
{
  • "success": true
}

Mark all notifications read

Authorizations:
riderToken

Responses

Response samples

Content type
application/json
{
  • "success": true
}

Dismiss a notification

Authorizations:
riderToken
path Parameters
id
required
integer

Responses

Response samples

Content type
application/json
{
  • "success": true
}

Register an FCM device token

Authorizations:
riderToken
Request Body schema: application/json
required
device_token
required
string
platform
required
string
Enum: "ios" "android" "web"
device_id
string or null
device_model
string or null
os_version
string or null
app_version
string or null

Responses

Request samples

Content type
application/json
{
  • "device_token": "string",
  • "platform": "ios",
  • "device_id": "string",
  • "device_model": "string",
  • "os_version": "string",
  • "app_version": "string"
}

Response samples

Content type
application/json
{
  • "success": true
}

Remove an FCM device token

Authorizations:
riderToken
Request Body schema: application/json
required
device_token
required
string

Responses

Request samples

Content type
application/json
{
  • "device_token": "string"
}

Response samples

Content type
application/json
{
  • "success": true
}