Skip to content
Help

Authentication

Creating scoped API keys, using them, and revoking them.

Public API2 min read

#Creating a key

Settings → Developers → Create key in the dashboard. You need the restaurant:write permission, which owners and admins have.

A key is defined by:

  • Name — for you, so you know what to revoke later.
  • Scopes — exactly what the key may do. Pick the minimum.
  • Branches — leave every branch unchecked for restaurant-wide access, or tick specific branches to fence the key to them.
  • Expires in — pick a window, or never. A key with an expiry stops working on its own, which is the right default for a contractor.

When you create the key, Restro shows the token once:

text
rk_a1b2c3d4e5f60718_Zm9vYmFyYmF6cXV4Y29ycmVjdGhvcnNlYmF0dGVyeQ

Copy it then. Restro stores only a SHA-256 hash of the secret, so nobody — including us — can show it to you again. Lose it and you create a new key.

#Using a key

Send it as a bearer token:

bash
curl https://api.tryrestro.com/v1/me \
  -H "Authorization: Bearer rk_a1b2c3d4e5f60718_..."

Or, if your HTTP client makes bearer tokens awkward:

bash
curl https://api.tryrestro.com/v1/me \
  -H "X-API-Key: rk_a1b2c3d4e5f60718_..."

Both are equivalent. Never put a key in a URL, in client-side code, or in a mobile app — it is a server-side credential.

#Scopes

ScopeGrants
orders:readList and fetch orders
orders:update-statusAdvance or cancel an order
menu:readList categories and items
menu:writeUpdate item publication, availability, and branch prices
customers:readList and fetch customers
inventory:readList and fetch stock
inventory:writeRecord stock movements

Scopes are drawn from the same permission vocabulary the dashboard uses for staff, so a scope means the same thing whichever side of the product you are on.

Calling an endpoint without its scope returns 403:

json
{ "error": "Missing required scope: menu:write", "code": "forbidden" }

#Checking a key

GET /v1/me tells you what the key can do without changing anything. It needs no particular scope, so it is the right first call from a new integration.

json
{
  "key": {
    "id": "cmd8x2k9p0001abcdefghijkl",
    "name": "Accounting sync",
    "prefix": "a1b2c3d4e5f60718",
    "scopes": ["orders:read", "customers:read"],
    "branchIds": []
  },
  "restaurant": {
    "id": "cmd8w1j8o0000abcdefghijkl",
    "name": "Broccar",
    "subdomain": "broccar"
  }
}

An empty branchIds means the key is not branch-restricted.

#Branch scoping

A branch-scoped key sees only those branches. Orders elsewhere return 404 rather than 403 — the key cannot confirm the order exists, which is the correct answer to give something that is not allowed to know.

Requesting a branch outside the key's scope via ?branchId= returns 403.

#Revoking

Settings → Developers. Revoke stops the key working immediately and keeps it in the list for the record. Delete removes it entirely.

Revoke rather than delete when you are cutting off an integration you may need to explain later — the activity log entries still point at the key by name.

Revoked and expired keys return 401:

json
{ "error": "API key is revoked or expired", "code": "key_inactive" }

#Rotating a key

There is no in-place rotation, deliberately. Create the new key, deploy it, confirm traffic has moved by watching last used on both keys, then revoke the old one. That sequence has no window where nothing works.

Did this page miss something? Tell us.

Back to top