Captures the working request bodies for the customer login/booking and the admin/hub assign-miler endpoints, plus the constraints that are easy to hit and hard to diagnose: - CityGate only accepts pickup pincodes in 641/600/560/500 - hub assign-miler 403s unless milerprofiles.hubid matches the calling hub, and most milers have hubid NULL - CreateCustomerBooking auto-assigns in the background, so a booking is often already on a miler before you assign one - the routing watchdog sweeps unaccepted assignments within ~a minute and may re-assign under a new bookingassignmentid, so accept IDs must be re-read - reject takes its reason in the body, not the query string Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
8.3 KiB
Creating a test booking and assigning it to a miler
How to create a pickup booking through the real customer API and put it on a
specific miler, against https://api.doormile.com. Every call below is the
production API — nothing here is a test harness or a shortcut.
Base URL: https://api.doormile.com/api/v1
1. Log in as a customer (two steps)
Customer auth is phone lookup, then PIN. The first call only confirms the account exists; it returns no token.
curl -X POST https://api.doormile.com/api/v1/customer/login \
-H 'Content-Type: application/json' \
-d '{"phone":"9876543222"}'
{ "success": true, "message": "PIN verification required", "phone": "9876543222" }
curl -X POST https://api.doormile.com/api/v1/customer/verify-pin \
-H 'Content-Type: application/json' \
-d '{"phone":"9876543222","pin":"1234"}'
The token is at the top level as token — not under data.
{ "success": true, "token": "eyJhbGciOi...", "user": { "appcustomerid": 1, "firstname": "Rahul", ... } }
Save it: TOKEN=eyJhbGciOi...
Customer test logins (all PIN 1234)
| City | Name | Phone | appcustomerid |
|---|---|---|---|
| Coimbatore | Rahul Sharma | 9876543222 | 1 |
| Hyderabad | Test Customer HYD | 9999900001 | 7 |
| Bangalore | Test Customer BLR | 9999999999 | 6 |
2. Create the booking
curl -X POST https://api.doormile.com/api/v1/customer/bookings \
-H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"pickupaddress": "123 Gandhipuram Main Rd, Coimbatore",
"pickuppincode": "641012",
"pickuplatitude": 11.0168,
"pickuplongitude": 76.9558,
"deliveryaddress": "45 Saravanampatti, Coimbatore",
"deliverypincode": "641035",
"deliverylatitude": 11.0780,
"deliverylongitude": 77.0010,
"serviceoption": "Normal",
"parcels": [{
"itemcategory": "Documents",
"itemdescription": "Test parcel",
"declaredvalue": 500,
"weight": 1.5,
"length": 20, "width": 15, "height": 10
}]
}'
Returns the created booking under data, with bookingid and status
Pending_Pickup. Note the bookingid — step 3 needs it.
Required vs optional
Only pickupaddress, pickuppincode and a non-empty parcels
array are enforced. Delivery fields are optional; if you give a
deliverypincode but no delivery lat/lon, the server geocodes the pincode for
you. Parcel weight and dimensions are optional too — the miler weighs at
pickup — but supplying them makes the volumetric-weight and pricing path
realistic.
serviceoption is one of Normal, Fast, Superfast.
The pickup pincode must be in an operating city
CityGateMiddleware rejects anything else with
{"code":"CITY_NOT_SUPPORTED"}. Allowed 3-digit prefixes:
| Prefix | City |
|---|---|
641 |
Coimbatore |
600 |
Chennai |
560 |
Bengaluru |
500 |
Hyderabad |
Same-prefix pickup and delivery goes hyperlocal
If pickup and delivery share the first 3 digits, BookingPickupComplete sends
the consignment straight to Out_for_Delivery and the same miler does the
final mile. Different prefixes park it at Inwarded_at_Hub, which currently
has no automated path onward. Keep both pincodes in the same prefix unless
you are specifically testing the cross-hub gap.
3. Assign it to a specific miler
The AI routing layer usually gets there first. CreateCustomerBooking
kicks off AssignCustomerMiler in a background goroutine, so a booking is
often auto-assigned within seconds of creation. Check before assigning
manually — you may already have what you want, on a miler you didn't pick.
Admin console — works for any miler
curl -X POST https://api.doormile.com/api/v1/admin/bookings/26/assign-miler \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-H 'Content-Type: application/json' \
-d '{"mileruserid": 4}'
Admin token comes from POST /admin/login (roles 1, 3, 4).
This path has no hub check and no city check — it will put any miler on any booking. That is what makes it the reliable option.
Hub console — miler must belong to the calling hub
curl -X POST https://api.doormile.com/api/v1/hub/bookings/26/assign-miler \
-H "Authorization: Bearer $HUB_TOKEN" \
-H 'Content-Type: application/json' \
-d '{"mileruserid": 4}'
Two extra constraints, both common sources of confusion:
- The booking must be in an assignable state, else
400 booking is not in an assignable state. - The miler's
milerprofiles.hubidmust equal the hub the token belongs to, else403 miler does not belong to this hub. Most milers in production havehubid = NULLand therefore cannot be assigned here at all — they are also invisible in the hub console's miler list. Use the admin endpoint, or set ahubidfirst.
Both endpoints take the same body and funnel into the same
AssignMilerToBooking function, so the resulting DB state is identical:
booking → Miler_Assigned, a new bookingassignments row with status
Assigned, and the miler's availabilitystatus → Assigned.
4. Accept it as the miler — within about a minute
A watchdog on the AI routing layer reverts assignments that are not accepted
promptly: the assignment row is deleted and the booking goes back to
Created. Observed turnaround is under a minute.
In practice it often re-assigns rather than leaving the booking idle, so the
booking still looks assigned to the same miler — but under a new
bookingassignmentid. Observed on booking 26: assignment 42 was swept and
replaced by 43 within ~2 minutes, same miler, same booking. So never hardcode
an assignment ID you noted earlier; always re-read GET /miler/assignments
immediately before accepting, or the accept will 404.
# Miler login mirrors the customer flow
curl -X POST https://api.doormile.com/api/v1/miler/login \
-H 'Content-Type: application/json' -d '{"phone":"9876543255"}'
curl -X POST https://api.doormile.com/api/v1/miler/verify-pin \
-H 'Content-Type: application/json' \
-d '{"phone":"9876543255","pin":"1234"}'
# List what is actually actionable, then accept
curl -H "Authorization: Bearer $MILER_TOKEN" \
https://api.doormile.com/api/v1/miler/assignments
curl -X POST https://api.doormile.com/api/v1/miler/assignments/42/accept \
-H "Authorization: Bearer $MILER_TOKEN"
GET /miler/assignments only returns assignments in Assigned or Accepted,
and accept only succeeds on one currently Assigned — a completed or rejected
job can no longer be revived.
To reject instead, the reason goes in the body, not the query string:
curl -X POST https://api.doormile.com/api/v1/miler/assignments/42/reject \
-H "Authorization: Bearer $MILER_TOKEN" \
-H 'Content-Type: application/json' \
-d '{"reason":"too far"}'
5. Rest of the delivery flow
In order, all as the miler, all Authorization: Bearer $MILER_TOKEN:
| Step | Call |
|---|---|
| Arrived at customer | POST /miler/bookings/:bookingid/reached |
| Confirm parcels | POST /miler/bookings/:bookingid/parcel-confirm |
| Pickup complete | POST /miler/bookings/:bookingid/pickup-complete |
| Deliver | POST /miler/consignments/:consignmentid/deliver |
pickup-complete is what converts the booking into a consignment, sets the
origin hub from the miler's own hubid, and applies the hyperlocal rule from
step 2.
Miler reference
Milers with hubid = NULL work fine via the admin endpoint but not the hub
console. Verify the current roster before relying on this table — production
has ~24 milers and the seed data has been reshaped more than once.
| userid | Name | Phone | Hub | City |
|---|---|---|---|---|
| 4 | Ramesh Kumar | 9876543255 | 1 — Jupiter | Coimbatore |
| 23 | Karthikeyan Vel | 9876500003 | 1 — Jupiter | Coimbatore |
| 6 | Rajesh Sekhar | 9876543256 | 2 — Neptune | Coimbatore |
| 7 | Karthi Keyan | 9876543257 | 7 — RS Puram | Coimbatore |
| 21 | Murugan Palani | 9876500001 | 8 — Saravanampatti | Coimbatore |
| 22 | Selvam Raja | 9876500002 | 17 — Test Hub | Coimbatore |
| 8 | Suresh Goud | 9876543261 | NULL | Hyderabad |
| 28 | Suresh Naik | 9876500008 | NULL | Bangalore |
Coimbatore hubs: 1 Jupiter (641012, sorting centre), 2 Neptune (641004), 7 RS Puram (641002), 8 Saravanampatti (641035), 17 Test Hub (641099).
All miler PINs above are 1234.