Skip to main content
The order lifecycle tools. validate_order, quote_order, and submit_order share one canonical order-intent shape; the by-id tools enforce ownership (an agent only touches orders it created).

validate_order

Run Phantom rule validation before quote or submit. REST equivalent: POST /api/agent/restaurants/:restaurantId/orders/validate. Input — { "restaurant_id": "…", "order": <canonical order intent> }:
  • restaurant_id at the tool level and inside order must match, or the call throws.
  • order.agent_id is stamped with the authenticated agent; supplying a different one throws.
  • fulfillment_address is required for delivery; send latitude/longitude when the client’s address autocomplete has geometry (courier dispatch needs them).
  • Per-player naming: a line with player_first_name must carry quantity: 1 — two players means two item lines.
Output:
Issue codes currently emitted: ordering_disabled, channel_deactivated, location_paused, lead_time_too_short, lead_time_too_long, headcount_too_large, menu_version_stale, player_name_incomplete, player_name_requires_separate_item_line, item_not_found, item_unavailable, item_unavailable_at_time, mapping_needs_review, modifier_group_invalid, modifier_invalid, modifier_unavailable, nested_modifier_quantity_invalid, modifier_not_nested, required_modifier_missing, too_many_modifiers, modifier_quantity_exceeded, too_many_items, order_value_too_large, delivery_unavailable, order_validation_failed.

quote_order

Return pricing for a valid order. REST equivalent: POST /api/agent/restaurants/:restaurantId/orders/quote. Input: same { restaurant_id, order } shape as validate_order. Output:
deliveryFeeCents is the courier fee, already folded into totalCents; it is 0/absent on pickup or when no dispatch quote was available. serviceFeeCents is the agent’s consumer fee (a configured share of subtotal). Idempotency replays are re-shaped to this current schema before being returned.

submit_order

Create the order in Phantom and enter the normal approval and provider-submission lifecycle. REST equivalent: POST /api/agent/restaurants/:restaurantId/orders/submit. Input: same { restaurant_id, order } shape as validate_order. Output:
submit_order never bypasses the restaurant’s approval rules — a needs_approval order awaits a human decision.

get_order_status

Phantom’s last known order state, latest provider order identifier, and the payment snapshot. REST equivalent: GET /api/agent/orders/:orderId/status. Input: { "order_id": "order_123" } Output:
payment is null when no payment record exists. get_order_status exposes Phantom’s order lifecycle, not raw provider-only state.

get_order_tracking

Full tracking snapshot: kitchen status + timestamped status-event timeline, and for delivery orders the courier leg. Input: { "order_id": "order_123" } Output:
Pickup orders return delivery: null.

cancel_order

Cancel a pending order the calling agent placed. Only possible before the restaurant accepts it. Cancels the POS ticket and any courier, and best-effort reverses the payment (refunds captured charges with payout clawback, voids held authorizations). Input: { "order_id": "order_123", "reason": "Customer changed plans" } (reason optional, ≤200 chars) Output: { "ok": true, "status": "cancelled", "message": "…", "payment": "refunded" } There is deliberately no restaurant-access check here: an agent must be able to cancel its own pending order even if the restaurant has since disabled ordering or its channel was deactivated.

update_order

Update a live order’s fulfillment details and re-point any courier (partial PATCH). Input:
Output:
status echoes the order’s current lifecycle status, not an update result. Menu items are not editable. The restaurant’s POS ticket cannot be amended post-submit — cancel and reorder instead. The editable surface is exactly what the courier’s partial update accepts: time, dropoff address, dropoff notes.