Developer Documentation
Agent Protocol API Reference
A REST API for AI agents to discover restaurants, browse menus, and place orders. ACP-compliant checkout with Stripe Shared Payment Tokens.
Overview
The Menami Agent Protocol is a REST API that enables AI agents — personal assistants, custom GPTs, autonomous ordering bots — to discover restaurants, browse menus with full modifier details, and complete orders programmatically.
The checkout flow is ACP-compliant (Agentic Commerce Protocol by Stripe and OpenAI), meaning any ACP-compatible agent can complete purchases using Stripe Shared Payment Tokens without additional integration work.
Base URL: https://api.menami.mx/api/v1/agent
Format: All requests and responses use JSON. Set Content-Type: application/json on request bodies.
Pagination: List endpoints support page and limit query params (default: page 1, limit 20, max 100).
Authentication
Discovery endpoints (listing restaurants, viewing menus) require no authentication. Checkout, delivery, and order status endpoints require an API key.
API Key
Pass your API key via the X-Agent-Key header. For ACP compatibility, Authorization: Bearer <key> is also accepted.
curl -X POST https://api.menami.mx/api/v1/agent/checkout_sessions \
-H "Content-Type: application/json" \
-H "X-Agent-Key: ak_live_7f3a9b2c..." \
-d '{ ... }'Rate Limits
Default rate limit is 60 requests per minute per API key. Rate-limited responses return HTTP 429 with a Retry-After header (seconds).
Idempotency
All POST endpoints require an Idempotency-Key header (UUID v4). Same key + identical body returns the cached response. Same key + different body returns 422 idempotency_conflict. Keys are retained for 24 hours.
Discovery Endpoints
Browse and search the restaurant catalog. No authentication required.
/api/v1/agent/restaurantsNo authSearch and filter restaurants.
| Param | Type | Description |
|---|---|---|
| q | string | Free-text search (name, cuisine, description) |
| cuisine | string | Filter by cuisine type |
| city | string | Filter by city (case-insensitive, partial match) |
| lat | number | Latitude for radius search |
| lng | number | Longitude for radius search |
| radius_km | number | Search radius in km (default: 8) |
| open_now | boolean | Only currently open restaurants |
| dietary | string | Filter by dietary tag |
| page | number | Page number (default: 1) |
| limit | number | Results per page (default: 20, max: 100) |
{
"total": 47,
"page": 1,
"limit": 20,
"restaurants": [
{
"name": "Tacos El Padrino",
"slug": "tacos-el-padrino",
"cuisine": ["mexican", "tacos"],
"city": "Mexico City",
"country": "MX",
"price_range": "$$",
"currency": "MXN",
"delivery": true,
"pickup": true,
"ordering_enabled": true,
"min_order_amount": 150,
"estimated_prep_minutes": 25,
"open_now": true,
"item_count": 34
}
]
}/api/v1/agent/restaurants/:slugNo authFull restaurant details including address, operating hours, and delivery zone.
{
"name": "Tacos El Padrino",
"slug": "tacos-el-padrino",
"cuisine": ["mexican", "tacos"],
"address": {
"street": "Av. Insurgentes Sur 1234",
"city": "Mexico City",
"state": "CDMX",
"zip": "03100",
"country": "MX"
},
"phone": "+525512345678",
"currency": "MXN",
"timezone": "America/Mexico_City",
"operating_hours": {
"monday": [{ "open": "11:00", "close": "22:00" }],
"friday": [{ "open": "11:00", "close": "23:00" }],
"sunday": [{ "open": "10:00", "close": "21:00" }]
},
"price_range": "$$",
"delivery": true,
"pickup": true,
"ordering_enabled": true,
"min_order_amount": 150,
"estimated_prep_minutes": 25,
"delivery_zone": {
"type": "radius",
"center": { "lat": 19.4126, "lng": -99.1703 },
"radius_km": 8
},
"open_now": true,
"website_url": "https://tacoselpadrino.menami.mx"
}/api/v1/agent/restaurants/:slug/menuNo authFull menu with categories, items, dietary tags, and modifier groups (customization options).
{
"restaurant_slug": "tacos-el-padrino",
"currency": "MXN",
"last_updated": "2026-02-24T10:00:00Z",
"categories": [
{
"name": "Tacos",
"slug": "tacos",
"description": "Handmade corn tortillas",
"items": [
{
"id": "550e8400-e29b-41d4-a716-446655440001",
"name": "Taco al Pastor",
"description": "Marinated pork with pineapple, cilantro, onion",
"price": 45.00,
"currency": "MXN",
"dietary_tags": ["gluten_free"],
"allergens": [],
"available": true,
"image_url": "https://cdn.example.com/taco-pastor.jpg",
"modifier_groups": [
{
"id": "group-uuid-1",
"name": "Spice Level",
"selection_type": "single_select",
"required": true,
"min_selections": 1,
"max_selections": 1,
"options": [
{ "id": "mod-1", "name": "Mild", "price_adjustment": 0 },
{ "id": "mod-2", "name": "Medium", "price_adjustment": 0 },
{ "id": "mod-3", "name": "Hot", "price_adjustment": 0 },
{ "id": "mod-4", "name": "Extra Hot", "price_adjustment": 5.00 }
]
},
{
"id": "group-uuid-2",
"name": "Extra Toppings",
"selection_type": "multi_select",
"required": false,
"min_selections": 0,
"max_selections": 3,
"options": [
{ "id": "mod-5", "name": "Extra Cheese", "price_adjustment": 15.00 },
{ "id": "mod-6", "name": "Guacamole", "price_adjustment": 20.00 },
{ "id": "mod-7", "name": "Sour Cream", "price_adjustment": 10.00 }
]
}
]
}
]
}
]
}Checkout Endpoints
ACP-compliant checkout flow. All endpoints require an API key via X-Agent-Key header and an Idempotency-Key header on POST requests.
/api/v1/agent/checkout_sessionsAPI key requiredCreate a checkout session with items, customer info, and optional delivery address. The server validates items, resolves modifiers, calculates totals (including tax and delivery), and returns an ACP-shaped session.
{
"restaurant_slug": "tacos-el-padrino",
"currency": "mxn",
"line_items": [
{
"id": "550e8400-e29b-41d4-a716-446655440001",
"quantity": 3,
"modifiers": [
{ "group_id": "group-uuid-1", "option_ids": ["mod-3"] },
{ "group_id": "group-uuid-2", "option_ids": ["mod-6"] }
]
},
{
"id": "550e8400-e29b-41d4-a716-446655440010",
"quantity": 1
}
],
"customer": {
"name": "Carlos Martinez",
"phone": "+525598765432",
"email": "carlos@example.com"
},
"fulfillment_details": {
"address": {
"street": "Calle Amsterdam 45, Apt 3B",
"city": "Mexico City",
"state": "CDMX",
"country": "MX",
"zip": "06100",
"lat": 19.4126,
"lng": -99.1703
}
},
"special_instructions": "Ring doorbell twice, second floor"
}The response follows the ACP CheckoutSession schema with enriched line items, fulfillment options, totals breakdown (subtotal, tax, delivery, total), and payment capabilities.
{
"id": "cs_abc123",
"status": "ready_for_payment",
"line_items": [ ... ],
"fulfillment_options": [
{ "type": "pickup", "label": "Pickup" },
{ "type": "local_delivery", "label": "Delivery", "fee": 59.99, "eta_minutes": 35 }
],
"totals": {
"subtotal": 175.00,
"tax": 28.00,
"fulfillment": 59.99,
"total": 262.99
},
"capabilities": {
"payment": {
"handlers": [
{ "id": "card_tokenized", "merchant_id": "acct_..." }
]
}
}
}/api/v1/agent/checkout_sessions/:idAPI key requiredRetrieve the current state of a checkout session, including status, line items, and totals.
/api/v1/agent/checkout_sessions/:id/completeAPI key requiredFinalize the order with a Stripe Shared Payment Token (SPT). The server creates a PaymentIntent, processes payment, creates the order, and triggers the restaurant notification flow.
{
"payment_data": {
"handler_id": "card_tokenized",
"instrument": {
"type": "card",
"credential": {
"type": "spt",
"token": "spt_abc123..."
}
}
}
}{
"status": "completed",
"order": {
"id": "order-uuid",
"order_number": "ORD-20260224-XK9F2",
"permalink_url": "https://tacoselpadrino.menami.mx/order/order-uuid",
"status": "confirmed"
}
}/api/v1/agent/checkout_sessions/:id/cancelAPI key requiredCancel a checkout session. Optionally include an intent_trace string for analytics on why the agent abandoned the order.
{
"intent_trace": "user_changed_mind"
}Utility Endpoints
/api/v1/agent/delivery-quoteAPI key requiredGet a delivery cost estimate and ETA before creating a checkout session.
{
"restaurant_slug": "tacos-el-padrino",
"delivery_address": {
"street": "Calle Amsterdam 45",
"city": "Mexico City",
"state": "CDMX",
"country": "MX",
"zip": "06100",
"lat": 19.4126,
"lng": -99.1703
}
}{
"fee": 59.99,
"currency": "MXN",
"eta_minutes": 35,
"available": true
}/api/v1/agent/orders/:idAPI key requiredCheck order status and delivery tracking information.
{
"order_id": "order-uuid",
"order_number": "ORD-20260224-XK9F2",
"status": "preparing",
"status_history": [
{ "status": "confirmed", "at": "2026-02-24T14:30:00Z" },
{ "status": "preparing", "at": "2026-02-24T14:32:00Z" }
],
"delivery": {
"status": "driver_assigned",
"tracking_url": "https://uber.com/track/..."
}
}Error Handling
All errors return a consistent JSON structure:
{
"error": "Human-readable error message",
"code": "error_code",
"details": { ... } // optional, endpoint-specific
}Common Error Codes
| HTTP | Code | Description |
|---|---|---|
| 400 | invalid_request | Missing or invalid request parameters |
| 400 | idempotency_key_required | POST request missing Idempotency-Key header |
| 401 | unauthorized | Missing or invalid API key |
| 404 | not_found | Restaurant, item, session, or order not found |
| 409 | conflict | Idempotent request already in flight (check Retry-After header) |
| 422 | idempotency_conflict | Same Idempotency-Key used with different body |
| 422 | out_of_stock | One or more items are unavailable |
| 422 | missing_modifier | Required modifier group has no selection |
| 422 | below_minimum | Order total below restaurant minimum |
| 422 | restaurant_closed | Restaurant is currently closed |
| 422 | outside_delivery_zone | Delivery address outside restaurant delivery range |
| 422 | payment_declined | Payment could not be processed |
| 429 | rate_limited | Too many requests (check Retry-After header) |
Ready to integrate?
Get your API key and start building agent-powered ordering for your platform.
Get your API key