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

14 KiB
Raw Blame History

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

{
  "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

{ "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

{
  "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:

{
  "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.

{
  "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

{
  "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

{
  "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

{
  "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).

[
  {
    "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

{
  "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

{
  "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

{
  "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

{
  "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.