API Reference
The Auris API is a REST API that provides programmatic access to all IAM functionality: authentication, user management, roles, permissions, organizations, fine-grained authorization, and more. All API responses use JSON.
Base URL
https://api.altovar.net/apiReplace your-auris-domain.com with the domain where your Auris instance is deployed. If you are using the Auris cloud service, your domain is the one shown in the Console under Settings → Custom Domains.
Authentication
Bearer Token
Most endpoints require a valid access token in the Authorization header:
Authorization: Bearer <access_token>Access tokens are short-lived JWTs (default 15 minutes) obtained through the authentication endpoints. They are signed with RS256 (or HS256 depending on configuration) and can be verified locally using the JWKS endpoint.
Access Level by Endpoint Type
| Endpoint Type | Authentication Required | Notes |
|---|---|---|
| Public auth endpoints | No | /api/auth/login, /api/auth/signup, /api/auth/magic-link, /api/oauth/authorize |
| Authenticated user | Yes | Standard user access token |
| Admin endpoints | Yes | Token must carry the required permission (e.g., manage:users) |
| M2M endpoints | Yes | client_credentials token with configured scopes |
Admin and management endpoints check permissions using the x-tenant header in combination with the Bearer token. The token’s roles are resolved and verified against the required permission before the request is processed.
Tenant Header
Auris is a multi-tenant platform. Requests to admin endpoints must include the tenant identifier:
x-tenant: <tenant-id>The x-tenant header should contain your tenant’s realm name. For Altovar-hosted deployments, use your assigned tenant identifier. Warning: the string 'default' is only a local development fallback — never hardcode it in production. For custom tenant setups, the realm name is shown in the Console under Settings → General.
If the header is omitted on endpoints that require it, the API returns 400 Bad Request with code MISSING_TENANT.
Request Format
Use Content-Type: application/json for all POST, PUT, and PATCH requests with a request body:
Content-Type: application/jsonExample request:
curl -X POST https://api.altovar.net/api/auth/login \
-H "Content-Type: application/json" \
-d '{"email": "[email protected]", "password": "secret"}'For file uploads (user import), use multipart/form-data.
Response Format
All API responses follow a consistent envelope format.
Success Response
{
"ok": true,
"data": { }
}The data field contains the result. Its shape varies by endpoint and is documented individually for each endpoint.
Note: some endpoints return { "success": true, "data": {} } instead of ok. The specific envelope key used is noted in each endpoint’s documentation.
Error Response
{
"ok": false,
"error": {
"code": "ERROR_CODE",
"message": "Human-readable description of what went wrong."
}
}HTTP Status Codes
| Code | Meaning |
|---|---|
200 OK | Request succeeded |
201 Created | Resource created successfully |
400 Bad Request | Invalid request body or parameters |
401 Unauthorized | Missing or invalid access token |
403 Forbidden | Token is valid but lacks the required permission |
404 Not Found | Resource does not exist |
409 Conflict | Resource already exists (e.g., duplicate email) |
429 Too Many Requests | Rate limit exceeded |
500 Internal Server Error | Server-side error |
Common Error Codes
| Code | Description |
|---|---|
INVALID_CREDENTIALS | Email/password combination is incorrect |
ACCOUNT_LOCKED | Account is locked due to too many failed attempts |
TOKEN_EXPIRED | Access token has expired |
TOKEN_INVALID | Access token is malformed or signature is invalid |
PERMISSION_DENIED | User lacks the required permission |
NOT_FOUND | Requested resource does not exist |
VALIDATION_ERROR | Request body failed schema validation |
RATE_LIMITED | Too many requests in a short window |
MISSING_TENANT | Required x-tenant header is missing |
TENANT_NOT_FOUND | Specified tenant does not exist |
Pagination
List endpoints return paginated results using cursor-based page numbers.
Response Shape
{
"ok": true,
"data": {
"data": [],
"pagination": {
"page": 1,
"limit": 20,
"total": 143,
"totalPages": 8
}
}
}Query Parameters
| Parameter | Type | Default | Max | Description |
|---|---|---|---|---|
page | integer | 1 | — | Page number (1-indexed) |
limit | integer | 20 | 100 | Items per page |
Example:
GET /api/users?page=2&limit=50Versioned API (/api/v1)
The rest of this reference documents the legacy /api/* routes as they exist today — most of them predate the { ok, data } envelope above and return their own historical shape ({ success, data }, a bare object/array, etc.), as called out per endpoint.
/api/v1/* is a thin, additive layer over a curated set of admin resources — users, tenants, organizations, roles, applications (OAuth clients), groups — that guarantees the canonical envelope on every response, for every list/get/create/update/delete operation the corresponding legacy route already supports. It calls the exact same legacy handler internally (same authentication, permissions, tenant scoping and rate limits), so it carries no new authorization behavior — only a consistent response shape. Legacy routes are unchanged and keep working exactly as documented elsewhere on this page; migrate to /api/v1 at your own pace.
Success
{ "ok": true, "data": { } }Lists
{
"ok": true,
"data": [ ],
"pagination": { "page": 1, "pageSize": 20, "total": 143, "totalPages": 8 }
}Accepts ?page= and ?pageSize= (default pageSize matches the wrapped endpoint’s own default, max 100). A handful of list endpoints (tenants, roles, groups) have no native pagination in the legacy route — v1 reports the whole list as a single page (page: 1, pageSize: total, totalPages: 1) rather than inventing paging the underlying route doesn’t do.
Errors
{ "ok": false, "error": { "code": "VALIDATION_ERROR", "message": "Request validation failed.", "details": [] } }code is derived from the HTTP status (400/422 → VALIDATION_ERROR, 401 → UNAUTHORIZED, 403 → FORBIDDEN, 404 → NOT_FOUND, 409 → CONFLICT, 429 → RATE_LIMITED, 5xx → INTERNAL), unless the wrapped legacy route already reports a specific machine-readable code (e.g. LIMIT_EXCEEDED_MAU), which is preserved as-is. message is always a static, safe-to-display string — v1 never reflects a legacy route’s raw error text back to the caller. details, when present, only ever carries { path, message } pairs (never the submitted value).
Status codes
201 is preserved on create. A handful of routes (e.g. deleting an organization) have no resource left to return; those report data: null on success rather than omitting data.
/api/v1 currently covers list/get/create/update/delete for the six resources above. It does not add operations the legacy route doesn’t already support (e.g. application client-secret rotation stays a legacy-only action endpoint).
Rate Limiting
Every response includes rate limiting headers:
| Header | Description |
|---|---|
X-RateLimit-Limit | Maximum requests allowed in the current window |
X-RateLimit-Remaining | Requests remaining in the current window |
X-RateLimit-Reset | Unix timestamp when the window resets |
When a rate limit is exceeded, the API returns 429 Too Many Requests with a Retry-After header indicating how many seconds to wait before retrying.
Rate Limit Tiers
| Tier | Endpoints | Limit |
|---|---|---|
| Auth | Login, signup, forgot-password | Strict (prevents brute force) |
| Sensitive | 2FA, password change, magic link | Moderate |
| API | All admin/management endpoints | Standard |
| Public | OIDC discovery, JWKS | Relaxed |
Auth and sensitive endpoints have additional per-account rate limits beyond the IP-based limits. Repeated failures on login trigger progressive lockout.
CORS
Cross-Origin Resource Sharing (CORS) is enforced on all API endpoints. Allowed origins must be registered in the Application settings in the Auris Console under Applications → [App] → Allowed Origins.
Preflight OPTIONS requests are handled automatically. Credentials (cookies) are allowed when the request origin is registered.
To register an origin:
- Go to Console → Applications
- Select your application
- Add the origin to Allowed Origins (e.g.,
https://app.yourdomain.com)
OIDC Discovery
Auris exposes a standard OpenID Connect Discovery document:
GET /api/.well-known/openid-configurationThis returns a JSON document containing all endpoint URLs, supported grant types, scopes, signing algorithms, and other metadata. Standard OIDC libraries use this to auto-configure themselves.
Example response fields:
{
"issuer": "https://api.altovar.net",
"authorization_endpoint": "https://api.altovar.net/api/oauth/authorize",
"token_endpoint": "https://api.altovar.net/api/auth/token",
"userinfo_endpoint": "https://api.altovar.net/api/auth/validate",
"jwks_uri": "https://api.altovar.net/api/.well-known/jwks.json",
"response_types_supported": ["code"],
"grant_types_supported": ["authorization_code", "client_credentials", "urn:ietf:params:oauth:grant-type:device_code", "urn:ietf:params:oauth:grant-type:token-exchange"],
"subject_types_supported": ["public"],
"id_token_signing_alg_values_supported": ["RS256", "HS256"],
"scopes_supported": ["openid", "profile", "email"]
}JWKS
Public signing keys used for JWT verification are available at:
GET /api/.well-known/jwks.jsonResponse:
{
"keys": [
{
"kty": "RSA",
"use": "sig",
"kid": "key-id-1",
"alg": "RS256",
"n": "...",
"e": "AQAB"
}
]
}Keys are cached by clients for up to 1 hour (Cache-Control: public, max-age=3600). Key rotation adds a new key to the set; old keys remain present until their issued tokens expire.
The Auris JS SDK (@auris/js) includes a built-in JWKS-based JWT verifier that automatically fetches and caches signing keys. See the SDK documentation for usage.
SDK Clients
Rather than calling the API directly, consider using an Auris SDK which handles token management, PKCE, refresh, and error handling automatically:
| SDK | Package | Language |
|---|---|---|
| JavaScript | @auris/js | Browser + Node.js |
| React | @auris/react | React 18+ |
| Next.js | @auris/nextjs | Next.js 13+ App Router |
| PHP | auris/sdk | PHP 7.4+ |
| WordPress | auris-sso | WordPress plugin |
See the SDKs documentation for installation and usage guides.