Skip to Content

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/api

Replace 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 TypeAuthentication RequiredNotes
Public auth endpointsNo/api/auth/login, /api/auth/signup, /api/auth/magic-link, /api/oauth/authorize
Authenticated userYesStandard user access token
Admin endpointsYesToken must carry the required permission (e.g., manage:users)
M2M endpointsYesclient_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/json

Example 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

CodeMeaning
200 OKRequest succeeded
201 CreatedResource created successfully
400 Bad RequestInvalid request body or parameters
401 UnauthorizedMissing or invalid access token
403 ForbiddenToken is valid but lacks the required permission
404 Not FoundResource does not exist
409 ConflictResource already exists (e.g., duplicate email)
429 Too Many RequestsRate limit exceeded
500 Internal Server ErrorServer-side error

Common Error Codes

CodeDescription
INVALID_CREDENTIALSEmail/password combination is incorrect
ACCOUNT_LOCKEDAccount is locked due to too many failed attempts
TOKEN_EXPIREDAccess token has expired
TOKEN_INVALIDAccess token is malformed or signature is invalid
PERMISSION_DENIEDUser lacks the required permission
NOT_FOUNDRequested resource does not exist
VALIDATION_ERRORRequest body failed schema validation
RATE_LIMITEDToo many requests in a short window
MISSING_TENANTRequired x-tenant header is missing
TENANT_NOT_FOUNDSpecified 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

ParameterTypeDefaultMaxDescription
pageinteger1—Page number (1-indexed)
limitinteger20100Items per page

Example:

GET /api/users?page=2&limit=50

Versioned 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:

HeaderDescription
X-RateLimit-LimitMaximum requests allowed in the current window
X-RateLimit-RemainingRequests remaining in the current window
X-RateLimit-ResetUnix 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

TierEndpointsLimit
AuthLogin, signup, forgot-passwordStrict (prevents brute force)
Sensitive2FA, password change, magic linkModerate
APIAll admin/management endpointsStandard
PublicOIDC discovery, JWKSRelaxed

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:

  1. Go to Console → Applications
  2. Select your application
  3. 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-configuration

This 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.json

Response:

{ "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:

SDKPackageLanguage
JavaScript@auris/jsBrowser + Node.js
React@auris/reactReact 18+
Next.js@auris/nextjsNext.js 13+ App Router
PHPauris/sdkPHP 7.4+
WordPressauris-ssoWordPress plugin

See the SDKs documentation for installation and usage guides.