The 3 keys most deployments need
Start here. Reach for the full permission catalogue below only when you need a narrower, custom-scoped key. See also Recommended key layout and Creating keys.
Permissions
The server enforces a fixed catalogue of permissions; each one gates specific HTTP routes. An admin key holds all of them; a scoped key holds the subset you grant on creation. Unknown permission strings are rejected when a key is created.Note: Two valid permissions are human/dashboard-only and cannot be granted to an API key:orgs:admin(instance administration, which is operator-only) andkeys:update. A request toPOST /keysorPATCH /keys/:idthat tries to grant either one is rejected with HTTP 422. See thekeys:updaterow below for why a bearer key may create keys but never edit them.
Events ingest & query
Sessions & evaluations
Dashboards
Saved queries (SQL composer)
AI assistant
API keys
Dashboard users
These permissions back the dashboard’s Users page, where each member’s granted scopes are shown as chips:

Operational settings

Alerts & incidents
Audits
Note: To give a key the audit surface, grant audits:* to it explicitly. See Upgrade and backward-compatibility notes for how existing grantees were migrated when Audits shipped.
The recipient-picker endpointGET /alerts/recipients(which lists the member emails an alert editor can notify) is reachable by a holder of eitheralerts:readoralerts:write, so alert editors can populate the picker without being grantedusers:read.
A dashboards viewer needs bothdashboards:read(to load the saved views) andevaluations:read(the health metrics are computed from evaluation data). Grantdashboards:writeto let a user create or edit dashboards, anddashboards:deleteto remove them.
/healthand/auth/*(OTP request, OTP verify, session check, logout) are unauthenticated by design; they’re the login flow and liveness probe.GET /access-grantersrequires a valid key but no specific permission, so any logged-in user can see which admins to contact about access changes.
Permission Sets
Permission sets let you apply a named role instead of hand-picking individual tokens every time. Rather than selecting a dozen permissions one by one for each new dashboard user or API key, you choose a set, and everyone assigned to it carries a consistent, reviewable grant. Editing a custom set re-applies the new grant to every user already assigned to it, so a role change is one edit rather than a sweep through every member. Every organization is seeded with three built-in sets:
The three built-in sets are immutable; their names always mean the same thing, so
read-only, standard, and admin are safe to reference in policy and onboarding. An operator can create additional custom sets to model roles specific to your organization (for example, a “dashboard author” role or a “collector-only” role).
Sets are surfaced in the dashboard and managed over the API at GET /permission-sets (list, gated by users:read) and POST /permission-sets / PUT /permission-sets/:name / DELETE /permission-sets/:name (create, edit, delete a custom set, gated by settings:write). Deleting or editing a built-in set is refused.
Set membership is what backs two other features:
DEFAULT_USER_PERMISSIONS(the grant preselected when an admin opens + new user) defaults to thestandardset.- The
--setflag onagenteye-orgctl(operator member management) starts a member from a named set, which you then fine-tune with--add/--remove.
Note: When a set includes a permission that is not key-assignable (for example a custom set carrying keys:update), seeding a key from that set drops the non-assignable tokens; the server would otherwise reject the key with HTTP 422. Dashboard users are not subject to that restriction.
Bootstrap Admin Key
The admin key is the single root credential that lets an operator bring up access from nothing: with it you can mint every other scoped key, invite the first dashboard users, and configure the instance before any other key exists. It is the one key you do not create through the keys API; it is provisioned from the environment so the server is reachable on first boot. Set theADMIN_KEY environment variable on the server. On every startup the server upserts this value as an admin key with all permissions.
To rotate: change ADMIN_KEY to a new secret and restart the server.
Organization scoping
Organizations themselves are created and managed out-of-band by an operator, not through this keys API. Org and member lifecycle (create / rename / delete / purge an org; add / update / remove a member) is done with theagenteye-orgctl CLI; there is no HTTP API or dashboard button for it. What is unchanged: per-org API keys are still minted in the dashboard (or via this keys API) by org members.
In a multi-org deployment, every key an org member creates (through this keys API or the dashboard Keys page) belongs to one organization and can only ever read or write that org’s data; the org is stamped on the key at creation and enforced on every request. The two bootstrap keys are the only exception: the admin key (seeded from ADMIN_KEY) and the dashboard-assistant key (seeded from AGENT_API_KEY) are instance-scoped (they carry no org). The dashboard authenticates with the admin key so it can proxy per-org requests on behalf of signed-in members. Single-tenant deployments need not think about this; all keys belong to the built-in default org.
Creating Keys
Use the admin key (or any key withkeys:create permission) to create additional scoped keys.
Collector key (ingest only)
Dashboard key (read only)
key value yourself; choose a strong secret and store it securely. (The dashboard works the other way: it generates a strong secret for you and shows it once at creation; see Key Management in the Dashboard.) The response confirms the key was created:
Listing Keys
Disabling a Key
Disabling revokes access immediately without deleting the key record.Regenerating a Key
Generates a new secret for an existing key. The old secret is invalidated immediately.Key Management in the Dashboard
The Keys page in the dashboard provides a UI for all of the above operations. You need a key withkeys:read permission to view the list, and keys:create / keys:update / keys:disable / keys:regenerate for the create / edit / disable / regenerate actions respectively. Editing a key’s permissions (keys:update) is separate from creating one (keys:create), so you can grant an operator the ability to mint keys without the ability to re-scope existing ones, or vice versa. The admin key covers all of these.
When you create a key from the dashboard you do not supply the secret; the dashboard generates a strong secret for you and displays it once at creation. Copy it immediately and store it securely; it is never shown again, exactly as with a regenerate. You can still pick the key’s permissions directly, or seed them from a permission set (see below).

Recommended Key Layout
Note: The assistant’s key is seeded automatically by the server from theAGENT_API_KEYenv var (the same secret the agent presents asAGENTEYE_API_KEY); there is no manual key-minting step and no admin key involved. Its permissions are fixed in source code so scope can’t be widened by misconfiguration: read across events / evaluations / dashboards, plus dashboards-write and queries-read / write / run for the “Ask AI to write a query” authoring flow. All SQL still goes through the same read-only role and guarded SQL path as a user-written query, so this widens the authoring surface, not the data surface; destructive operations (queries:delete,dashboards:delete) deliberately stay off the assistant key. Like theadminkey, it is protected: it can’t be disabled or regenerated through the keys API, only rotated by changingAGENT_API_KEYand restarting. Dashboard users additionally need theagent:usepermission to see and use the assistant. If you enable self-instrumentation, give the assistant a separateevents:add-only key.
Upgrade and backward-compatibility notes
You only need these if you are upgrading an existing instance; new deployments can skip them.When Audits shipped, existing grantees were widened along the same role shapes as alerts: every user and permission set holdingalerts:readgainedaudits:read, and every holder ofalerts:writegainedaudits:write. Existing API keys were not widened. Grantaudits:*to a key explicitly if it needs the audit surface.
Stored grants of the legacyalerts:acktoken are parsed asincidents:ackso on-callers retain access without rekeying. The token is no longer assignable from the dashboard’s user editor; the matrix offersincidents:ackinstead.
Next steps
- Python SDK: how your agent code authenticates when sending events.
- Security: how sign-in, access control, and per-organization data isolation work.

