Saves stop and product updates for one or more stops on a route. Handles stop status, product counts, OSD entries, driver comments, and signatures.
Endpoint: PUT /api/route/stop
Authentication: Required: headers: employee_id, api_token
Note (Route closure: behavior differs by environment as of v23): Whether to enable arrival-gating in production is an ongoing internal decision (still unresolved as of this writing), not a bug: both paths below are current and intentional for now.
DB_LIBRARIES other than DVXDEVFIL): legacy behavior: submitting stop id: 999 with updates.status: "D" closes the route (GROUTEC.ROUTEPOD = 'C') immediately. No arrival check, no timer.DB_LIBRARIES=DVXDEVFIL): route closure is gated on warehouse arrival. Submitting stop 999 with arrived: true sets GROUTEC.ROUTERTN = 'Y'. When stop 999 is later submitted with updates.status: "D": if arrival was recorded, the route closes immediately; otherwise a 10-minute server-side timer starts (keyed per route, deduped against concurrent submits) and force-closes the route when it fires even without a confirmed arrival.Note (OSD): Both product.updates.osd_data and product.action.updates.osd_data use the same grouped format: [{ osd_id, osd_code, data: [{ osd_parent, comment, quantity, images_id, barcodes, quantity_type }] }]. barcodes is a single barcode string per entry (empty string if none). quantity_type v23 is "units", "cases", or omitted/null: written to the PDQTYIS column. osd_id (group-level) and osd_parent (entry-level) v23 are opaque char(6) values written to PDOSDID/PDOSDPAR and echoed back unchanged on GET: the API only stores and recalls them, it does not interpret them. Product-level OSD writes PDIDCODE = product_id, PDUPCCD = barcodes, PDOSDITMZ = 'N'. Action (itemized) OSD writes PDIDCODE = product_id, PDUPCCD = '', PDOSDITMZ = 'Y'; barcodes in data entries are not persisted.
Note (Overage Items): Items found at the stop that are not on the manifest go in stop.updates.overage_items: [{ barcode, osd_code, quantity, comment, images_id }]: no quantity_type on this shape. Each entry writes one GPODOSD row (PDIDCODE = '', PDUPCCD = barcode, PDOSDITMZ=N). On GET, rows with an empty PDIDCODE are returned in stop.updates.overage_items.
Note (Delivery Email): If the stop is non-warehouse (id !== 999), updates.status is "D", and the route is flagged GROUTEC.ROUTEPPOD = 'Y', a delivery summary email is sent automatically after all writes complete. See the email preview tool below.
Request body:
{
"id": "17140",
"facility": "011",
"week_end": "20251031",
"stops": [
{
"id": 258,
"arrived": false,
"updates": {
"status": "D",
"followup_reason_code": "",
"start_delivery_time": "2025-10-31T10:00:00Z",
"end_delivery_time": "2025-10-31T10:15:00Z",
"delivery_latitude": "41.8781",
"delivery_longitude": "-87.6298",
"delivered_by_driver_id": "T0048",
"store_emp_id": "EMP001",
"store_emp_name": "JOHN DOE",
"driver_comments": "Left at dock",
"skip_refuse_reason_code": "",
"skip_refuse_timestamp": "",
"skip_refuse_driver_comment": "",
"signature_id": "",
"osd_emails": [],
"overage_items": [
{ "barcode": "012345678901", "osd_code": "85", "quantity": 1, "comment": "", "images_id": "" }
]
},
"products": [
{
"id": "038976",
"invoice": "0806591",
"updates": {
"accounting_complete": false,
"delivered": 6,
"returned": 0,
"delivered_pallets": null,
"image_ids": null,
"osd_data": [
{
"osd_id": "ABCDEF",
"osd_code": 51,
"data": [
{ "osd_parent": "ABCDEF", "comment": "1 bag missing", "quantity": 1, "images_id": "", "barcodes": "00016000148710", "quantity_type": "units" },
{ "osd_parent": null, "comment": "1 damaged box", "quantity": 1, "images_id": "", "barcodes": "016000502789", "quantity_type": null }
]
}
]
},
"action": {
"updates": { "delivered": 0, "osd_data": [] },
"type": null,
"open": false,
"open_action": null,
"item_name": null,
"quantity": 7
}
},
{
"id": "9001",
"invoice": "0806591",
"updates": {
"accounting_complete": false,
"delivered": 10,
"returned": 0,
"delivered_pallets": null,
"image_ids": null,
"osd_data": []
},
"action": {
"updates": { "delivered": 10, "osd_data": [] },
"type": "count",
"open": false,
"open_action": null,
"item_name": null,
"quantity": 10
}
}
],
"collections": [
{
"id": "9009",
"invoice": "0806591",
"updates": {
"returned": 0,
"accounting_complete": false,
"image_ids": null,
"osd_data": []
},
"action": {
"updates": { "delivered": 0, "osd_data": [] },
"type": "collect",
"open": false,
"open_action": null,
"item_name": null,
"quantity": 0
}
}
]
}
]
}
Result:
...
Renders the delivery summary email's generated HTML directly in the response: no email is sent. Useful for checking layout/content without triggering a real send (which is otherwise a side effect of PUT /api/route/stop, not directly callable).
Endpoint: GET /api/route/stop/email-preview?facility=&route_id=&stop_id=&week_end=
Authentication: None
Marks a stop as skipped or refused.
Endpoint: PUT /api/route/stop/skip-refuse
Authentication: Required: headers: employee_id, api_token
Required body fields: route_id, stop_id
Result:
...