/versionpublicAPI version (no key)
curl -sS "https://api.modr.se/v1/version"Partner API
Public REST API for partners: menu, Orderhanterare, open checks and closed sales per outlet. Authenticate with outlet API keys — not device JWTs or staff PINs.
All protected calls require a valid outlet key. Send either:
Authorization: Bearer modr_live_…or
Authorization: Bearer modr_test_…Alternative header:X-Api-Key: modr_test_…
Invalid or revoked keys return 401. Keys are stored hashed; prefix and last4 are shown in Backoffice.
Always call MODR Open API on api.modr.se. Live and test share the same host — the key prefix selects the environment. Use modr_test_ keys against a test outlet while developing.
https://api.modr.se/v1 — canonical base URLhttps://modr.se/api/v1 — same API via modr.semodr_test_ — sandbox / lower rate limitmodr_live_ — productionFixed window per minute per key. Exceeding the limit returns 429 with Retry-After.
modr_test_ — 60 req/min (default)modr_live_ — 120 req/min (default)Response headers: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset
POST and PUT accept an optional Idempotency-Key (8–128 characters). The same key and body replay the original response. The same key with a different body returns 409.
Idempotency-Key: 8f3c2a91-partner-order-14Optionally send X-Correlation-Id. The same value is returned and included in error payloads — use it when contacting support.
All paths are relative to the base URL above. POST /orders puts a waiting order in Orderhanterare. POST /checks creates an open POS check. GET /sales is cursor-paginated — pass nextCursor as cursor.
/versionpublicAPI version (no key)
curl -sS "https://api.modr.se/v1/version"/environmentKey environment and outlet binding
curl -sS "https://api.modr.se/v1/environment" \
-H "Authorization: Bearer modr_test_…"/productsPublished menu / catalog with modifiers
curl -sS "https://api.modr.se/v1/products" \
-H "Authorization: Bearer modr_test_…"/tablesTables and any open check
curl -sS "https://api.modr.se/v1/tables" \
-H "Authorization: Bearer modr_test_…"/checksList open POS checks
curl -sS "https://api.modr.se/v1/checks?limit=50" \
-H "Authorization: Bearer modr_test_…"/checksCreate open POS check (no payment)
curl -sS -X POST "https://api.modr.se/v1/checks" \
-H "Authorization: Bearer modr_test_…" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"name":"Online 1","tableId":"<tableId>","lines":[{"productId":"<id>","qty":1}]}'/checks/{id}Get one open check
curl -sS "https://api.modr.se/v1/checks/<checkId>" \
-H "Authorization: Bearer modr_test_…"/checks/{id}/itemsAdd items to an open check
curl -sS -X POST "https://api.modr.se/v1/checks/<checkId>/items" \
-H "Authorization: Bearer modr_test_…" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"lines":[{"productId":"<id>","qty":1}]}'/checks/{id}/tableAttach check to a table
curl -sS -X PUT "https://api.modr.se/v1/checks/<checkId>/table" \
-H "Authorization: Bearer modr_test_…" \
-H "Content-Type: application/json" \
-d '{"tableId":"<tableId>"}'/ordersCreate Orderhanterare waiting-queue order
curl -sS -X POST "https://api.modr.se/v1/orders" \
-H "Authorization: Bearer modr_test_…" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"name":"Wolt 14","orderType":"Takeaway","lines":[{"productId":"<id>","qty":1}]}'/ordersList Orderhanterare queue orders
curl -sS "https://api.modr.se/v1/orders?queue=waiting" \
-H "Authorization: Bearer modr_test_…"/salesClosed sales with lines, VAT and payments
curl -sS "https://api.modr.se/v1/sales?limit=50" \
-H "Authorization: Bearer modr_test_…"/sales/{id}Get one closed sale
curl -sS "https://api.modr.se/v1/sales/<saleId>" \
-H "Authorization: Bearer modr_test_…"Configure a public HTTPS URL and events in Backoffice. The first attempt is synchronous. Failed deliveries retry with backoff, up to 8 attempts. sale.created includes lines, VAT and payments.
check.createdcheck.updatedorder.createdsale.createdHeaders: X-Modr-Timestamp, X-Modr-Signature, X-Modr-Event
HMAC-SHA256 hex of{timestamp}.{rawBody} using the webhook secret.
# verify (pseudo)
expected = hmac_sha256(secret, timestamp + "." + rawBody)
assert expected == X-Modr-SignatureJSON errors use a consistent shape:
{
"code": "unauthorized",
"message": "Missing API key …",
"correlationId": "…"
}Pay/terminal, refunds, cash, Z/X/fiscal, staff PIN, device link and manager override are not part of Open API v1.