Skip to content

Authentication

Axowl exposes several authentication mechanisms depending on the caller.

PrefixCallerAuth
/api/org/{slug}/*Dashboard (org member)Session token; org + membership resolved by TenantResolutionMiddleware.
/api/public/*SDK / end userApplication key and/or per-org RS256 JWT.
/api/m2m/tokenServer-to-serverExchanges an org API key (ah_live_…) for a short-lived token.
/scim/v2/{orgSlug}/*IdP provisioningSCIM bearer token.
/api/v1/admin/*Platform adminSession token.

End-user JWTs are signed with the org’s RSA key and verified via the org’s published JWKS. Server-authoritative checks (Introspect, CheckPermission) read fresh permissions from the database (IdentityServiceImpl.cs:226), so revocations apply immediately.

Use the API key directly. Org API keys are prefixed ah_live_ and presented as Authorization: Bearer ah_live_… (IdentityServiceImpl.cs:124). They are SHA-256 hashed at rest, scoped to a single organization, and can be rotated or revoked from Settings → Keys.

Section titled “Token exchange (recommended for anything high-volume)”

POST /api/m2m/token trades the API key for a short-lived access token — 5 minutes by default. Prefer it over sending the key on every call: the key is a long-lived secret, so each request that carries it is another place it can leak (proxy logs, crash dumps, traces). The token expires on its own and can be narrowed to fewer scopes than the key holds.

Terminal window
curl -X POST https://testapi.axowl.com/api/m2m/token \
-H 'Content-Type: application/json' \
-d '{"orgSlug":"acme","apiKey":"ah_live_…","scope":"org.member.read"}'
{ "accessToken": "eyJhbGciOi…", "tokenType": "Bearer", "expiresIn": 300, "org": "acme" }

Send it as Authorization: Bearer <accessToken> to /api/org/{slug}/*. The organization in the token must match the {slug} in the route, and if the key is bound to a service account, that account must still be active — both are re-checked on every request, so suspending the service account takes effect immediately rather than when the token expires. Revoking the key also cuts off tokens already issued from it, on the next request.

scope is optional and can only narrow what the key already has; it never widens it.

Longer-lived tokens for devices (added 2026-09-12)

Section titled “Longer-lived tokens for devices (added 2026-09-12)”

Robots, gateways and other IoT devices lose connectivity and should not have to re-exchange every five minutes. The lifetime is a per-key ceiling, not an organization setting, so widening it for one device fleet changes nothing for your other keys.

  1. When issuing the key (POST /api/org/{slug}/settings/keys/api-keys, or Settings → Keys), set maxTokenLifetimeSeconds. Allowed values: 60 seconds to 7 days (604800). Anything above the default 300 requires the request to come from the organization owner and to carry the owner’s personal seal (assertionResponseJson, a passkey assertion bound to api_key.long_lifetime). The dashboard collects the seal for you when you pick 1 hour, 24 hours or 7 days. Shorter-than-default ceilings need neither. A key’s ceiling cannot be changed afterwards — revoke and reissue.
  2. When exchanging, pass lifetimeSeconds. The issued lifetime is min(lifetimeSeconds, key ceiling, 7 days), and the response’s expiresIn is the real value. Omitting lifetimeSeconds always yields the 5-minute default, even on a 7-day key — a longer token is something the device asks for explicitly.
Terminal window
curl -X POST https://testapi.axowl.com/api/m2m/token \
-H 'Content-Type: application/json' \
-d '{"orgSlug":"acme","apiKey":"ah_live_…","lifetimeSeconds":86400}'
RequestKey ceilingIssued
omittedany300
86400none (default key)300
864008640086400
6048008640086400
30any60 (floor)

Revocation still wins: every /api/org/{slug}/* request checks the issuing key against a revocation marker that is kept for the key’s full ceiling plus one hour, so a revoked 7-day key is refused on the next call for the whole window. What the ceiling does widen is exposure — a leaked token is a bearer credential for its entire lifetime until you revoke the key — which is why issuing one is an owner-plus-seal action. Keep ceilings as short as the device’s offline pattern actually needs.