Order Tracking Extension¶
Extension: dev.asp.services.order_tracking
Version: 2026-02-19
Extends: dev.ucp.shopping.order
Schema: order_tracking.json
Purpose¶
Extends UCP order with granular fulfillment status tracking. Supports both polling (GET) and push (webhook) models for real-time updates.
Status Progression¶
accepted → in_progress → en_route → completed
→ cancelled (from any state)
Schema: Fulfillment Status¶
| Field | Type | Required | Description |
|---|---|---|---|
order_id |
string | Yes | Identifier of the order being tracked. |
status |
string | Yes | Current order status. Values: accepted, in_progress, en_route, completed, cancelled |
estimated_service_minutes |
integer | No | Updated estimated service time in minutes. |
updated_at |
string | Yes | Timestamp of the last status update. |
agent_location |
object | No | Real-time agent location for live tracking. |
history |
array\<object> | No | Ordered timeline of status transitions. Enables agents to narrate the full journey: 'Accepted at 7:01, picked up at 7:15.' |
is_delayed |
boolean | No | Whether the order is running behind the original estimate. Allows agents to proactively warn: 'Heads up, your order is running late.' |
delay_minutes |
integer | No | How many minutes behind the original estimate. e.g. 'Running about 10 minutes late.' |
Polling Endpoint¶
GET /orders/{order_id}/tracking
Returns the current fulfillment_status object.
Push Model: Webhooks¶
The marketplace sends a status_update_event to the agent/platform whenever the order status changes:
{
"event_type": "order.status_updated",
"order_id": "order-12345",
"status": {
"order_id": "order-12345",
"status": "en_route",
"estimated_service_minutes": 12,
"updated_at": "2026-02-19T12:45:00Z",
"agent_location": {
"latitude": 37.7751,
"longitude": -122.4180
}
},
"timestamp": "2026-02-19T12:45:00Z"
}
Webhook Registration¶
Webhook endpoints are declared in the discovery profile or negotiated during checkout. The marketplace POSTs status_update_event payloads to the registered URL.
Status History¶
The history array provides an ordered timeline of status transitions, enabling agents to narrate the full journey:
{
"order_id": "order-12345",
"status": "en_route",
"updated_at": "2026-02-19T12:45:00Z",
"history": [
{ "status": "accepted", "timestamp": "2026-02-19T12:30:00Z" },
{ "status": "in_progress", "timestamp": "2026-02-19T12:35:00Z" },
{ "status": "en_route", "timestamp": "2026-02-19T12:45:00Z", "note": "Driver picked up order" }
]
}
Agent says: "Accepted at 12:30, started preparing at 12:35, driver picked up at 12:45."
Delay Awareness¶
Two optional fields let agents proactively warn users:
| Field | Type | Description |
|---|---|---|
is_delayed |
boolean | Whether the order is running behind the original estimate |
delay_minutes |
integer | How many minutes behind |
Agent says: "Heads up, your order is running about 10 minutes late."
Domain-Specific Statuses¶
The 5 base statuses are intentionally abstract. Domain profiles can define granular statuses that map to the base set, giving agents richer vocabulary without breaking compatibility.
For example, the food delivery domain profile maps 10 granular statuses to the 5 base — see Food Delivery Domain for the full mapping table. An agent that only understands the base statuses still works; the granular statuses are additive.
Agent Behavior¶
Agents should proactively surface status changes to the user:
- accepted: "Your order has been accepted!"
- in_progress: "Your order is being prepared."
- en_route: "Your order is on its way! ETA: 12 minutes."
- completed: "Your order is complete. Enjoy!"
- delayed: "Heads up, your order is running about 10 minutes late."
The estimated_service_minutes field updates with each status change, allowing the agent to show a live countdown.
Agent Location¶
The optional agent_location field (latitude/longitude) enables live map tracking during the en_route phase. This is opt-in — marketplaces that don't support live tracking simply omit the field.
Live Streaming¶
Extension: dev.asp.services.streaming
Extends: dev.asp.services.order_tracking
Schema: streaming.json
Transport: asyncapi.yaml
For continuous agent location tracking (e.g. rendering a live delivery map), ASP provides a WebSocket streaming channel defined via AsyncAPI 3.0.
WebSocket Channel¶
wss://<host>/asp/v1/ws → /orders/{order_id}/tracking/stream
Message Types¶
The server sends three event types, discriminated by event_type:
| Event | When | Frequency |
|---|---|---|
location_update |
Agent GPS position changed | Every 3-5 seconds during en_route |
status_changed |
Order status transition | ~5 per order lifecycle |
heartbeat |
Keep-alive | Every 30 seconds |
Connection Lifecycle¶
- Client opens WebSocket to
wss://<host>/asp/v1/ws - Client sends
subscribewithorder_idand bearertoken(first-message auth) - Server validates and sends a
status_changedsnapshot of current state - Server streams
location_updateevents duringen_routephase - Server sends
heartbeatevery 30s - On terminal status (
completed/cancelled), server sends finalstatus_changedand closes with code 1000
Location Update Payload¶
{
"event_type": "location_update",
"order_id": "order-12345",
"payload": {
"status": "en_route",
"agent_location": {
"latitude": 37.7751,
"longitude": -122.4180,
"heading": 45.0,
"speed_kmh": 28.5
},
"estimated_service_minutes": 8,
"updated_at": "2026-02-19T12:45:03Z"
},
"timestamp": "2026-02-19T12:45:03Z"
}
The heading (compass degrees) and speed_kmh fields enable rotating map markers and smooth interpolation between updates.
Reconnection¶
If the connection drops, the client should:
- Wait with exponential backoff (1s, 2s, 4s, max 30s)
- Reconnect and send a new
subscribemessage - The server resends the current state snapshot
No events are buffered during disconnection — the client gets the latest state on reconnect.
Fallback¶
Clients that cannot use WebSocket should fall back to polling GET /orders/{order_id}/tracking. The webhook push model continues to fire on status transitions regardless of whether a WebSocket connection is active.