Middleware & Policies
Rate Limiting
Section titled “Rate Limiting”Rate limits are enforced per-tenant using a Redis sliding window counter.
| Scope | Window | Limit |
|---|---|---|
| Authenticated requests | 60 seconds | 300 per tenant |
| Unauthenticated requests | 60 seconds | 30 per IP |
Rate limit headers are included on every authenticated response:
X-RateLimit-Limit: 300X-RateLimit-Remaining: 285X-RateLimit-Reset: 1738900860When the limit is exceeded, the API returns 429 Too Many Requests with a Retry-After header indicating seconds until the next window.
Request Tracing
Section titled “Request Tracing”Every request receives a unique request ID for distributed tracing:
- If the client sends an
X-Request-Idheader, the server uses that value - Otherwise, the server generates
req_{ULID}(e.g.,req_01ARZ3NDEKTSV4RRFFQ69G5FAV) - The request ID appears in the response
X-Request-Idheader and in theinstancefield of all error responses
Idempotency
Section titled “Idempotency”POST endpoints that create resources accept an optional Idempotency-Key header (UUID). Duplicate requests with the same key return the stored response without re-executing. Keys are stored for 24 hours.
PUT, DELETE, and GET are naturally idempotent.
| Setting | Value |
|---|---|
| Allowed origins | Configurable via AKILI_CORS_ORIGINS env var |
| Allowed methods | GET, POST, PUT, PATCH, DELETE, OPTIONS |
| Allowed headers | Authorization, Content-Type, X-Request-Id, X-Tenant-Id |
| Exposed headers | X-Request-Id, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset |
| Max age | 3600 seconds |
| Credentials | true |