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.
Quickstart
Go from zero to a confirmed restaurant order in five requests. Pick a language tab in any code block. Your choice syncs to every other block on the page.
1 · Register an API key
Self-serve, instant. Save the key field. It is shown only once.
curl -X POST https://api.menami.mx/api/v1/agent/keys/register \
-H "Content-Type: application/json" \
-d '{
"platform_name": "AcmeAgent",
"contact_email": "dev@acme.ai",
"website_url": "https://acme.ai",
"description": "Voice agent for restaurant ordering"
}'2 · Find a restaurant
Discovery endpoints are public. No auth needed.
curl "https://api.menami.mx/api/v1/agent/restaurants?city=mexico&cuisine=mexican&limit=5"
3 · Fetch the menu
Menu responses include full modifier groups (sizes, sides, add-ons) and dietary tags.
curl "https://api.menami.mx/api/v1/agent/restaurants/tacos-el-padrino/menu"
4 · Create a checkout session
POSTs require an Idempotency-Key header. The server validates items, resolves modifiers, calculates tax plus delivery, and returns an ACP-shaped session.
curl -X POST https://api.menami.mx/api/v1/agent/checkout_sessions \
-H "Content-Type: application/json" \
-H "X-Agent-Key: $MENAMI_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"restaurant_slug": "tacos-el-padrino",
"currency": "mxn",
"line_items": [
{ "id": "550e8400-e29b-41d4-a716-446655440001", "quantity": 3 }
],
"customer": {
"name": "Carlos Martinez",
"phone": "+525598765432"
}
}'5 · Complete with a Shared Payment Token
Pass a Stripe SPT (or any ACP-compliant token). The server creates the PaymentIntent on the restaurant's connected account and dispatches the order.
curl -X POST https://api.menami.mx/api/v1/agent/checkout_sessions/cs_abc123/complete \
-H "Content-Type: application/json" \
-H "X-Agent-Key: $MENAMI_KEY" \
-d '{
"payment_data": {
"handler_id": "card_tokenized",
"instrument": {
"type": "card",
"credential": { "type": "spt", "token": "spt_abc123..." }
}
}
}'Already speak MCP? Skip the REST layer entirely. Install @menami/mcp-server and your agent gets recommendations, booking, ordering, and feedback as native MCP tools. See SDKs and integrations.
Overview
The Menami Agent Protocol is a REST API that enables AI agents (personal assistants, custom GPTs, autonomous ordering bots, search indexers) to discover restaurants, browse menus with full modifier details, complete orders programmatically, and track delivery.
The checkout flow is ACP-compliant (Agentic Commerce Protocol by Stripe and OpenAI). 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: JSON in, JSON out. Set Content-Type: application/json on POST bodies.
Pagination: List endpoints accept page (default 1) and limit (default 20, max 100).
OpenAPI: Full spec at api.menami.mx/openapi.yaml. Generate SDKs in any language.
Authentication
Discovery endpoints (listing restaurants, viewing menus, sitemap) require no authentication. Checkout, delivery quotes, and order status 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. Both header names route to the same auth check.
curl https://api.menami.mx/api/v1/agent/orders/$ORDER_ID/status \ -H "X-Agent-Key: ak_live_7f3a9b2c..." # ACP-style equivalent: curl https://api.menami.mx/api/v1/agent/orders/$ORDER_ID/status \ -H "Authorization: Bearer ak_live_7f3a9b2c..."
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). Self-serve key registration is additionally rate-limited to 5 registrations per IP per hour. Need higher limits as a partner? agents@menami.mx.
Idempotency
All POST endpoints require an Idempotency-Key header (UUID v4 recommended). Same key plus identical body returns the cached response. Same key plus different body returns 422 idempotency_conflict. Keys are retained for 24 hours.
Request correlation
Every response includes an X-Request-Id header. If you supply your own value on the request, we echo it back; otherwise we mint a req_* UUID. Include this ID in any support email and we can trace the request end-to-end in seconds.
Test mode
Build and integrate without ever placing a real order. Pass mode: "test" when registering a key and you get back an ak_test_* key. Test keys behave identically to live keys at the protocol level (same endpoints, same response shapes, same idempotency), but the checkout completion step does not charge a card or notify the restaurant.
curl -X POST https://api.menami.mx/api/v1/agent/keys/register \
-H "Content-Type: application/json" \
-d '{
"platform_name": "AcmeAgent",
"contact_email": "dev@acme.ai",
"mode": "test"
}'Differences in test mode:
POST /checkout_sessions/:id/completeskips Stripe entirely and returns a syntheticpi_test_*payment intent ID.- The order is still created in the database (with
channel="agent_test"andtest_mode=trueon the response) so you can exercise the full lifecycle including webhooks. - Order status webhooks fire for both live and test keys. Emit fake status transitions from the admin console to drive your integration.
- Discovery endpoints behave identically; you can browse the real restaurant catalog.
Pagination
List endpoints support two pagination modes. Pick the one that fits your access pattern:
Page-based (default)
Pass page and limit. Convenient for UI pagers (we return total). Not stable across writes: if the catalog changes mid-iteration you can miss or duplicate rows.
Cursor-based (recommended for crawlers)
Pass starting_after=<slug> from the previous response's next_cursor field. Results are ordered by slug, so iteration is stable even while restaurants are being added or modified. Keep going until next_cursor is null.
# First page — no cursor curl "https://api.menami.mx/api/v1/agent/restaurants?limit=100" # Subsequent pages — pass the next_cursor from the previous response curl "https://api.menami.mx/api/v1/agent/restaurants?starting_after=tacos-el-padrino&limit=100"
Combine with updated_since to crawl only the rows that changed since your last sweep. See Indexing and partners.
Discovery endpoints
Browse and search the restaurant catalog. No authentication required.
/api/v1/agent/restaurantsNo authSearch and filter restaurants. Returns active, ordering-enabled, Stripe-onboarded restaurants.
| Param | Type | Description |
|---|---|---|
| q | string | Free-text search across name and cuisine. |
| city | string | Filter by city (case-insensitive partial match). |
| cuisine | string | Filter by cuisine type (case-insensitive partial match). |
| updated_since | ISO-8601 | Return only restaurants modified at or after this timestamp. Use for incremental indexing. |
| starting_after | string | Cursor. Pass next_cursor from the previous response for stable iteration. Mutually informative with page. |
| page | integer | Page number (default: 1). Ignored when starting_after is set. |
| limit | integer | Results per page (default: 20, max: 100). |
curl "https://api.menami.mx/api/v1/agent/restaurants?city=mexico&cuisine=mexican&limit=5"
{
"total": 47,
"page": 1,
"limit": 20,
"next_cursor": null,
"has_more": true,
"restaurants": [
{
"name": "Tacos El Padrino",
"slug": "tacos-el-padrino",
"cuisine": ["mexican"],
"city": "Mexico City",
"country": "MX",
"currency": "MXN",
"delivery": true,
"pickup": true,
"ordering_enabled": true,
"min_order_amount": 15000,
"estimated_prep_minutes": 25,
"item_count": 34,
"updated_at": "2026-05-01T12:00:00.000Z"
}
]
}All monetary amounts (e.g. min_order_amount) are in minor units: cents for USD, centavos for MXN.
/api/v1/agent/restaurants/:slugNo authFull restaurant details including address, operating hours, and a Schema.org JSON-LD Restaurant block in the schema_org field.
{
"name": "Tacos El Padrino",
"slug": "tacos-el-padrino",
"cuisine": ["mexican"],
"address": {
"street": "Av. Insurgentes Sur 1234",
"city": "Mexico City",
"state": "CDMX",
"zip": "03100",
"country": "MX"
},
"phone": "+525512345678",
"email": "hola@tacoselpadrino.mx",
"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" }]
},
"delivery": true,
"pickup": true,
"ordering_enabled": true,
"min_order_amount": 15000,
"estimated_prep_minutes": 25,
"website_url": "https://tacos-el-padrino.orderin.ai",
"updated_at": "2026-05-10T08:30:00.000Z",
"schema_org": {
"@context": "https://schema.org",
"@type": "Restaurant",
"name": "Tacos El Padrino",
"url": "https://tacos-el-padrino.orderin.ai",
"servesCuisine": ["mexican"],
"address": {
"@type": "PostalAddress",
"streetAddress": "Av. Insurgentes Sur 1234",
"addressLocality": "Mexico City",
"addressRegion": "CDMX",
"postalCode": "03100",
"addressCountry": "MX"
},
"telephone": "+525512345678",
"hasMenu": "https://tacos-el-padrino.orderin.ai/menu"
}
}Full menu with categories, items, dietary tags, allergens, and modifier groups (customization options).
curl "https://api.menami.mx/api/v1/agent/restaurants/tacos-el-padrino/menu"
{
"restaurant_slug": "tacos-el-padrino",
"currency": "MXN",
"last_updated": "2026-05-12T17:42:00.000Z",
"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": 4500,
"currency": "MXN",
"dietary_tags": ["gluten_free"],
"allergens": [],
"available": true,
"image_url": "https://cdn.menami.mx/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 }
]
}
]
}
]
}
]
}/api/v1/agent/sitemap.jsonNo authEvery active restaurant slug with its updated_at timestamp and canonical detail/menu URLs. Designed for search indexers to bootstrap or refresh their index. Cached for 5 minutes at the edge.
curl https://api.menami.mx/api/v1/agent/sitemap.json
{
"version": "1.0",
"generated_at": "2026-05-26T08:00:00.000Z",
"total": 8421,
"restaurants": [
{
"slug": "tacos-el-padrino",
"city": "Mexico City",
"country": "MX",
"updated_at": "2026-05-24T16:12:00.000Z",
"detail_url": "/api/v1/agent/restaurants/tacos-el-padrino",
"menu_url": "/api/v1/agent/restaurants/tacos-el-padrino/menu"
}
]
}Indexing & partners
Building a search engine, recommendation system, or AI agent that needs the full Menami catalog? You don't need an API key for read-only crawling, but you do need to play nice with our infrastructure.
Recommended crawl pattern
- Initial seed: Pull
/sitemap.jsononce to get every active slug and itsupdated_at. - Fetch detail and menu: For each slug, hit
/restaurants/:slugand/restaurants/:slug/menu. The detail response includes a ready-to-use Schema.org JSON-LDRestaurantblock. - Incremental refresh: Store the max
updated_atfrom your last batch. On the next crawl, hit/restaurants?updated_since=<timestamp>&limit=100. You'll only pay the bandwidth for what changed.
# Fetch only restaurants updated since your last crawl curl "https://api.menami.mx/api/v1/agent/restaurants?updated_since=2026-05-01T00:00:00Z&limit=100"
Crawl policy
- Identify yourself in the
User-Agentheader (e.g.,YourCrawler/1.0 (+https://yourcompany.ai/bot)). - Default unauthenticated rate limit applies to read endpoints. For higher throughput, register a key. Authenticated requests get 60 req/min by default and you can request a partner tier.
- Respect
Cache-Controlheaders. The sitemap is cached 5 minutes; restaurant detail and menu responses are stable for at least 60 seconds in the absence of operator edits. - We do not require attribution but appreciate "Powered by Menami" badges where your UI surfaces our data.
Partner program: Higher rate limits, webhook push updates, and bulk export are available for search engines, AI labs, and agent platforms. partners@menami.mx.
API keys
Self-service key registration. Rate-limited to 5 registrations per IP per hour.
/api/v1/agent/keys/registerNo authRegister your platform and receive an API key instantly. The plaintext key is shown exactly once. Store it securely.
| Param | Type | Description |
|---|---|---|
| platform_namerequired | string | Human-readable name for your agent or platform. |
| contact_emailrequired | string | Email we can use to reach you for security advisories. |
| website_url | string | Optional URL for your product or company. |
| description | string | Short description of what your agent does. |
curl -X POST https://api.menami.mx/api/v1/agent/keys/register \
-H "Content-Type: application/json" \
-d '{
"platform_name": "AcmeAgent",
"contact_email": "dev@acme.ai",
"website_url": "https://acme.ai",
"description": "Voice agent for restaurant ordering"
}'{
"key": "ak_live_7f3a9b2c1d4e5f60718293a4b5c6d7e8f",
"key_prefix": "ak_live_7f3a",
"platform_name": "AcmeAgent",
"rate_limit_per_minute": 60
}Checkout endpoints
ACP-compliant checkout flow. All endpoints require an API key via X-Agent-Key and an Idempotency-Key header on POSTs.
/api/v1/agent/checkout_sessionsAPI key requiredCreate a checkout session. The server validates items, resolves modifiers, calculates totals (subtotal, tax, delivery), and returns a session in ready_for_payment state.
{
"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"] }
]
}
],
"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"
}curl -X POST https://api.menami.mx/api/v1/agent/checkout_sessions \
-H "Content-Type: application/json" \
-H "X-Agent-Key: $MENAMI_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"restaurant_slug": "tacos-el-padrino",
"currency": "mxn",
"line_items": [
{ "id": "550e8400-e29b-41d4-a716-446655440001", "quantity": 3 }
],
"customer": {
"name": "Carlos Martinez",
"phone": "+525598765432"
}
}'{
"id": "cs_abc123",
"status": "ready_for_payment",
"restaurant_slug": "tacos-el-padrino",
"currency": "mxn",
"line_items": [ /* enriched with resolved names + prices */ ],
"fulfillment_options": [
{ "id": "fo_pickup", "type": "pickup", "label": "Pickup" },
{ "id": "fo_delivery", "type": "local_delivery", "label": "Delivery",
"totals": [{ "amount": 5999, "type": "fulfillment" }], "eta_minutes": 35 }
],
"totals": {
"subtotal": 17500,
"tax": 2800,
"fulfillment": 5999,
"total": 26299
},
"capabilities": {
"payment": {
"handlers": [
{ "id": "card_tokenized", "merchant_id": "acct_..." }
]
}
}
}All monetary amounts are in minor units (cents for USD, centavos for MXN).
/api/v1/agent/checkout_sessions/:idAPI key requiredRetrieve the current state of a checkout session.
/api/v1/agent/checkout_sessions/:idAPI key requiredUpdate fulfillment selection (e.g., switch from pickup to delivery), line items, or delivery address. The server recalculates totals.
{
"selected_fulfillment_options": [
{ "type": "local_delivery", "option_id": "fo_delivery" }
]
}/api/v1/agent/checkout_sessions/:id/completeAPI key requiredFinalize with a Stripe Shared Payment Token (SPT). The server creates a PaymentIntent on the restaurant's connected account, processes payment, creates the order, and dispatches it to the restaurant's POS or notification flow.
{
"payment_data": {
"handler_id": "card_tokenized",
"instrument": {
"type": "card",
"credential": {
"type": "spt",
"token": "spt_abc123..."
}
}
}
}curl -X POST https://api.menami.mx/api/v1/agent/checkout_sessions/cs_abc123/complete \
-H "Content-Type: application/json" \
-H "X-Agent-Key: $MENAMI_KEY" \
-d '{
"payment_data": {
"handler_id": "card_tokenized",
"instrument": {
"type": "card",
"credential": { "type": "spt", "token": "spt_abc123..." }
}
}
}'{
"id": "cs_abc123",
"status": "completed",
"order": {
"id": "order-uuid",
"order_number": "ORD-20260224-XK9F2",
"permalink_url": "https://tacos-el-padrino.orderin.ai/order/order-uuid",
"status": "confirmed"
}
}/api/v1/agent/checkout_sessions/:id/cancelAPI key requiredCancel a checkout session. Optionally include intent_trace 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. Useful for previewing the delivery fee in a conversational UI.
curl -X POST https://api.menami.mx/api/v1/agent/delivery/quote \
-H "Content-Type: application/json" \
-H "X-Agent-Key: $MENAMI_KEY" \
-d '{
"restaurant_slug": "tacos-el-padrino",
"delivery_address": {
"street": "Calle Amsterdam 45",
"city": "Mexico City",
"country": "MX",
"lat": 19.4126,
"lng": -99.1703
}
}'{
"delivery_fee": 5999,
"currency": "MXN",
"estimated_minutes": 35,
"quote_id": "dq_abc123",
"expires_at": "2026-05-26T08:15:00.000Z"
}delivery_fee is in minor units (centavos).
/api/v1/agent/orders/:orderId/statusAPI key requiredCheck order status and full status history.
curl https://api.menami.mx/api/v1/agent/orders/$ORDER_ID/status \ -H "X-Agent-Key: $MENAMI_KEY"
{
"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" }
]
}Webhooks
Register endpoints to receive push notifications for order lifecycle events. No more polling. Every delivery is signed with HMAC-SHA256 so you can trust the payload.
Supported events
| Event | Fires when |
|---|---|
| order.confirmed | Payment captured, order accepted. |
| order.preparing | Restaurant marks the order in the kitchen. |
| order.ready | Pickup order is ready for collection. |
| order.out_for_delivery | Driver has picked up the order. |
| order.delivered | Delivery driver completed the dropoff. |
| order.picked_up | Customer picked up a pickup order. |
| order.canceled | Restaurant or customer canceled the order. |
/api/v1/agent/webhooks/endpointsAPI key requiredRegister a webhook URL. The plaintext signing secret is returned exactly once. Save it.
| Param | Type | Description |
|---|---|---|
| urlrequired | string (https) | Where to POST events. HTTPS required in production. |
| events | string[] | Subset of supported events. Defaults to all. |
| description | string | Free-text label shown in the admin dashboard. |
curl -X POST https://api.menami.mx/api/v1/agent/webhooks/endpoints \
-H "Content-Type: application/json" \
-H "X-Agent-Key: $MENAMI_KEY" \
-d '{
"url": "https://yourapp.com/menami-hooks",
"events": ["order.confirmed", "order.delivered", "order.canceled"],
"description": "Production order events"
}'{
"id": "wh_abc123",
"url": "https://yourapp.com/menami-hooks",
"events": ["order.confirmed", "order.delivered", "order.canceled"],
"is_active": true,
"description": "Production order events",
"created_at": "2026-05-26T08:00:00.000Z",
"secret": "whsec_8a2b9f1e..."
}/api/v1/agent/webhooks/endpointsAPI key requiredList all webhook endpoints registered to your API key. The secret is never returned after creation. If you lose it, delete the endpoint and re-register.
/api/v1/agent/webhooks/endpoints/:idAPI key requiredPermanently delete a webhook endpoint. Returns 204.
Event payload
Every event is a JSON envelope with stable top-level fields:
{
"id": "evt_2X9aB1c...",
"type": "order.delivered",
"created": 1716710400,
"data": {
"order_id": "order-uuid",
"order_number": "ORD-20260526-XK9F2",
"status": "delivered",
"source": "uber_direct",
"notes": null,
"updated_at": "2026-05-26T08:00:00.000Z"
}
}Verifying the signature
Every request includes:
X-Menami-Signature: t=<unix_ts>,v1=<hex_hmac>X-Menami-Event: order.deliveredUser-Agent: Menami-Webhooks/1.0
Compute HMAC_SHA256(secret, "{t}.{raw_body}") and constant-time compare to the v1 value. Reject if the timestamp drifts more than 5 minutes from your clock (protects against replay). Always verify against the raw request body, not a re-serialized JSON object.
import crypto from "crypto";
import express from "express";
const app = express();
// Mount with the raw body so we can verify against the exact bytes Menami signed.
app.post(
"/menami-hooks",
express.raw({ type: "application/json" }),
(req, res) => {
const header = req.header("x-menami-signature") || "";
const parts = Object.fromEntries(
header.split(",").map((kv) => kv.split("="))
);
const t = parts.t;
const v1 = parts.v1;
const signed = `${t}.${req.body.toString("utf8")}`;
const expected = crypto
.createHmac("sha256", process.env.MENAMI_WEBHOOK_SECRET!)
.update(signed)
.digest("hex");
// Constant-time compare; reject if timestamp drifts > 5 min.
const fresh = Math.abs(Date.now() / 1000 - Number(t)) < 300;
const valid =
v1.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(v1), Buffer.from(expected));
if (!fresh || !valid) return res.status(400).send("invalid signature");
const event = JSON.parse(req.body.toString("utf8"));
console.log("Received", event.type, event.data.order_id);
res.status(200).send("ok");
}
);Delivery semantics
- Single best-effort POST with a 5-second timeout. We log every attempt and surface them in your dashboard (and via
GET /webhooks/deliveries, coming soon). - Idempotency: retries (when shipped) reuse the same
id. Treatidas the dedup key. - Respond with any 2xx status to acknowledge. Non-2xx responses are logged but do not block order processing.
Error handling
All errors return a consistent JSON structure. The code field is stable and machine-readable; error is human-readable and may change.
{
"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 the 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 (retry with Retry-After). |
| 422 | idempotency_conflict | Same Idempotency-Key used with a 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 the restaurant minimum. |
| 422 | restaurant_closed | Restaurant is currently closed. |
| 422 | outside_delivery_zone | Delivery address outside the restaurant range. |
| 402 | payment_declined | Payment could not be processed (card declined). |
| 429 | rate_limited | Too many requests. Check Retry-After header. |
SDKs & integrations
Don't want to write REST code? We ship two first-party clients on npm, and the OpenAPI spec generates idiomatic SDKs in any language.
@menami/mcp-server
Drop-in Model Context Protocol server. Works with Claude Desktop, Cursor, Windsurf, and any MCP-compatible agent. 7 tools for recommendations, booking, ordering, feedback.
npx @menami/mcp-server connect@menami/cli
Personal food agent for the terminal. Discover, recommend, book, order, all from the command line. Same auth identity (phone number) as the REST API and MCP server.
npm install -g @menami/cliFor language-specific SDKs (Go, Rust, Java, etc.), feed our OpenAPI spec into openapi-generator or your favorite codegen tool.
Versioning
We use URL versioning: /api/v1/agent/*. The current major version is v1.
- Additive changes (new fields, new endpoints, new optional params, new enum values) ship into
v1without notice. Treat the schema as forward-compatible: ignore fields you don't recognize. - Breaking changes (renamed fields, removed endpoints, semantic changes) ship as a new major version (
v2). We commit to running the previous major in parallel for at least 12 months after a new one is announced. - Deprecations are announced via email to every registered
contact_email, listed in the Changelog, and surfaced on affected endpoints via aDeprecationresponse header. - The OpenAPI spec is the source of truth. Lock to
api.menami.mx/openapi.yaml?v=1for stable codegen.
Pricing & quotas
During the v1 launch period the Agent Protocol is free to use for all registered partners. The economic model is per-order revenue share with the restaurant. Agents don't pay us; restaurants pay Menami a platform fee that's already baked into the totals you see (and into the Stripe split).
| Tier | Rate limit | Sitemap throughput | How to get it |
|---|---|---|---|
| Self-serve | 60 req/min | Default catalog scrape | POST /keys/register |
| Verified partner | 600 req/min | Bulk export available | partners@menami.mx |
| Enterprise | Custom | S3 dump + webhooks | partners@menami.mx |
Verified-partner tier
Verified-partner status unlocks 10× rate limits, a higher per-IP key registration cap, early access to roadmap endpoints (webhook delivery logs, S3 catalog export), and a direct Slack channel with engineering. Eligibility: a published product or research paper that uses our data, plus a stable contact channel. Email partners@menami.mx with your platform name, contact_email used in registration, and a sentence on what you're building.
Fair-use policy
We don't bill for API access, but we do throttle abusive patterns: repeated 4xx loops, scraping past the documented rate limits, registering many keys to circumvent limits, or unauthenticated catalog dumps faster than once per hour. If you need a higher ceiling, just ask. Almost every legitimate request gets approved.
Changelog
Material changes to the API surface. Additive entries are released without notice; breaking entries get a 12-month grace period (see Versioning).
- Webhooks. New
POST /webhooks/endpoints, signed HMAC-SHA256 delivery for allorder.*lifecycle events. Partners no longer need to poll. - Test mode. Self-serve
ak_test_*keys viamode: "test"on registration. Skip Stripe entirely while integrating. - Cursor pagination.
starting_afterplusnext_cursoronGET /restaurantsfor stable iteration. - Minor units everywhere. All monetary fields (
delivery_fee,min_order_amount,price,price_adjustment) now return integer minor units (cents/centavos). Breaking for any clients that were depending on major-unit decimals. The prior behavior is preserved on the deprecated/api/v0/agent/*shadow until 2027-05-28. - X-Request-Id. Every response now carries a correlation header. Send your own to thread context through your stack.
- Public launch.
/api/v1/agentopens for self-serve registration. - Indexing affordances.
GET /sitemap.json,updated_sincefilter, andschema_orgJSON-LD on restaurant detail. - OpenAPI 3.1 spec published at api.menami.mx/openapi.yaml.
Ready to integrate?
Get an API key and start building agent-powered ordering, search, or recommendations against 12,000+ restaurants.