Files
Xpress-rider/API_ENDPOINTS.md
2026-08-12 10:50:45 +05:30

452 lines
14 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Nearle Rider — API Reference
Generated from a source sweep of `lib/`. Every endpoint the app talks to, with
request payloads for all write operations.
## Base hosts
| Host | Used for | Notes |
|---|---|---|
| `jupiter.nearle.app` | all **reads** | env segment from `ApiConstants.mainRoute` (`live`) / `mainDev` (`dev`) |
| `queue.workolik.com` | all **writes** (status updates + logs) | hardcoded `live`, DNS pinned to `66.116.225.226`, TLS cert validation bypassed (`lib/providers/deliverylog/deliverylog_provider.dart:20`) |
| `msg.lionsms.com` | OTP SMS | |
| `maps.googleapis.com` | route distance | |
| `sgp1.digitaloceanspaces.com` → `images.nearle.app` | proof / ticket images (Minio SDK, not REST) | |
| `66.116.225.226:1883` | MQTT telemetry | |
**No auth header on any call.** Every request sends only
`Content-Type: application/json` / `Accept: application/json`. Identity is
carried as a `userid` field in the query string or body.
Endpoint constants live in `lib/views/helpers/constants/apiconstants.dart`.
---
## 1. Auth
### POST `https://jupiter.nearle.app/live/api/v2/users/rider/login`
`lib/providers/auth/auth_provider.dart:19`
```json
{
"contactno": "9876543210",
"devicetype": "android",
"configid": 1,
"deviceid": "<device id>",
"userfcmtoken": "<fcm token>",
"pin": 1234
}
```
`pin` is only included when non-null.
Response `details` is persisted to SharedPreferences: `userid`, `shiftid`,
`logid`, `riderid`, `partnerid`, `configid`, `logseconds`, `locationid`,
`tenantid`, `applocationid`, `userfcmtoken`, `firstname`, `lastname`,
`username`, `onduty`, `fuelcharge`, `firstmilecharge`, `starttime`, `endtime`,
`deliveryradius` (default 100 m).
### PUT `https://jupiter.nearle.app/live/api/v2/users/update`
Set / change MPIN — `lib/providers/auth/auth_provider.dart:186`
```json
{ "userid": 1242, "pin": 1234 }
```
### GET `https://jupiter.nearle.app/live/api/v1/platform/getsmsprovider?templatetypeid=1`
Fetches `templateid` + SMS `content` template. Cached 1 hour.
`lib/controllers/auth.dart:367`
### GET `https://msg.lionsms.com/api/smsapi`
`lib/controllers/auth.dart:407`
| Param | Value |
|---|---|
| `key` | `e57f5c9679af26077be1a7eadabb1b2a` |
| `route` | `7` |
| `sender` | `NEARLE` |
| `number` | `+91<phone>` |
| `templateid` | from `getsmsprovider` |
| `sms` | URL-encoded body with OTP substituted for `{#var#}` |
The OTP is **generated on-device** and stored in `SharedPreferences('lastOtp')`.
---
## 2. Deliveries — reads (all GET)
| Endpoint | Query | Caller |
|---|---|---|
| `…/{env}/api/v2/deliveries/getdeliveryqueues` | `userid, fromdate, todate, t` (+ optional `orderstatus`) | `lib/providers/delivery/delivery_provider.dart:34` |
| `…/{env}/api/v1/deliveries/getdeliveries` | `userid, fromdate, todate, t` | `lib/background/backgroundservice.dart:68` |
| `…/{env}/api/v2/deliveries/getdeliveries` | `userid, fromdate, todate, t` | hardcoded in `homepage.dart:1074`, `cartpage.dart:79`, `deliveries.dart:563` |
| `…/{env}/api/v3/deliveries/getdeliveries` | `userid, fromdate, todate, t` | picked orders — `delivery_provider.dart:92` |
- `fromdate` / `todate` are always **today** in `YYYY-MM-DD`.
- `t` is a cache-buster (epoch ms).
- Response shape: `{ "code": 200, "status": true, "message": "Success", "details": [ … ] }`.
Readers fall back to `data` then the raw body.
---
## 3. Delivery status updates
### PUT `https://queue.workolik.com/live/api/v1/deliveries/updatedelivery`
One endpoint, eight payload shapes. All from `lib/controllers/deliveries_controller.dart`.
Most variants share this GPS block:
`riderslat`, `riderslon`, `raw_latitude`, `raw_longitude`, `velocity_lat`,
`velocity_lng`, `speed`, `heading`.
#### accepted — `:695`
```json
{
"deliveryid": 0,
"orderheaderid": 0,
"orderstatus": "accepted",
"acceptedtime": "YYYY-MM-DD HH:MM:SS",
"riderslat": "", "riderslon": "",
"raw_latitude": "", "raw_longitude": "",
"velocity_lat": "", "velocity_lng": "",
"speed": "", "heading": "",
"deliverylat": "", "deliverylong": "",
"actualkms": "",
"deliveryamt": 0.0,
"notes": ""
}
```
#### active (start navigation) — `:1317`
Same as accepted, plus:
```json
{
"orderstatus": "active",
"activetime": "YYYY-MM-DD HH:MM:SS",
"starttime": "YYYY-MM-DD HH:MM:SS",
"activelat": "", "activelon": ""
}
```
Aborts if rider coordinates resolve to `0`.
#### arrived — `:1429`
Same as accepted, with `"orderstatus": "arrived"` and
`"arrivaltime": "YYYY-MM-DD HH:MM:SS"`. Geofence-checked against the pickup
location before sending.
#### picked — `:280`
No `raw_*` / velocity block on this one.
```json
{
"deliveryid": 0,
"orderheaderid": 0,
"pickuplocationid": 0,
"orderstatus": "picked",
"pickuptime": "YYYY-MM-DD HH:MM:SS",
"riderslat": "", "riderslon": "",
"deliverylat": "", "deliverylong": "",
"actualkms": "0.00",
"deliveryamt": 0.0,
"deliverytype": "",
"address": "", "city": "", "state": "", "suburb": "", "postcode": "",
"notes": "",
"pickupimage": "",
"proofimage": ""
}
```
`actualkms` is computed rider→pickup when not supplied. Geofence-checked.
#### delivered — `:1229`
```json
{
"deliveryid": 0,
"orderheaderid": 0,
"deliverylocationid": 0,
"orderstatus": "delivered",
"deliveredtime": "YYYY-MM-DD HH:MM:SS",
"deliverytime": "YYYY-MM-DD HH:MM:SS",
"smsdelivery": 0,
"riderslat": "", "riderslon": "",
"raw_latitude": "", "raw_longitude": "",
"velocity_lat": "", "velocity_lng": "",
"speed": "", "heading": "",
"pickuplat": "", "pickuplong": "",
"deliverylat": "", "deliverylong": "",
"riderkms": "",
"ridercharges": 0,
"deliveryamt": 0,
"collectionamt": 0,
"collectedamt": 0,
"collectionstatus": "",
"ridertime": 0,
"notes": "",
"wasskipped": false,
"bonuspts": 0,
"dropimage": ""
}
```
Returns `false` without sending if rider **or** drop coordinates are `0` or
out of range (`|lat| > 90`, `|lng| > 180`).
#### skipped — `:1758`
```json
{
"deliveryid": 0,
"orderheaderid": 0,
"orderstatus": "skipped",
"skippedtime": "YYYY-MM-DD HH:MM:SS",
"riderslat": "", "riderslon": "",
"deliverylat": "", "deliverylong": "",
"actualkms": "",
"deliveryamt": 0.0,
"notes": "",
"riderkms": "0.00"
}
```
`riderkms` is added only when the computed distance is > 0 (Google Directions,
falling back to straight-line).
#### rejected — `:1477`
Status block only, no timestamp: `"orderstatus": "rejected"` plus the shared
GPS block, `deliverylat`/`deliverylong`, `actualkms`, `deliveryamt`, `notes`.
#### cancelled — `:1813`
```json
{
"deliveryid": 0,
"orderheaderid": 0,
"orderstatus": "cancelled",
"canceltime": "YYYY-MM-DD HH:MM:SS",
"riderslat": "", "riderslon": "",
"raw_latitude": "", "raw_longitude": "",
"velocity_lat": "", "velocity_lng": "",
"speed": "", "heading": "",
"deliverylat": "", "deliverylong": "",
"riderkms": "0.00",
"ridercharges": 0,
"deliveryamt": 0.0,
"notes": ""
}
```
---
## 4. Delivery log (background heartbeat)
### POST `https://queue.workolik.com/live/api/v2/deliveries/createdeliverylog`
**The body is wrapped in an array** — `json.encode([data])`
(`lib/providers/deliverylog/deliverylog_provider.dart:73`).
```json
[
{
"logid": 0,
"tenantid": 0,
"partnerid": 0,
"locationid": 0,
"orderheaderid": 0,
"deliveryid": 0,
"userid": 1242,
"orderid": "ORD123",
"orderstatus": "active",
"logdate": "YYYY-MM-DD HH:MM:SS",
"latitude": "", "longitude": "",
"raw_latitude": "", "raw_longitude": "",
"velocity_lat": "", "velocity_lng": "",
"speed": "", "heading": "",
"riderkms": 0.0,
"logstatus": 0
}
]
```
Base fields come from `_createPayload` (`backgroundservice.dart:236`); GPS,
`logdate`, `riderkms` and `logstatus` are merged in `_postDeliveryLog` (`:180`).
Posted roughly every 30 s per active delivery. 10 s timeout; failures are
queued in SharedPreferences and retried.
---
## 5. Rider log
### GET `…/{env}/api/v1/partners/getriderlog?userid=<id>`
Response `details` is cached as `riderlog_template` and reused as the base for
every subsequent create-log payload.
### GET `…/{env}/api/v1/partners/getridercount?userid=<id>`
### POST `https://queue.workolik.com/live/api/v2/partners/createriderlog`
Periodic on-duty ping — `lib/controllers/riderlog.dart:289`,
`lib/background/foreground_service.dart:289`
```json
{
"logid": 0,
"userid": 1242,
"partnerid": 0,
"shiftid": 0,
"logdate": "YYYY-MM-DD HH:MM:SS",
"login": "HH:MM:SS",
"latitude": "", "longitude": "",
"raw_latitude": "", "raw_longitude": "",
"velocity_lat": "", "velocity_lng": "",
"speed": "", "heading": "",
"onduty": 1,
"status": "active",
"contactno": "",
"username": "",
"firstname": "",
"lastname": "",
"tenantid": 0,
"locationid": 0,
"applocationid": 0,
"userfcmtoken": "",
"orderid": ""
}
```
- Built by spreading the cached `riderlog_template`, then overriding time, GPS
and identity fields.
- `status` is `"active"` when deliveries are live, otherwise `"idle"`.
- `firstname` / `lastname` keys are **removed** when empty; `username` is always
sent even if blank.
- Interval = `logseconds` from login, forced to **30 s** while deliveries are
active. 3 retries with 1 s backoff, then the offline queue (capped at 50).
### PUT `…/{env}/api/v1/partners/updateriderlog`
Duty toggle — `lib/controllers/riderlog.dart:520`, model at
`lib/Models/riders/riders_models.dart:275`
```json
{
"userid": 1242,
"logstatus": null,
"Logout": null,
"workhours": null,
"shorthours": null,
"latitude": "",
"longitude": "",
"onduty": 1
}
```
Note the capitalized `Logout` key (and `Login` in `RiderLogin.toJson`).
---
## 6. Breaks
### POST `https://queue.workolik.com/live/api/v2/partners/createbreaklog`
`lib/controllers/riderlog.dart:925`
```json
{
"breakid": 427,
"logid": 0,
"breakdate": "YYYY-MM-DD HH:MM:SS",
"userid": 1242,
"partnerid": 0,
"shiftid": 0,
"breakstart": "HH:MM:SS",
"breakend": "",
"breakhours": 0.0,
"latitude": "",
"longitude": ""
}
```
`breakid` is a **client-generated random 3-digit** value (100–999), replaced by
the server id when one comes back.
Also emitted by the auto-shift-end flow at `backgroundservice.dart:765`.
### PUT `https://queue.workolik.com/live/api/v2/partners/updatebreaklog`
`lib/controllers/riderlog.dart:196`
Same shape, with `breakend` filled and `breakhours` as fractional hours
(`duration.inSeconds / 3600`).
---
## 7. Stats & rewards (GET)
| Endpoint | Source |
|---|---|
| `…/live/api/v2/partners/getdeliverystats?userid=<id>` | `lib/providers/summary/summary.dart:10` |
| `…/live/api/v1/partners/getriderweeklykms?userid=<id>` | `lib/views/Dashboard/summary/summary.dart:318` |
| `…/live/api/v1/utils/getuserbonussummary/?userid=<id>` | `lib/controllers/rewards_controller.dart:16` |
---
## 8. Support tickets
### GET `…/live/api/v1/partners/getridersupport/?userid=<id>`
### POST `…/live/api/v1/partners/createridersupport/`
`lib/controllers/support_ticket.dart:186`
```json
{
"userid": 1242,
"category": "",
"priority": "",
"subject": "",
"issue": "",
"image": "https://images.nearle.app/support/ticket-1234-1242.jpg"
}
```
Images are uploaded directly to DigitalOcean Spaces with the Minio SDK
(bucket `nearle`, folder `support`, region `sgp1`) — not through the API. The
returned CDN URL is what goes in `image`.
---
## 9. External services
- **GET** `https://maps.googleapis.com/maps/api/directions/json?origin=<lat,lng>&destination=<lat,lng>&key=<key>&units=metric&mode=driving`
— road distance for km calculation, 5 s timeout (`deliveries_controller.dart:1115`)
- `launchUrl` only (no HTTP from the app):
- `https://www.google.com/maps/dir/?api=1&destination=<lat>,<lng>` (`nav.dart:444`)
- `https://nearle.in/terms`, `https://nearle.in/privacy`, `https://nearle.in/faq`
- `https://play.google.com/store/apps/details?id=com.nearle.partner`
- `https://apps.apple.com/us/app/nearle/id1596895375ls=1`
### MQTT
`66.116.225.226:1883`, user `admin` (`lib/views/helpers/constants/mqtt_constants.dart`)
| Topic | Payload |
|---|---|
| `nearle/riders/{riderId}/status` | `Online` / `Offline` / `Idle` / `Active` |
| `nearle/riders/{riderId}/profile` | `userid, username, firstname, lastname, contactno, userfcmtoken, app_version, device_info` |
| `nearle/riders/{riderId}/location` | `userid, orderid, lat, lng, raw_lat, raw_lng, speed, heading, velocity_lat, velocity_lng, timestamp` |
| `nearle/riders/{riderId}/telemetry` | battery, charging, speed, connection, accuracy |
| `nearle/riders/{riderId}/logs` | `rider_periodic_log`, `delivery_picked`, `critical_battery`, alerts |
---
## Known issues found during the sweep
1. **`lib/controllers/riderkm.dart:11` builds a broken URL.** `baseUrl` is
already `…/v1/partners/getriderweeklykms`, and the code appends
`/getriderweeklykms?userid=` → `…/getriderweeklykms/getriderweeklykms?userid=`.
The summary *view* calls it correctly, so this controller path is likely dead
or silently failing.
2. **`lib/controllers/support_ticket.dart:66` hardcodes `userId = 1242`** in
`fetchTickets()` — every rider sees user 1242's ticket list.
3. **Secrets shipped in the APK**: DO Spaces access key + secret
(`support_ticket.dart`, `deliveries_controller.dart`), LionSMS API key,
MQTT `admin` / `Package@321#`, Google Maps key.
4. **OTP is generated and verified on-device**, stored in
`SharedPreferences('lastOtp')` — trivially bypassable.
5. **TLS verification disabled** for `queue.workolik.com` plus a hardcoded IP
pin (`66.116.225.226`). If that VPS IP changes, every write endpoint breaks
at once.
6. **`backgroundservice.dart:845` POSTs to `updateriderlog`** while every other
caller PUTs it. If the server is method-strict, auto-shift-end never marks
the rider offline.
7. `updateDeliveryDev`, `createRiderLogDev`, `createBreakRiderLogDev`,
`updateBreakRiderLogDev` and `createDeliveryLogDev` all point at **live** —
there is no working dev environment for writes.
8. `lib/providers/support/support_ticket.dart` is a dead duplicate of the
controller and references an `…/partners/uploadimage/` endpoint nothing else
uses.