Menuraq Developer API v1

Production API Docs for Menuraq Integrations

Build secure integrations with business-scoped keys, strict scope checks, rate limiting, and traceable request IDs. Use this page as your complete endpoint reference plus in-browser request tester.

Base URL

https://menuraq.com

Version

/api/v1

Auth

Bearer or x-api-key

Authentication

Use API key auth for `/api/v1` endpoints.

Supported headers:

Authorization: Bearer <api_key>
x-api-key: <api_key>

Dashboard key-management endpoints (`/api/developer-keys/*`) use signed-in dashboard session tokens.

Quickstart

Fast path to first request.

1. Enable 2FA in Dashboard Settings.

2. Create API key in Dashboard Settings -> Developer API.

3. Grant minimal scopes, then call `/api/v1/business`.

curl -H "Authorization: Bearer $MNRQ_API_KEY" \
  "https://menuraq.com/api/v1/business"

API Playground

Test endpoints directly from your browser. Your API key is only used in this request and is not persisted.

Scope Model

read:all

Wildcard read access across all read endpoints.

read:business

Business profile and business-level stats.

read:branches

Branch listings and branch metadata.

read:menus

Menus and menu detail payloads.

read:menu-items

Menu item listings.

write:menu-items

Menu item updates (PATCH).

read:analytics

Analytics totals and date windows.

read:promotions

Promotion listings and detail views.

read:templates

Template render access (iframe/html).

API Key Management Endpoints

GET/api/developer-keysDashboard JWTScope: dashboard-user-session

List API keys for businesses owned by the signed-in account.

Returns keys with prefix, scopes, expiry, usage timestamps, and creation metadata for your businesses.

Query Params

NameTypeRequiredDescription
businessIduuidNoFilter keys by one business.

Notes

  • - Requires signed-in dashboard user session.
  • - 2FA must be enabled to access Developer API management UI.
curl -H "Authorization: Bearer $DASHBOARD_JWT" \
  "https://menuraq.com/api/developer-keys?businessId=<uuid>"

Response Example

{
  "ok": true,
  "keys": [{
    "id": "a4f...",
    "name": "Production Mobile",
    "key_prefix": "mnrq_live_a1b2c3d4",
    "scopes": ["read:business", "read:menus"],
    "rate_limit_per_minute": 120
  }]
}
POST/api/developer-keysDashboard JWTScope: dashboard-user-session

Create a new API key and reveal plaintext once.

Creates a business-scoped key with least-privilege scopes. Plaintext secret is only returned in this response.

Body Params

NameTypeRequiredDescription
businessIduuidYesTarget business ID.
namestringYesReadable key name shown in dashboard.
scopesstring[]NoRequested scopes.
expiresAtdatetimeNoExact expiration timestamp.
expiresInDaysintegerNoRelative expiration in days.
currentPasswordstringNoPassword confirmation for password-based accounts.

Notes

  • - A maximum of 3 active API keys is allowed per business.
  • - Menuraq enforces secure default rate limiting server-side.
curl -X POST \
  -H "Authorization: Bearer $DASHBOARD_JWT" \
  -H "Content-Type: application/json" \
  -d '{"businessId":"<uuid>","name":"Android app","scopes":["read:business","read:menus"]}' \
  "https://menuraq.com/api/developer-keys"

Response Example

{
  "ok": true,
  "key": { "id": "a4f...", "key_prefix": "mnrq_live_a1b2c3d4" },
  "apiKey": "mnrq_live_a1b2c3d4_...",
  "warning": "Store this API key now. Menuraq will not show it again."
}
POST/api/developer-keys/:id/rotateDashboard JWTScope: dashboard-user-session

Rotate one key and issue a replacement secret.

Invalidates previous key hash and returns a new plaintext key once.

Path Params

NameTypeRequiredDescription
iduuidYesAPI key ID to rotate.

Body Params

NameTypeRequiredDescription
currentPasswordstringNoPassword confirmation for password-based accounts.
curl -X POST \
  -H "Authorization: Bearer $DASHBOARD_JWT" \
  -H "Content-Type: application/json" \
  -d '{"currentPassword":"<password>"}' \
  "https://menuraq.com/api/developer-keys/<id>/rotate"

Response Example

{
  "ok": true,
  "key": { "id": "a4f...", "key_prefix": "mnrq_live_9f8e7d6c" },
  "apiKey": "mnrq_live_9f8e7d6c_..."
}
POST/api/developer-keys/:id/secretDashboard JWTScope: dashboard-user-session

Reveal existing secret after password confirmation.

Shows decrypted API key for already-issued keys using secure storage.

Path Params

NameTypeRequiredDescription
iduuidYesAPI key ID to reveal.

Body Params

NameTypeRequiredDescription
currentPasswordstringYesAccount password.
curl -X POST \
  -H "Authorization: Bearer $DASHBOARD_JWT" \
  -H "Content-Type: application/json" \
  -d '{"currentPassword":"<password>"}' \
  "https://menuraq.com/api/developer-keys/<id>/secret"

Response Example

{
  "ok": true,
  "key": { "id": "a4f...", "name": "Production Mobile", "key_prefix": "mnrq_live_a1b2c3d4" },
  "apiKey": "mnrq_live_a1b2c3d4_..."
}
DELETE/api/developer-keys/:idDashboard JWTScope: dashboard-user-session

Permanently delete one API key.

Removes key record and immediately blocks future usage.

Path Params

NameTypeRequiredDescription
iduuidYesAPI key ID to delete.
curl -X DELETE \
  -H "Authorization: Bearer $DASHBOARD_JWT" \
  "https://menuraq.com/api/developer-keys/<id>"

Response Example

{
  "ok": true,
  "deleted": true
}
GET/api/developer-keys/:id/usageDashboard JWTScope: dashboard-user-session

Get usage summary and per-request logs for one key.

Returns aggregate counts and recent request-level logs for observability.

Path Params

NameTypeRequiredDescription
iduuidYesAPI key ID.

Query Params

NameTypeRequiredDescription
date_fromYYYY-MM-DDNoWindow start date.
date_toYYYY-MM-DDNoWindow end date.
limit1..500NoLog row limit.
curl -H "Authorization: Bearer $DASHBOARD_JWT" \
  "https://menuraq.com/api/developer-keys/<id>/usage?limit=100"

Response Example

{
  "ok": true,
  "usage": {
    "total_requests": 982,
    "window_count": 100,
    "summary": { "success_count": 97, "error_count": 3 }
  }
}

Public Data Endpoints

GET/api/v1/businessAPI KeyScope: read:business

Get business profile and top-level stats.

Returns business identity data plus aggregate menu/branch/promotion counts.

curl -H "Authorization: Bearer $MNRQ_API_KEY" \
  "https://menuraq.com/api/v1/business"

Response Example

{
  "ok": true,
  "request_id": "89ff...",
  "data": {
    "business": { "id": "b1...", "name": "Blue Olive" },
    "stats": { "menus": 4, "branches": 3, "active_promotions": 2 }
  }
}
GET/api/v1/branchesAPI KeyScope: read:branches

List branch records for the current business.

Returns branches with status and summary fields.

Query Params

NameTypeRequiredDescription
include_inactivebooleanNoInclude inactive branches in results.
curl -H "Authorization: Bearer $MNRQ_API_KEY" \
  "https://menuraq.com/api/v1/branches?include_inactive=false"

Response Example

{
  "ok": true,
  "data": [
    { "id": "br1...", "name": "Airport", "menu_count": 1 },
    { "id": "br2...", "name": "Downtown", "menu_count": 1 }
  ]
}
GET/api/v1/menusAPI KeyScope: read:menus

List menus with pagination and status filters.

Supports pagination and optional inclusion of items per menu.

Query Params

NameTypeRequiredDescription
limitintegerNoMax rows to return.
offsetintegerNoPagination offset.
statuslive|draftNoStatus filter.
include_itemsbooleanNoInclude menu items in each menu record.
curl -H "Authorization: Bearer $MNRQ_API_KEY" \
  "https://menuraq.com/api/v1/menus?limit=20&offset=0&status=live"

Response Example

{
  "ok": true,
  "data": [{ "id": "m1...", "title": "Main Menu", "item_count": 42 }],
  "pagination": { "total": 1, "limit": 20, "offset": 0, "has_more": false }
}
GET/api/v1/menus/:menuIdAPI KeyScope: read:menus

Get one menu with categories and items.

Optionally include analytics when key has analytics scope.

Path Params

NameTypeRequiredDescription
menuIduuidYesMenu ID.

Query Params

NameTypeRequiredDescription
include_analyticsbooleanNoInclude analytics payload when scope allows.
curl -H "Authorization: Bearer $MNRQ_API_KEY" \
  "https://menuraq.com/api/v1/menus/<menuId>?include_analytics=true"

Response Example

{
  "ok": true,
  "data": {
    "id": "m1...",
    "categories": [{ "id": "c1...", "name": "Starters" }],
    "items": [{ "id": "i1...", "title": "Fried Rice" }]
  }
}
GET/api/v1/menu-itemsAPI KeyScope: read:menu-items

List menu items with filtering and pagination.

Filter by menu, category, availability, then paginate.

Query Params

NameTypeRequiredDescription
menu_iduuidNoFilter to one menu.
category_iduuidNoFilter to one category.
availablebooleanNoFilter available items.
limitintegerNoMax rows.
offsetintegerNoPagination offset.
curl -H "Authorization: Bearer $MNRQ_API_KEY" \
  "https://menuraq.com/api/v1/menu-items?menu_id=<menuId>&available=true"

Response Example

{
  "ok": true,
  "data": [{ "id": "i1...", "title": "Spicy Shrimp", "price": 21.5 }],
  "pagination": { "total": 14, "limit": 50, "offset": 0, "has_more": false }
}
PATCH/api/v1/menu-items/:itemIdAPI KeyScope: write:menu-items

Update one menu item using allow-listed fields.

Mutates one menu item in the key business scope only.

Path Params

NameTypeRequiredDescription
itemIduuidYesItem ID.

Body Params

NameTypeRequiredDescription
titlestringNoItem title.
descriptionstring|nullNoItem description.
pricenumberNoPrice value.
availablebooleanNoAvailability flag.
tagsstring[]NoTag list.
available_Daysstring[]NoWeekly availability days.
available_Times{start,end}|nullNoTime-window availability block.
curl -X PATCH \
  -H "Authorization: Bearer $MNRQ_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"title":"Spicy Chicken Deluxe","price":18.5,"available":true}' \
  "https://menuraq.com/api/v1/menu-items/<itemId>"

Response Example

{
  "ok": true,
  "request_id": "9ab2...",
  "data": { "id": "i1...", "title": "Spicy Chicken Deluxe", "price": 18.5 }
}
GET/api/v1/analyticsAPI KeyScope: read:analytics

Get aggregate analytics for configured date windows.

Returns totals, per-menu series, and optional daily details.

Query Params

NameTypeRequiredDescription
menu_iduuidNoFilter to one menu.
date_fromYYYY-MM-DDNoWindow start date.
date_toYYYY-MM-DDNoWindow end date.
include_dailybooleanNoInclude day-level rows in output.
curl -H "Authorization: Bearer $MNRQ_API_KEY" \
  "https://menuraq.com/api/v1/analytics?date_from=2026-01-01&date_to=2026-01-31"

Response Example

{
  "ok": true,
  "data": {
    "totals": { "views": 3242, "scans": 991, "downloads": 122, "shares": 63 },
    "by_menu": [{ "menu_id": "m1...", "views": 3242 }]
  }
}
GET/api/v1/promotionsAPI KeyScope: read:promotions

List promotions with activity and menu filters.

Returns promotion rows in business scope, optionally active-only.

Query Params

NameTypeRequiredDescription
menu_iduuidNoFilter by menu.
active_onlybooleanNoOnly active promotions.
limitintegerNoMax rows.
offsetintegerNoPagination offset.
curl -H "Authorization: Bearer $MNRQ_API_KEY" \
  "https://menuraq.com/api/v1/promotions?active_only=true"

Response Example

{
  "ok": true,
  "data": [{ "id": "p1...", "title": "Happy Hour", "is_active": true }]
}
GET/api/v1/promotions/:promotionIdAPI KeyScope: read:promotions

Get one promotion detail in tenant scope.

Returns one promotion object by ID.

Path Params

NameTypeRequiredDescription
promotionIduuidYesPromotion ID.
curl -H "Authorization: Bearer $MNRQ_API_KEY" \
  "https://menuraq.com/api/v1/promotions/<promotionId>"

Response Example

{
  "ok": true,
  "data": { "id": "p1...", "title": "Happy Hour", "discount_type": "percentage" }
}
GET/api/v1/templates/renderAPI KeyScope: read:templates

Get menu template render as iframe metadata or raw HTML.

Supports menu selector, mode selection, and header visibility control for embeds.

Query Params

NameTypeRequiredDescription
menu_iduuidNoTarget menu ID (one of menu_id/menu_slug).
menu_slugstringNoTarget menu slug (one of menu_id/menu_slug).
modeiframe|htmlNoRender output mode.
hide_headerbooleanNoWhen true, public URL adds embed mode and hides the /m page header.

Notes

  • - When mode=iframe, hide_header defaults to true unless explicitly disabled.
curl -H "Authorization: Bearer $MNRQ_API_KEY" \
  "https://menuraq.com/api/v1/templates/render?menu_slug=main-menu&mode=iframe&hide_header=true"

Response Example

{
  "ok": true,
  "data": {
    "mode": "iframe",
    "public_url": "https://menuraq.com/m/main-menu?embed=1",
    "presentation": { "hide_header": true },
    "embed_code": "<iframe src=\"...\"></iframe>"
  }
}

HTTP Status Codes

200

Successful request.

201

Resource created.

400

Invalid payload or query parameters.

401

Missing/invalid credentials or API key.

403

Insufficient scope or unauthorized access.

404

Resource not found in tenant scope.

409

Conflict (for example max keys reached).

429

Rate limit exceeded.

500

Internal server error.

503

Service not configured in environment.

Production checklist

Set `DEVELOPER_API_KEY_PEPPER`, set `DEVELOPER_API_KEY_ENCRYPTION_SECRET`, rotate keys, keep scopes least-privilege, and monitor request logs in Dashboard Settings.