API referenceOverview

API overview

ExaRoutes exposes a REST API at https://api.exaroutes.com. All endpoints accept and return JSON. Authentication uses workspace-level API keys.

Base URL

https://api.exaroutes.com

For staging:

https://api.staging.exaroutes.com

Authentication

Pass your API key in the Authorization header:

curl https://api.exaroutes.com/api/qr/codes \
  -H "Authorization: Bearer exr_live_..."

See Authentication for full details on key scopes and rotation.

The QR endpoints accept the full design surface (shapes, gradients, per-eye colors, logos, and error correction). See the QR styling request body.

Rate limits

ExaRoutes applies two distinct kinds of throttle:

Per-IP request limits (express-rate-limit)

Hard caps to keep a single IP from blowing up the service. Apply to every caller (anonymous, cookie-authed, or API-key-authed). Limit + window vary per route. The most-asked-about ones:

RouteLimitWindow
POST /api/auth/login20 failed attempts15 min
POST /api/auth/register31 hour
POST /api/auth/step-up515 min
POST /api/mfa/verify1015 min
GET /r/:shortId (QR scan)6001 min
POST /api/forms/.../submissions301 min
POST /api/verify/serial601 min
GET /v/:itemId/:signature601 min
POST /api/webhook/dodo601 min
POST /api/ai/...301 hour
Public free QR generator101 day
GET /api/qr/render/:shortId (signed download links)601 min

Headers on rate-limited responses follow the draft-7 standard: RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset, plus Retry-After on 429s.

Per-plan quotas (usage middleware)

Daily / monthly / lifetime caps tied to your subscription’s plan tier (apiCalls, dynamicQr, bulkOrders, etc.). Hitting one returns a 429 with X-ExaRoutes-Error-Code: PLAN_LIMIT_REACHED and a body indicating which capability tripped:

{
  "error": "Daily QR generation limit reached for the qr.starter plan.",
  "code": 429,
  "exaroutesErrorCode": "PLAN_LIMIT_REACHED"
}

Plan limits are documented per tier on the pricing page.

Per-key request rate

Every Bearer-authenticated endpoint is also throttled per subscription (all of a subscription’s keys share one bucket, so a leaked key spread across many IPs cannot multiply it). Requests per second by plan: Free 5, Starter 10, Growth 30, Business 100, Enterprise 500. Rate-limited responses carry the same draft-7 headers as above.

What’s NOT yet implemented

  • Per-key scopes (keys currently carry a scopes field but all keys have full access to their subscription’s products).

Versioning

The API is currently unversioned. Breaking changes will be announced via the changelog with a six-month deprecation window once we go GA.