Rate limits¶
Limits apply per client_id and per IP. The stricter of the two wins.
Defaults¶
| Endpoint | Public client | Confidential client | Anonymous IP |
|---|---|---|---|
/oidc/authorize | 1 000 / hour | 10 000 / hour | 200 / hour |
/oidc/token | 1 000 / hour | 10 000 / hour | 200 / hour |
/oidc/userinfo | 5 000 / hour | 50 000 / hour | n/a |
/oidc/revoke | 100 / hour | 1 000 / hour | 50 / hour |
/oidc/introspect | n/a | 50 000 / hour | n/a |
/oidc/onetap (iframe) | 60 / minute / IP | 60 / minute / IP | 60 / minute / IP |
/oidc/iframe/check_session | 120 / minute / IP | 120 / minute / IP | 120 / minute / IP |
/.well-known/* | uncapped (cached) | uncapped (cached) | uncapped (cached) |
/sdk.js | uncapped (cached) | uncapped (cached) | uncapped (cached) |
Headers¶
Every response includes:
http X-RateLimit-Limit: 1000 X-RateLimit-Remaining: 942 X-RateLimit-Reset: 1714684800
When throttled, you get:
http HTTP/1.1 429 Too Many Requests Retry-After: 47 X-RateLimit-Reset: 1714684847
with body:
json { "error": "lxl_rate_limited", "error_description": "Hourly cap exceeded for /oidc/token" }
Raising your limits¶
Apply through the developer portal — pick the client, Settings → Rate limits → Request increase. Provide:
- Expected sustained QPS.
- Endpoint(s).
- Brief justification (use case).
We approve in business hours. Burst allowance is configurable separately.
Best practices¶
- Cache
/oidc/userinfofor the duration of the access token. It rarely changes. - Honor
Retry-After. Implement exponential backoff with jitter; don't hammer. - Use webhooks instead of polling for account state changes.
- Reuse the discovery document — it's cacheable.