Authentication
API key authentication, scopes, and access control for the Aurion API.
Authentication
The Aurion API uses API key authentication. Include your key in the X-API-Key header with every request. The same key is also accepted as Authorization: Bearer itsm_sk_live_xxxx.
curl -H "X-API-Key: itsm_sk_live_xxxx" \
https://apps.aurionai.net/api/v1/ticketsAPI keys are formatted as itsm_sk_{env}_{random}. The prefix follows your tenant, not the environment: keys minted for a sandbox tenant use itsm_sk_test_; every other tenant's keys use itsm_sk_live_, on staging as in production. Send the key exactly as issued — changing its prefix returns 401.
API Key Scopes
Each API key is assigned one or more scopes that control which endpoints it can access. Scopes are validated at creation time against the fixed catalog below: the API lowercases and de-duplicates what you supply, and any scope not in the table returns 400 with Unknown API key scope(s): …. There is no wildcard — * is not a scope, is rejected the same way, and no all-access key can be created; list each scope the key needs.
| Scope | Description | Endpoints |
|---|---|---|
tickets:read | Read tickets and ticket history | GET /api/v1/tickets, GET /api/v1/tickets/:id |
tickets:write | Create and update tickets | POST /api/v1/tickets, PATCH /api/v1/tickets/:id |
calls:read | View call recordings and logs | GET /api/v1/calls, GET /api/v1/calls/:id |
calls:write | Start web voice widget sessions (together with config:write) | POST /api/v1/voice-widget/token |
usage:read | View usage data | GET /api/v1/usage/summary, GET /api/v1/usage/details |
usage:write | Accepted, but no public endpoint writes usage data today | — |
billing:read / billing:write | Read / update billing data | /api/v1/billing/* |
webhooks:read / webhooks:write | Read / create webhook subscriptions | GET /api/v1/webhooks, POST /api/v1/webhooks |
webhooks:delete | Delete webhook subscriptions (together with webhooks:write) | DELETE /api/v1/webhooks/:id |
kb:read / kb:write / kb:media | Accepted, but no public endpoint uses them yet — the Knowledge Base is reachable only through a dashboard session | — |
users:read / users:write | List / manage requesters and team users | GET /api/v1/requesters, GET /api/v1/tenant/users |
roles:write | List team users (together with users:read) | GET /api/v1/tenant/users |
conversations:read / conversations:write | Read / write conversations (v1 only) | /api/v1/conversations/* |
conversations:export | Export a call or conversation (together with conversations:write and conversations:read) | POST /api/v1/conversations/:id/export |
config:read / config:write | Read / update tenant configuration | /api/v1/config/*, /api/v1/configuration/*, /api/v1/integrations/*, /api/v1/telephony/*, /api/v1/voice-widget/*, /api/v1/onboarding/*, /api/v1/tenant/* |
exports:read / exports:write | Read / trigger tenant exports | /api/v1/tenant/exports/* |
contacts:read / contacts:write | Accepted, but not enforced by any endpoint yet — no contacts endpoint (v1 or v2) is reachable with an API key | — |
The users scope maps to /api/v1/requesters and /api/v1/tenant/users — not /api/v1/users (dashboard user management), which is denied to API keys entirely (see Denied Paths).
Scopes the dashboard does not offer
The dashboard's Create API Key dialog (Configuration > API Keys) offers the Conversations, Tickets, Calls, Usage (read only), Webhooks and Knowledge Base scopes, on every plan. It does not offer these:
billing:read, billing:write, config:read, config:write, contacts:read, contacts:write, exports:read, exports:write, roles:write, usage:write, users:read, users:write
To get a key with any of them, a tenant admin creates it with POST /api/v1/api-keys — see API Key Management.
Scope Enforcement
Scopes are enforced using path-prefix matching. A key with tickets:read can access any GET/HEAD request under /api/v1/tickets/.
The required action is derived from the HTTP method: GET and HEAD require the :read scope; POST, PUT, PATCH, and DELETE require the :write scope on the matching path prefix.
Many endpoints also check a second scope of their own, and the key must hold both. For example:
| Endpoint | Path scope | Additional scope |
|---|---|---|
DELETE /api/v1/webhooks/:id | webhooks:write | webhooks:delete |
GET /api/v1/tenant/users | users:read | roles:write |
POST /api/v1/voice-widget/token | config:write | calls:write |
Many config:* and billing:* reads also need the matching :write scope, and listing, creating and reading exports under /api/v1/tenant/exports also needs config:write. A key missing the path scope gets 403 API key missing required scope: …; a key missing the additional scope gets 403 Insufficient permissions: requires X — add scope X to the key if it is in the scope table above; otherwise that endpoint cannot be called with an API key.
Denied Paths
The following path prefixes are never accessible via API keys regardless of scopes — a request authenticated with X-API-Key returns 403 {"detail": "API keys are not permitted for this endpoint"}:
/api/v1/api-keys— API key management (use a dashboard session JWT)/api/v1/auth— Authentication/api/v1/users— Dashboard user management/api/v1/tenants— Tenant management/api/v1/super-admin— Platform administration/api/internal— Internal service endpoints
In addition, any path that is not in the scope allowlist above is rejected with 403 — this includes every /api/v2/* endpoint. API keys can only reach the /api/v1 prefixes listed in the scope table.
Error Responses
Authentication and authorization errors follow the standard error shape — a JSON body with a single detail string. Branch on the HTTP status code and the detail message; there is no error/message envelope.
401 Unauthorized — Invalid API key. The response carries a WWW-Authenticate: Bearer header:
{
"detail": "Invalid API key"
}When no credentials are supplied at all, the body is instead:
{
"detail": "Missing authentication credentials"
}403 Forbidden — Valid key but insufficient scope:
{
"detail": "API key missing required scope: tickets:write"
}403 Forbidden — Valid key but the path is denied to API keys (see Denied Paths):
{
"detail": "API keys are not permitted for this endpoint"
}End-User Authentication
End-user endpoints (mobile app, voice widget) use JWT Bearer tokens instead of API keys:
curl -H "Authorization: Bearer eyJhbGciOi..." \
https://apps.aurionai.net/api/v1/app/ticketsEnd-user tokens are issued via SSO, password login, or magic link. See the End-User API guide for full authentication details.
API Key Management
Manage API keys programmatically under /api/v1/api-keys. These endpoints require a dashboard session JWT with the tenant_admin role (or higher).
To get one, sign in to the Admin Dashboard as a tenant admin, open your browser's developer tools, and copy the value stored under app_access_token in Local Storage for that site. It is your own session token, valid for at most 60 minutes and replaced when the dashboard refreshes your session, so copy it right before the call. Sign out of the dashboard afterwards to revoke it, and never share or store it.
⚠️ Key-management endpoints reject API keys
The
/api/v1/api-keysendpoints are in the deny list — a request authenticated withX-API-Keyreturns403 {"detail": "API keys are not permitted for this endpoint"}. Authenticate these calls with a dashboard session JWT (Authorization: Bearer <dashboard-jwt>), not an API key.
Create API Key
The request body fields:
| Field | Type | Constraints |
|---|---|---|
name | string | Required, 1–100 chars |
description | string | Optional, ≤ 500 chars |
scopes | string[] | Required, at least 1 item |
expires_in_days | int | Optional, 1–3650 |
curl -X POST "https://apps.aurionai.net/api/v1/api-keys" \
-H "Authorization: Bearer <dashboard-jwt>" \
-H "Content-Type: application/json" \
-d '{
"name": "CI/CD Pipeline",
"description": "Key for automated deployments",
"scopes": ["tickets:read", "tickets:write"],
"expires_in_days": 365
}'Response (201 Created):
{
"id": "key_abc123",
"name": "CI/CD Pipeline",
"description": "Key for automated deployments",
"key_prefix": "a1b2c3d4e5f6",
"scopes": ["tickets:read", "tickets:write"],
"created_at": "2026-04-09T00:00:00Z",
"expires_at": "2027-04-09T00:00:00Z",
"api_key": "itsm_sk_live_xxxx"
}The full api_key value is returned only once at creation time. Store it securely. The
key_prefix is the first 12 characters of the key's random segment — it identifies the key in
listings but is not the full secret.
List API Keys
curl "https://apps.aurionai.net/api/v1/api-keys" \
-H "Authorization: Bearer <dashboard-jwt>"Response:
{
"api_keys": [
{
"id": "key_abc123",
"name": "CI/CD Pipeline",
"description": "Key for automated deployments",
"key_prefix": "a1b2c3d4e5f6",
"scopes": ["tickets:read", "tickets:write"],
"created_by": "user_xyz",
"created_at": "2026-04-09T00:00:00Z",
"expires_at": "2027-04-09T00:00:00Z",
"last_used_at": "2026-04-10T12:30:00Z",
"revoked_at": null,
"is_active": true
}
]
}The full secret is never returned in listings — only the key_prefix.
Rotate API Key
Generate a new key with the same scopes, revoking the old one:
curl -X POST "https://apps.aurionai.net/api/v1/api-keys/key_abc123/rotate" \
-H "Authorization: Bearer <dashboard-jwt>"Response:
{
"id": "key_def456",
"key_prefix": "f6e5d4c3b2a1",
"scopes": ["tickets:read", "tickets:write"],
"api_key": "itsm_sk_live_rotated_xxxx"
}Revoke API Key
Immediately deactivate a key without deleting it:
curl -X POST "https://apps.aurionai.net/api/v1/api-keys/key_abc123/revoke" \
-H "Authorization: Bearer <dashboard-jwt>"Returns 204 No Content.
Delete API Key
curl -X DELETE "https://apps.aurionai.net/api/v1/api-keys/key_abc123" \
-H "Authorization: Bearer <dashboard-jwt>"Returns 204 No Content.
Best Practices
- Least privilege — Only grant the scopes your integration needs
- Rotate regularly — Create new keys and retire old ones periodically
- Never commit keys — Use environment variables, not source code
- One key per integration — Makes it easy to revoke access per integration