Agent Ordering MCP + REST

AI assistants can order food from Soldi Now restaurants on a customer’s behalf: read the live menu, quote the cart exactly, place a pay-first order, and hand the customer the payment link. The customer pays on Soldi Now’s hosted page (card, Apple Pay, Google Pay, or their Soldi Now account); the assistant never touches payment details. The kitchen starts the order only after it is paid.

Connect

SurfaceWhereFor
MCP server (Streamable HTTP, stateless, no auth)https://web.soldinow.com/mcpClaude.ai custom connectors, Claude Desktop and Claude Code, ChatGPT and Gemini connectors, any MCP client
REST + OpenAPI 3.1https://web.soldinow.com/api/agent/v1/ · spec: openapi.jsonCustom GPT actions, plain HTTP agents, schema-driven frameworks

Claude.ai: Settings → Connectors → Add custom connector → paste the MCP URL, choose “no authentication”. Staging: https://web-staging.soldinow.com/mcp.

Participating restaurants are listed at /restaurants; each page carries the menu as HTML and schema.org markup, and says how to order from it.

The six operations

MCP toolRESTWhat it does
find_storesGET /stores?q=Participating restaurants by name or address substring, with whether online ordering is accepting right now and when it closes or reopens.
get_menuGET /stores/{storeId}/menu?menu=full|vegCategories, items with prices and dietary tags (veg, vegan, gf, spicy), popularity, and each item’s modifier groups (required choices, add-ons, quantities). Use these ids in the next two calls.
quote_orderPOST /stores/{storeId}/quoteServer-priced dry run of the cart: resolved lines, promo, tax, estimated total — or an error whose code says what to fix. Nothing is written. Confirm with the customer before placing.
place_orderPOST /stores/{storeId}/ordersCreates the pay-first order. Returns paymentUrl, a 4-digit payAtCounterCode, expiresAt (30 minutes), statusUrl. Requires customerName and a fresh idempotencyKey per new order (a repeated key returns the original order, never a second one).
get_order_statusGET /orders/{orderId}awaiting_payment → paid (the kitchen has it), or expired / cancelled. Poll every 15–30 seconds while the customer pays.
cancel_orderPOST /orders/{orderId}/cancelRetire an unpaid order the customer no longer wants. Refused once paid or while a payment is in progress. To change an order: cancel and place again.

Also: GET /orders/{orderId}/payment-qr renders the payment link as a PNG QR code for assistants with a screen but no tap target.

The flow

  1. The customer asks their assistant to order. find_stores("chaat house") → store card with address and “accepting until 9:30 pm”.
  2. get_menu → the assistant maps what the customer said onto item and option ids.
  3. quote_order → the resolved cart and total, or a problem such as REQUIRED_MODIFIER_MISSING (“Samosa Chaat needs a spice level: Mild, Medium, Hot”). The assistant confirms with the customer.
  4. place_order → the assistant shows the link: “Pay $23.41 here → … (or give code 4821 at the counter)”. The customer opens it on Soldi Now’s payment page; a signed-in member gets their Cash Club points and offers, a guest pays by card or wallet.
  5. Payment closes the order and the kitchen ticket prints. get_order_status flips to paid; the assistant tells the customer where to pick up.
  6. Nothing paid in 30 minutes → the order expires and never reaches the kitchen; the assistant offers to reorder.

Request shape (quote and place)

{
  "lineItems": [
    {"menuItemId": "…", "quantity": 2, "optionIds": ["…"], "notes": "no onions"}
  ],
  "fulfillment": "TAKEOUT",          // or DINE_IN
  "menu": "full",                    // or veg, where the restaurant offers it
  "promoCode": "SCHOOL10",           // optional

  "customerName": "Priya",           // place only, required
  "customerPhone": "+14085551212",   // optional
  "idempotencyKey": "chat-7f3a-…",   // place only, required, unique per new order
  "agent": "claude"                  // optional attribution
}

Always send optionIds (an empty array when the item has no choices) so required groups are enforced. Repeat an option id to take it more than once only when its group has allowQuantity. Prices never come from the assistant.

Errors the model can act on

Every failure is {"error": {"code", "message", "details"}} (MCP: a tool error carrying the same JSON). The message is customer-facing and safe to relay.

CodeHTTPMeaning / details
STORE_NOT_FOUND404Not a participating restaurant.
ORDERING_CLOSED409Outside online-ordering hours or paused; reopensAt, message, paused.
ITEM_NOT_FOUND / ITEM_UNAVAILABLE400Unknown id, wrong store, sold out, not today, or not on the vegetarian menu; menuItemId.
REQUIRED_MODIFIER_MISSING / INVALID_OPTION / TOO_MANY_OPTIONS400Fix the optionIds for the named item and group.
PROMO_INVALID400The code does not apply; the message says why.
QUANTITY_TOO_LARGE / ORDER_TOO_LARGE40020 per line, 60 units per order, 30 lines; limit. Confirm with the customer and split.
FREE_ITEMS_ONLY400A cart with nothing to pay for cannot be ordered online.
REQUEST_IN_PROGRESS409Another call with the same idempotencyKey is still running; retry in a few seconds.
ALREADY_PAID / PAYMENT_IN_PROGRESS / ORDER_EXPIRED409For cancel_order and the QR.
RATE_LIMITED429retryAfterSeconds. Per-address limits, and at most 25 unpaid assistant orders per restaurant at a time.
MENU_UNAVAILABLE503Transient; retry.

Rules for agent builders

Security model

PropertyHow
Assistant never holds credentialsOnly a payment link and an order id ever reach it.
Links are not bearer secretsThe payment page verifies the link’s signature and pays that order only; a leaked link cannot pay anything else.
Human-present approvalThe customer sees the restaurant, the lines and the total on our page before any money moves.
Abuse boundedUnpaid orders expire in 30 minutes and never reach the kitchen; per-address rate limits, per-restaurant caps, per-line quantity caps, idempotency keys.
Restaurants opt inOnly restaurants that switched assistant ordering on are reachable at all.

For restaurants

Switch on “Let AI assistants order from this store” on your Soldi Now menu page and set the public page address. Set your Google Business Profile “Order online” link to your Soldi Now takeout link so assistants that search the web find the ordering path. Questions — support@soldinow.com.