API Overview
Base URL
The Cerberus IAM API base URL is configured via the ISSUER_URL environment variable.
Default (development): http://localhost:4000
Production: Set via your deployment configuration
API Versioning
Authentication endpoints are versioned:
- Current version:
/v1 - OAuth2/OIDC endpoints:
/oauth2(spec-compliant, no version prefix) - Well-known endpoints:
/.well-known(spec-compliant)
Authentication Methods
1. Session-Based Authentication (Cookie)
Used for web applications and admin interfaces.
Cookie Name: cerb_sid (configurable via SESSION_COOKIE_NAME)
How to authenticate:
- Call
POST /v1/auth/loginwith credentials - Server sets HttpOnly session cookie
- Include cookie in subsequent requests
Security:
- HttpOnly flag prevents JavaScript access
- Secure flag enforced in production
- SameSite=Lax for CSRF protection
- CSRF token required for state-changing operations
2. Bearer Token Authentication (OAuth2)
Used for API clients and third-party integrations.
How to authenticate:
- Complete OAuth2 authorization flow
- Exchange authorization code for access token
- Include token in Authorization header:
Authorization: Bearer <access_token>Token types:
- Access Token: Short-lived JWT (default expiry varies by client configuration)
- Refresh Token: Long-lived opaque token (optional, requires
offline_accessscope)
3. Client Credentials
Used for machine-to-machine authentication.
Methods supported:
client_secret_basic: HTTP Basic Authenticationclient_secret_post: Credentials in request bodynone: Public clients (no secret required)
Common Headers
Required Headers
X-Org-Domain
Required for: Tenant-scoped admin APIs such as /v1/admin/*
Description: Identifies the organisation context for the request. Each organisation has a unique slug assigned during registration.
Example:
X-Org-Domain: acme-corpWhen not required:
- OAuth2/OIDC endpoints (organisation derived from client/token)
- Public endpoints (registration, password reset)
/v1/me/*routes (tenant inferred from the authenticated session)
Optional Headers
Authorization
OAuth2 bearer token for API authentication.
Authorization: Bearer eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCJ9...X-CSRF-Token
Required for state-changing operations when using session authentication.
X-CSRF-Token: <csrf_token>Content-Type
Always use application/json for request bodies.
Content-Type: application/jsonResponse Format
Success Responses
All successful responses return JSON with appropriate HTTP status codes:
Single resource:
{
"id": "usr_abc123",
"email": "[email protected]",
"name": "John Doe"
}Collection:
{
"data": [
{ "id": "usr_abc123", "email": "[email protected]" },
{ "id": "usr_xyz789", "email": "[email protected]" }
],
"total": 2
}Operation success:
{
"message": "Operation completed successfully"
}Status Codes
| Code | Description |
|---|---|
| 200 | OK - Request succeeded |
| 201 | Created - Resource created successfully |
| 204 | No Content - Request succeeded, no content to return |
| 400 | Bad Request - Invalid input or malformed request |
| 401 | Unauthorized - Authentication required or failed |
| 403 | Forbidden - Insufficient permissions |
| 404 | Not Found - Resource does not exist |
| 409 | Conflict - Resource conflict (e.g., duplicate email) |
| 422 | Unprocessable Entity - Semantic validation errors |
| 429 | Too Many Requests - Rate limit exceeded |
| 500 | Internal Server Error - Unexpected server error |
Error Responses
All errors follow RFC 7807 Problem Details format. See errors.md for complete documentation.
Example:
{https://api.cerberus-iam.com
"type": "https://cerberus.local/errors/bad-request",
"title": "Bad Request",
"status": 400,
"detail": "Invalid email format"
}Rate Limiting
The API implements rate limiting to prevent abuse.
Default limits:
- General endpoints: 120 requests per 60 seconds
- Authentication endpoints: 30 requests per 60 seconds
- Token endpoint: 30 requests per 60 seconds
Configuration:
RATE_WINDOW_SEC/RATE_MAX: General rate limitsAUTH_RATE_WINDOW_SEC/AUTH_RATE_MAX: Auth endpointsTOKEN_RATE_WINDOW_SEC/TOKEN_RATE_MAX: Token endpoint
Rate limit headers: When a limit is hit the response includes a Retry-After header (seconds until the window resets) and an RFC 7807 error body. No X-RateLimit-* headers are emitted today.
Pagination
Collection endpoints that support pagination use the following query parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
page | integer | 1 | Page number (1-indexed) |
limit | integer | 50 | Items per page (max 100) |
sort | string | - | Sort field (prefix with - for descending) |
Example:
GET /v1/admin/users?page=2&limit=25&sort=-createdAtResponse:
{
"data": [...],
"total": 150,
"page": 2,
"limit": 25,
"pages": 6
}CORS
Cross-Origin Resource Sharing (CORS) is configured via environment variables:
ADMIN_WEB_ORIGIN: Allowed origin for admin web applicationADMIN_WEB_INTERNAL_ORIGIN: Internal origin (for server-to-server)
Development: http://localhost:3000 is allowed by default
Security Headers
The API includes the following security headers via Helmet:
Strict-Transport-Security: HTTPS enforcementX-Content-Type-Options: nosniff: Prevent MIME sniffingX-Frame-Options: DENY: Prevent clickjackingX-XSS-Protection: 1; mode=block: XSS protectionContent-Security-Policy: Restrict resource loading
Request ID Tracing
Every request is assigned a unique request ID for tracing and debugging.
Header: X-Request-Id
Example:
X-Request-Id: req_1234567890abcdefThis ID is included in all log entries and can be used to trace a request through the system.
API Clients
JavaScript/TypeScript
const response = await fetch('http://localhost:4000/v1/auth/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
email: '[email protected]',
password: 'SecurePass123!',
}),
credentials: 'include', // Include cookies
});
const data = await response.json();cURL
curl -X POST http://localhost:4000/v1/auth/login \
-H "Content-Type: application/json" \
-d '{
"email": "[email protected]",
"password": "SecurePass123!"
}' \
-c cookies.txt # Save cookies