Files
doormile_milderapp/API_SPEC.md
2026-08-11 13:16:33 +05:30

18 KiB
Raw Permalink Blame History

Miler (Rider App) — Backend API Specification

Audience: Doormile backend team Purpose: This is the contract the Miler rider app needs the backend to implement so we can connect everything and go live. It documents (1) what the app already sends and expects today, and (2) the changes required to ship the mixed pickup + delivery route feature.

How to use this doc: Design/confirm each endpoint below, then send back the finalized doc (exact URLs, request/response JSON, and any field renames). We then wire the app to your final contract and go live.

Status legend for each endpoint: [LIVE] already called by the current app — keep the contract stable. [CHANGE] needs a change/addition before go-live. [NEW] not built yet.


1. Global conventions

1.1 Base URLs / environments

The app switches between dev and live by an environment flag. Please expose the same path on both:

DEV  base:  https://jupiter.doormile.app/dev/api
LIVE base:  https://jupiter.doormile.app/live/api

⚠️ Must fix before go-live: Today a few write endpoints (update pickup, create rider log, break logs) point at a second host https://queue.workolik.com/live/api/..., and the app currently has to bypass TLS cert validation and hard-code the server IP (66.116.225.226) because carrier DNS returns broken CDN nodes for that host and the certificate doesn't validate. Please serve everything from one host (jupiter.doormile.app) with a valid TLS certificate and correct DNS so we can remove the SSL-bypass hack. This is a security and reliability blocker.

1.2 Auth

  • The app does not currently send a bearer token — requests are keyed by userid. Please tell us the intended auth model. Recommended: return a JWT/session token from login and require Authorization: Bearer <token> on every other call. If you keep userid-only, confirm that explicitly.

1.3 Request/response format

  • Content type: application/json (both directions).
  • Standard response envelope (already used by read endpoints — please use it everywhere):
{
  "code": 200,
  "status": true,
  "message": "Success",
  "details": [ ... ]        // object OR array — the actual payload
}
  • The app reads the payload from details first, then falls back to data, then the root. Please standardize on details.
  • On error return status: false, a non-2xx HTTP code, and a human-readable message.

1.4 Formats

  • Dates (query params): YYYY-MM-DD (e.g. 2026-07-18).
  • Timestamps (bodies): full date-time string, currently YYYY-MM-DD HH:mm:ss. Confirm timezone — please use IST consistently and state it.
  • Lat/Long: strings, decimal degrees (e.g. "12.9716"). Do not truncate precision.
  • Money: number (₹). Confirm 2-decimal.
  • Booleans / flags: confirm whether you use true/false or 1/0 — the app currently tolerates both for status but please pick one.

1.5 Cache-busting

Read endpoints receive a t=<epoch-millis> query param — ignore it server-side; it exists to defeat caching.


2. Authentication

2.1 Rider Login [LIVE]

POST /v2/users/rider/login

Request:

{
  "contactno": "9876543210",
  "devicetype": "android",        // "android" | "ios"
  "configid": 123,
  "deviceid": "<device-uuid>",
  "userfcmtoken": "<fcm-token>",
  "pin": 1234                      // optional; sent on PIN login
}

Response details (object) — every field below is consumed by the app, so keep them:

{
  "userid": 1001,
  "riderid": 55,
  "partnerid": 12,
  "configid": 123,
  "shiftid": 7,
  "logid": 0,
  "logseconds": 0,
  "tenantid": 3,
  "locationid": 9,
  "applocationid": 9,
  "roleid": 2,
  "authmode": 1,
  "authname": "…",
  "firstname": "Suriya",
  "lastname": "K",
  "username": "suriya",
  "email": "…",
  "onduty": 0,                     // 0 = off duty, 1 = on duty
  "starttime": "09:00",            // shift window (display)
  "endtime": "18:00",
  "pickupradius": 100,             // meters — geofence radius for arrived/pickup
  "fuelcharge": 5.0,               // ₹ per km (rider payout)
  "firstmilecharge": 0.0,          // per-km first-mile charge (alias: firstmilecharges)
  "userfcmtoken": "<echoed>"
}

Notes:

  • authmode decides the flow (e.g. whether a PIN step is required). Please document the possible values.
  • If a rider needs to set a PIN on first login, tell us how that state is signaled.

2.2 Update PIN [LIVE]

PUT /v2/users/update

{ "userid": 1001, "pin": 1234 }

Response: standard envelope, status: true on success.


3. Rider duty log (On/Off Duty, breaks)

The rider goes On Duty → works stops → Off Duty. These calls power the duty timer and location tracking.

3.1 Create Rider Log (go On Duty) [LIVE]

POST /v2/partners/createriderlog

Request:

{
  "logid": 0,                      // 0 → server assigns new logid; returned in response
  "userid": 1001,
  "partnerid": 12,
  "shiftid": 7,
  "logdate": "2026-07-18T09:00:00",
  "login": "2026-07-18 09:00:00",  // on-duty timestamp
  "onduty": 1,
  "status": "online",
  "latitude": "12.9716",
  "longitude": "77.5946",
  "raw_latitude": "12.9716",
  "raw_longitude": "77.5946",
  "velocity_lat": "0",
  "velocity_lng": "0",
  "speed": "0",
  "heading": "0",
  "contactno": "9876543210",
  "tenantid": 3,
  "locationid": 9,
  "applocationid": 9,
  "userfcmtoken": "<fcm-token>",
  "orderid": ""                    // optional; current stop context if any
}

Response must return the new logid (the app stores it and uses it for updates). Return it in details.

3.2 Update Rider Log (heartbeat / go Off Duty) [LIVE]

PUT /v1/partners/updateriderlog

Sent periodically as a location heartbeat and once when going Off Duty:

{
  "logid": 4567,
  "userid": 1001,
  "logdate": "2026-07-18T13:00:00",
  "latitude": "12.9722",
  "longitude": "77.5950",
  "speed": "0",
  "heading": "0",
  "status": "online",             // "offline" when going off duty
  "orderid": ""
}

Confirm the exact field(s) used to mark Off Duty (e.g. status: "offline" and/or logout timestamp + onduty: 0). Please state it explicitly.

3.3 Get Rider Log [LIVE]

GET /v1/partners/getriderlog?userid=1001 → current log record (used to restore duty state on app restart). Return logid, onduty, login time, accumulated seconds, etc.

3.4 Get Rider Count [LIVE]

GET /v1/partners/getridercount?userid=1001 → counts for the dashboard (e.g. completed stops today). Please document exact fields.

3.5 Break logs [LIVE]

  • POST /v2/partners/createbreaklog — start break.
  • PUT /v2/partners/updatebreaklog — end break.

Please document the exact request bodies (rider id, logid, start/end timestamps, break type).


4. Route & Stops (the core flow)

Domain recap for the backend: For a booked time slot, the hub/admin assigns a rider an ordered route of stops. The rider starts at a hub, works stops in fixed sequence (cannot reorder), can skip and resume a stop, and after the last stop returns to the same hub. Each stop is either a PICKUP or a DELIVERY (see §4.5 — this is the key new requirement).

4.1 Get Pickup Queue (assigned/pending stops) [LIVE]

GET /v2/pickups/getpickupqueues?userid=1001&fromdate=2026-07-18&todate=2026-07-18&orderstatus=<optional>&t=<epoch>

Returns details = array of stop objects. Fields the app reads today (please keep these names, lowercase):

Field Type Meaning
orderid string/int Order identifier shown to rider
pickupid int Stop id — primary key for all status updates
orderheaderid int Order header id (sent back on updates)
pickuplocationid int Location id of the stop
orderstatus string Current status (see §4.6 lifecycle)
step int Sequence position in the route (1..N) — defines fixed order
pickupcustomer string Customer / store name
pickupcontactno string Customer phone (Call button)
pickupaddress string Stop address
pickuplat / pickuplong string Stop coordinates (geofence + navigation)
dropaddress string Drop address (delivery stops)
droplat / droplon string Drop coordinates (delivery stops)
collectionamt number Amount to collect at this stop (0 = none)
pickupamt number Pickup charge
eta / expected_pickup_time string ETA / expected time (display)
tenantid / tenantname int/string Tenant
starttime string Slot / assignment start

⚠️ Casing: the app has seen both pickuplat/PickupLat and orderid/OrderId variants in responses. Please return one consistent casing (lowercase preferred) across all endpoints and never mix within a payload.

4.2 Get Current Pickups [LIVE]

GET /v1/pickups/getpickups?userid=1001&fromdate=&todate=&t= — the rider's active/in-progress stops. Same object shape as §4.1.

4.3 Get Pickups V3 (date-bounded / picked history) [LIVE]

GET /v3/pickups/getpickups?userid=1001&fromdate=&todate=&t= — used for completed/"picked" history. Same object shape.

Please clarify the intended difference between v1/v2/v3 of getpickups so we can consolidate. Ideally one endpoint filtered by orderstatus and date range.

4.4 Update Stop status [LIVE — needs delivery extension, see §4.5]

PUT /v1/pickups/updatepickup

This one endpoint is called at every state transition; orderstatus selects the transition. Common fields on all transitions:

{
  "pickupid": 8890,
  "orderheaderid": 4501,
  "orderstatus": "<state>",
  "riderslat": "12.9716",         // rider GPS at the moment
  "riderslon": "77.5946",
  "raw_latitude": "12.9716", "raw_longitude": "77.5946",
  "velocity_lat": "0", "velocity_lng": "0", "speed": "0", "heading": "0",
  "notes": ""
}

Per-transition additional fields:

accepted — rider starts the assigned route/stop.

active — rider en route to the stop.

arrived — rider reached the stop (passes geofence check):

{ "orderstatus": "arrived", "arrivaltime": "2026-07-18 10:05:00", "pickuplat": "", "pickuplong": "", "actualkms": "", "pickupamt": 0.0 }

Picked up (pickup complete) — the big one:

{
  "orderstatus": "Picked up",
  "pickupedtime": "2026-07-18 10:07:00",
  "pickuptime":   "2026-07-18 10:07:00",
  "pickuplocationid": 9,
  "pickuplat": "12.9716", "pickuplong": "77.5946",
  "riderkms": "0.4200",           // distance rider travelled to this stop
  "ridercharges": 2.10,           // payout for this leg
  "ridertime": 12,                // minutes
  "pickupamt": 0.0,
  "collectionamt": 100.0,         // amount due
  "collectedamt": 100.0,          // amount actually collected
  "collectionstatus": "collected",
  "smspickup": 0,
  "wasskipped": false,            // true if this stop had been skipped earlier
  "bonuspts": 5,
  "dropimage": "<base64-or-url>"  // photo proof of pickup
}

skipped — rider skips this stop, will resume later (first-class; sequence preserved).

cancelled — pickup could not be completed (reason in notes).

rejected — rider rejects the assigned stop.

picked — internal "picked" marker (via updatepickup v1). Please clarify vs Picked up.

⚠️ Please normalize orderstatus values. Today they are inconsistent ("Picked up" with a space & capital, vs "arrived", "active", "skipped" lowercase). Give us one canonical set of machine values (e.g. all lowercase snake: assigned, active, arrived, picked_up, delivered, skipped, cancelled, rejected) and we'll map the UI labels ourselves.

Response for all updates: standard envelope with status: true.

4.5 ⭐ REQUIRED CHANGE — Stop type (Pickup vs Delivery) [CHANGE]

This is the single most important change for go-live. Each stop on a route can be a pickup or a delivery, and the app UI must branch on it. Today the API returns no such field, so the app treats every stop as a pickup. Please add:

  1. On every stop object (§4.1–4.3) add a stop type field:

    "type": "pickup"      // "pickup" | "delivery"
    

    (Name it type or stoptype — the app already looks for type/stoptype/stopType; pick one and tell us.)

  2. For delivery stops, the stop object must carry delivery details:

    Field Type Meaning
    dropaddress string Where to deliver
    droplat / droplon string Delivery coordinates (geofence + nav)
    otp string/int Delivery OTP the customer gives (proof of delivery)
    collectionamt number COD to collect on delivery (0 = prepaid)
    customer name/phone string Recipient contact (reuse pickupcustomer/pickupcontactno or give delivery-specific fields — tell us which)
  3. Delivery completion goes through the same PUT /v1/pickups/updatepickup with:

    {
      "pickupid": 8891,
      "orderstatus": "delivered",     // canonical value TBD (see §4.4 note)
      "deliveredtime": "2026-07-18 10:20:00",
      "otp": "4821",                  // OTP the rider entered — verify server-side
      "dropimage": "<base64-or-url>", // photo proof of delivery
      "collectedamt": 0.0, "collectionstatus": "prepaid",
      "riderslat": "…", "riderslon": "…", "riderkms": "…", "bonuspts": 5
    }
    

    Please confirm: (a) whether OTP is verified server-side (recommended) or just recorded, (b) the canonical orderstatus for a completed delivery, (c) delivery-specific proof fields (signature? photo? OTP-only?).

4.6 Stop status lifecycle (state machine)

assigned ──► active ──► arrived ──► ┌─ (pickup)   picked_up  ─┐
   │            │           │        └─ (delivery) delivered  ─┤──► [next stop]
   │            │           └────────────► skipped ──► (resume later) ─► active
   └────────────┴──────────────────────► cancelled / rejected

Rules the backend must enforce/allow:

  • Rider cannot reorder; step is authoritative.
  • Rider can skip any stop and resume it later — skipped is not terminal.
  • After the last stop the rider returns to the origin hub. Please tell us whether hub-return is its own record/status or implicit.

4.7 Create Pickup Log [LIVE]

POST /v2/pickups/createpickuplog — audit/event log entries for a stop. Body is wrapped in an array: [ { ...event } ]. Please document the event schema (event type, timestamp, pickupid, lat/long).


5. Earnings / Summary

5.1 Partner summary [LIVE]

GET /v2/partners/... (base https://jupiter.doormile.app/live/api/v2/partners) Powers the Earnings screen (daily/weekly/monthly totals, stop counts, payout). Please document the exact path + params (userid, period, date range) and the response fields (totals, per-day breakdown).

5.2 Rider weekly KMs [LIVE]

GET /v1/partners/... — weekly distance for payout. Document exact path + response.


6. Supporting endpoints

These are used by the app; please document each (request + response):

  • Notifications — list rider notifications (used on the notifications tab). Need: list + mark-read.
  • Rewards / bonus points — the app shows bonuspts/bonusPoints; document how points are earned and fetched.
  • Support tickets — create ticket, list tickets (models exist: subject, description, status, timestamps).
  • FCM push — confirm the payload schema for push notifications (new stop assigned, route updated, etc.) so we can handle taps/deep-links.
  • App version / force-update — the app tracks CurrentVersion; if you gate minimum version, document the endpoint.

7. Field glossary (canonical names)

Field Meaning
userid Rider's user id (primary key the app sends everywhere)
riderid / partnerid Rider/partner identifiers
shiftid / logid Shift and current duty-log ids
tenantid / locationid / applocationid Org / hub / app-location scoping
pickupid Stop id — the PK for a single stop, used on all status updates
orderid / orderheaderid Order + order-header identifiers
step Stop's fixed position in the route (1..N)
type / stoptype NEW: pickup | delivery
orderstatus Stop state (see §4.6)
collectionamt / collectedamt / collectionstatus COD due / collected / status
pickuplat,pickuplong / droplat,droplon Stop / drop coordinates
riderslat,riderslon Rider GPS at time of action
riderkms / ridercharges / ridertime Distance / payout / minutes for a leg
otp Delivery OTP (proof of delivery)
dropimage Photo proof (pickup or delivery)
bonuspts Bonus points for completing a stop
pickupradius Geofence radius (m) for arrived/complete

8. Open questions for the backend team (please answer in your returned doc)

  1. Auth model — token-based or userid-only? (§1.2)
  2. Single host + valid TLS + working DNS — can we drop the queue.workolik.com host and the SSL/IP hack? (§1.1)
  3. Canonical orderstatus values — give us the final machine strings. (§4.4)
  4. Stop type field — final field name (type vs stoptype) and the delivery fields. (§4.5)
  5. Delivery proof — OTP verified server-side? photo/signature required? canonical delivered status? (§4.5)
  6. getpickups v1/v2/v3 — can we consolidate to one endpoint? (§4.3)
  7. Casing — confirm all-lowercase field names across every endpoint. (§4.1)
  8. Timezone — confirm IST for all timestamps. (§1.4)
  9. Hub return — is returning to hub its own status/record? (§4.6)
  10. Summary, rewards, notifications, support, push — full request/response schemas. (§5–6)

Generated from the current Miler app's live API integration. Every field marked [LIVE] is already sent/consumed by the app in production code — please preserve those names or tell us the new ones so we can migrate.