Skip to main content

Authentication

OrderUp's API supports two authentication paths. Pick the one that matches what you're building.

Two paths

PathWho uses itWhat you send
Cookie-based JWTOur own management and POS apps when running in a browser/web viewA signed cookie set by /api/v1/auth/login, transmitted automatically by the browser
API keyThird-party integrators, server-to-server clients, ISVsAn x-api-key header on every request, plus a tenant scope identifier

If you're writing server code that talks to the API on behalf of a tenant, you want the API key path. The cookie path only makes sense if you're embedding the management UI itself or scripting against your own browser session.

API key flow (third-party integrators)

Getting a key

API keys are issued per tenant by an OrderUp admin. To request one:

  1. Have your tenant's account manager open a support ticket on your behalf, or open it yourself if you're authorized to act on the tenant's behalf.
  2. Provide:
    • The tenant and restaurant(s) the key should access.
    • The integration name and a brief description (one or two sentences) of what it does.
    • The IP allowlist (recommended) for production traffic.
    • A point of contact for security notifications.
  3. Once issued, the key is shown to you once. Store it in your secrets manager (AWS Secrets Manager, GCP Secret Manager, HashiCorp Vault — anything that isn't a flat file in a git repo). We can't retrieve it for you later; if it's lost, we rotate.

A self-serve API-key issuance flow inside the management app is on the roadmap. Until it ships, the support-ticket path is canonical.

Required headers

Every request:

x-api-key: ouk_live_<your-key>

If your key is scoped to multiple restaurants, also send:

x-restaurant-guid: <restaurant-guid>

So a complete request looks like:

curl -X GET https://api.letsorderup.com/api/v1/restaurants/abc-123/orders \
-H "x-api-key: ouk_live_a1b2c3d4..." \
-H "x-restaurant-guid: abc-123"

Permissions

API keys carry a fixed permission scope set at issuance. Common scopes:

  • read:orders — list and read orders.
  • write:orders — create or update orders (used by ordering kiosks, marketplace integrations).
  • read:menu / write:menu — for menu sync tools.
  • read:reports — for accounting/BI integrations.

If your application calls an endpoint outside its scope, you'll get a 403 FORBIDDEN. Request a wider scope through the same support process.

Rotation

Rotate keys on any of the following:

  • A team member with key access leaves.
  • You suspect a key was exposed (committed to a public repo, leaked in a log).
  • It's been more than 12 months since the last rotation (this is our recommendation, not an enforced expiry — but get into the habit).

To rotate:

  1. Request a new key. The old key keeps working.
  2. Roll the new key out across your infrastructure.
  3. Verify all your services are using the new key.
  4. Ask us to revoke the old key.

We can also generate a new key with a configurable overlap window (typically 7 days) so you have a clean swap window.

If you're building a web client that holds a user session — the management app, the POS web shell — authenticate with the user's email and password (or SSO) and let the cookie do the work.

# Login
curl -X POST https://api.letsorderup.com/api/v1/auth/login \
-H "Content-Type: application/json" \
-c cookies.txt \
-d '{"email":"manager@example.com","password":"..."}'

# Subsequent calls use the cookie
curl https://api.letsorderup.com/api/v1/restaurants/abc-123/orders \
-b cookies.txt

The cookie is httpOnly and Secure — JavaScript can't read it, and it only travels over HTTPS. Your browser handles it transparently after login.

Token lifetimes:

  • Access cookie: short-lived (15 minutes).
  • Refresh cookie: longer-lived (30 days, sliding).

The server refreshes silently on requests that come in close to access-token expiry, so well-behaved clients don't usually need to do anything special. If you hit a 401 on a previously-working session, call /api/v1/auth/refresh — that's the explicit path back to a fresh access token.

To log out: POST /api/v1/auth/signout. This endpoint is intentionally public — it does not require a valid session, so a browser whose access cookie already expired can still complete the sign-out instead of getting a 401 that leaves the stale cookie in place. It always clears the session cookie; refresh-token revocation (which is what invalidates the session on other devices and on OrderUp's other domains) happens on a best-effort basis and only when a valid session was presented. The client should also discard any locally-cached session state.

Multi-factor authentication

User-account logins (cookie path) support TOTP-based MFA. If a user has MFA enabled, the login endpoint returns a challenge:

{
"success": false,
"error": {
"code": "MFA_REQUIRED",
"message": "Multi-factor authentication required",
"details": { "challengeId": "..." }
}
}

Submit the second factor at /api/v1/auth/mfa/verify with the challenge ID and the 6-digit code. On success you get the cookies back as if you had logged in normally.

API keys do not use MFA — they are themselves the credential. Keep them in a secrets manager and rotate.

Webhooks

Webhook signatures are a related but separate topic. If your integration receives webhooks from OrderUp, see the webhook signing-key documentation in the route reference for the relevant endpoint. Webhook payloads are signed with HMAC-SHA256 over the raw body — verify the signature before trusting any payload, and reject unsigned or stale (>5 min old) requests.

Security checklist before you go to production

  • API key stored in a secrets manager, not a config file.
  • IP allowlist configured if traffic comes from known addresses.
  • Logs scrub the x-api-key header.
  • Rotation procedure documented and tested.
  • On-call contact for security incidents on file with us.
  • Webhook signatures verified on every incoming webhook.