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 er_live_..."

See Authentication for full details on key scopes and rotation.

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/login515 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

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.

What’s NOT yet implemented

  • Per-API-key rate limits (today, throttling is per-IP). Tracked for V11.
  • Per-workspace bulk-job throttling (today, bulk jobs share the per-IP limit). Tracked for V11.

Versioning

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