Skip to content

API reference

Management API

Privileged endpoints for your own backend: create and manage end users, grant time, generate and revoke license keys, and manage variables.

Server-side only

Management keys are secrets. Never embed ak_dev_… or ak_live_… keys in software you distribute, in a browser, or in a public repository. If a key leaks, revoke it in the dashboard and create a new one.

Authentication

Create a secret key for an application in the dashboard. Each key belongs to exactly one application, carries a set of scopes, and is stored by Aroli only as a hash - copy it when it's shown. Send it as a bearer token:

Terminal
curl https://<your-aroli-host>/api/v1/management/users \
  -H "Authorization: Bearer ak_live_…"
Scopes
ScopeGrantsUsed by
users:readreadGET /users, GET /users/{id}
users:writewriteCreate, update, delete, ban, unban, revoke sessions, reset devices
licenses:readreadGET /licenses
licenses:writewriteGenerate and revoke license keys
entitlements:writewritePOST /users/{id}/grants
variables:readreadGET /variables
variables:writewritePUT /variables/{key}

A request with a key that lacks the required scope fails with 403 forbidden. Requests are rate-limited per key; see the X-RateLimit-* headers.

Idempotency

POST, PATCH and DELETE requests accept an Idempotency-Key header. If you retry with the same key and the same request, Aroli returns the original response (with Idempotent-Replayed: true) instead of performing the action again. Reusing a key with a different request fails with idempotency_conflict.

Generate 50 keys, safely retryable
curl -X POST https://<your-aroli-host>/api/v1/management/licenses \
  -H "Authorization: Bearer ak_live_…" \
  -H "Idempotency-Key: batch-2026-11-launch" \
  -H "Content-Type: application/json" \
  -d '{ "product": "pro", "quantity": 50, "durationDays": 30, "maxActivations": 3, "prefix": "NWS" }'

Responses

Like the client API, successful responses are { data, requestId } and errors are { "error": { "code", "message" }, "requestId" }. Management responses are not Ed25519-signed - they travel between your server and Aroli over HTTPS.

Users

Base path: /api/v1/management.

GET · POST/usersusers:read · users:write

List end users of the key's application, or create one (username, password, optional email).

GET · PATCH · DELETE/users/{id}users:read · users:write

Fetch, update or delete a single end user.

POST/users/{id}/banusers:write

Bans the user. Optional body { reason }. Banned users can't sign in (user_banned).

POST/users/{id}/unbanusers:write

Lifts a ban.

POST/users/{id}/sessions/revokeusers:write

Ends all of the user's active sessions immediately.

POST/users/{id}/devices/resetusers:write

Unbinds all of the user's devices so they can sign in from a new machine.

POST/users/{id}/grantsentitlements:write

Grants time on a product directly, without a license key.

Grant body
FieldTypeDescription
productstringProduct key, e.g. pro.
durationDaysnumber | nullDays to add, or null for lifetime.
notestring?Optional note stored with the grant.

Licenses

GET/licenseslicenses:read

Lists license keys for the application. Keys are returned with a short hint - never the full plaintext.

POST/licenseslicenses:write

Generates a batch of keys. The plaintext keys are returned once, in this response only - store or deliver them immediately.

Generate licenses body
FieldTypeDescription
productstringProduct key the licenses grant.
quantitynumberHow many keys to generate.
durationDaysnumber | nullTime each key grants, or null for lifetime.
maxActivationsnumberHow many devices each key may be activated on.
labelstring?Optional label to find the batch later.
prefixstring?Optional key prefix, up to 8 letters or digits (e.g. NWS).
POST/licenses/{id}/revokelicenses:write

Revokes a key. Only the time that this key granted is withdrawn from the user's entitlement - see revocation.

Variables

GET/variablesvariables:read

Lists the application's variables.

PUT/variables/{key}variables:write

Creates or replaces a variable. Body { value, scope }, where scope is PUBLIC (readable with the app ID), AUTHENTICATED (requires a signed-in user) or PRIVATE (never served to clients).

OpenAPI

A machine-readable description is published at /api/v1/openapi.json. You can use it to generate a typed client for your backend.