WakaStart
Using the API

API Usage — Headers & Rate Limits

Required and optional headers, idempotency, CORS, rate limiting and exponential backoff.

Version v1.03 min read

API Usage — Headers & Rate Limits

This chapter covers HTTP headers, CORS rules and throttling. Read REST Conventions first.


Required headers

Frontend calls (Bearer + enriched)

http
Authorization: Bearer <keycloak_access_token> x-enriched-token: <wakastart_token> Content-Type: application/json

Backend calls (API Key)

http
x-api-key: sk_live_... Content-Type: application/json

Optional headers

HeaderDescription
Accept-LanguagePreferred language for error messages (fr, en).

No x-trace-id/x-request-id: these headers are not implemented to date (no occurrence on public-api, backend-for-front, or discovery). For a support incident, provide the timestamp, the route called, and the error response body.


CORS

The WakaStart API supports CORS for registered origins. The rules:

  • Allowed origins: configured in ALLOWED_ORIGINS on the API side.
  • Credentials: Access-Control-Allow-Credentials: true — HttpOnly cookies are transmitted.
  • Methods: GET, POST, PUT, PATCH, DELETE, OPTIONS.
  • Exposed headers: Retry-After.

Direct calls from the browser: if your frontend calls the API without a proxy, the wakastart_token cookie is HttpOnly and inaccessible from JavaScript. You cannot pass x-enriched-token from the browser without a proxy. Always use a server-side proxy.


Idempotency

GET, PUT, and DELETE operations are idempotent. For POST:

  • Invitation creation: if a PENDING invitation already exists for the same email + Customer, the API responds 409 Conflict. It is safe to retry after a network failure.
  • Enrichment: /api/auth/enrich is idempotent for the same access_token within its validity period.
  • Token refresh: /api/auth/token/refresh generates a new token on every call. Do not call it in parallel.

Rate limiting

The API applies three levels of throttling:

LevelTTLLimitDescription
Short1,000 ms10 reqImmediate anti-burst
Medium60,000 ms100 reqPer-minute limit
Long3,600,000 ms1,000 reqPer-hour limit

Endpoint-specific limits

EndpointLimit
POST /discover/start-login5/60s · 20/600s (10 min) · 100/3600s (1 h)
POST /api/auth/enrichNot limited on the BFF side (no guard/throttler on this route)
POST /api/auth/logoutNot limited on the BFF side (no guard/throttler on this route)
POST /api/auth/token/refresh10/min (default of the BFF's ThrottlerModule, no specific rule)
GET /api/invitations/verify/:token10/min/IP
POST /api/invitations/accept/:token5/min/IP
POST /api/mcp10/min

429 Response:

json
{ "statusCode": 429, "message": "Too Many Requests" }

The Retry-After header indicates the wait time in seconds.


Exponential backoff

typescript
async function fetchWithRetry( url: string, options: RequestInit, maxRetries = 3 ): Promise<Response> { for (let attempt = 0; attempt < maxRetries; attempt++) { const res = await fetch(url, options); if (res.status !== 429) return res; const retryAfter = parseInt(res.headers.get("Retry-After") ?? "1", 10); const delay = retryAfter * 1000 * Math.pow(2, attempt); await new Promise(r => setTimeout(r, delay)); } throw new Error("Rate limit exceeded after retries"); }

Checking rights from your backend

http
POST /api/token/authorize x-api-key: sk_live_... Content-Type: application/json { "token": "eyJ...", "checks": { "adminLevel": { "requiredLevel": "CustomerAdmin" }, "roles": { "roles": ["CONFIG"], "mode": "any" }, "appRights": { "rights": ["users.create"], "mode": "all" } } }
json
{ "authorized": true, "details": { "adminLevel": { "hasLevel": true, "actualLevel": "NetworkAdmin" }, "roles": { "hasRoles": true, "matchedRoles": ["CONFIG"] }, "appRights": { "hasRights": true, "missingRights": [] } } }

Best practices

  • Headers don't stack: a call with both x-api-key AND Authorization: Bearer will see the API key take precedence.
  • Log the error response body on 5xx (route, method, statusCode, message): in the absence of x-request-id, this is what lets support find the incident.
  • Respect Retry-After: don't ignore this header, it protects the API's stability.

Common pitfalls

  • Parallel calls to refresh: if several requests expire at the same time and all attempt a simultaneous refresh, only one succeeds. Implement a client-side mutex.
  • Rate limit on tests: in CI, a batch of tests can trigger the short-duration rate limit. Add delays between integration tests.

Go further