Give an app its own key
The credential an app you host holds, the separate authority that creates it, where the secret lives, and how to stop the app.
On this page
Each backend app has a dedicated management key bound to one project, with only the permissions it needs, kept in your server's secret store. An approved browser aggregate uses a temporary token minted by that exact backend parent, as described below. A deliberately public static aggregate page instead publishes one finite projection credential and needs no backend; its management parent stays secret. The complete table of which credential each kind of host holds is in Authentication and API keys; this page is the checklist your agent follows for each worked example.
Two credentials, two jobs
| Credential | Who holds it | What it may do |
|---|---|---|
| The builder's credential | Your agent, while it builds and provisions the app | Read the contract and the docs, preview and confirm the app's key (api_key:read, api_key:write, mcp:write, and every permission it grants). |
| The app's runtime key | The app's server, scheduler or bot backend, and nothing else | Only the reads the app makes. It never creates, lists, edits or revokes keys, and every route that does refuses it. |
Do not give the runtime key mcp:read, docs:read or a bundle such as investigate. Discovery is the
builder's job; the running app reads only the operations it calls.
Provision the runtime key
Your agent previews the key and you confirm it. Use the app's name, the one project it reads and a fixed expiry:
anectico --project PROJECT_UUID apikey create --name status-board --scope services:read \
--expires-at <fixed-future-RFC3339-expiry> --idempotency-key status-board-1
# Review the complete server preview, then repeat the identical arguments:
anectico --project PROJECT_UUID apikey create --name status-board --scope services:read \
--expires-at <fixed-future-RFC3339-expiry> --idempotency-key status-board-1 --confirm-token <server-token>
The secret appears once. Put it straight into the host's secret store (a secrets manager, the
scheduler's secret variables, a file readable only by the service user) and hand it to the app as
ANECTICO_API_KEY. If the response was lost, repeat the same command with the same
--idempotency-key: you get the key's details and no secret, and no second key is created. If you
never saw the secret, revoke that key and create a new one.
The permissions each worked example needs:
| Example | Runtime permissions |
|---|---|
| Status board | services:read |
| Support page | persons:read |
| Slack bot | oncall:read, projects:read, members:read |
| Nightly report | errors:read; with a saved result, also insights:read, analytics:read, persons:read and the result's own source permissions |
Add a permission that releases customer content (persons:profile:read, replay:content:read,
agents:content:read) only when the app must show that content, and say so in the app's own
documentation.
Where the secret may appear
Only in the server process's environment or secret store, and in the X-API-Key header of requests
the server sends to Anectico. Never in browser code, a mobile binary, a source map, browser storage, a
URL, a query string, a log line, an error page, a repository or a screenshot. Redact it from crash
reports. A program that serves pages to people renders them on the server and sends no key, not even a
masked one.
Watch and limit the key
The key has its own request rate and operation budget beside it on Agents and keys, and every call it makes is in the agent activity record under the key's name:
anectico budget get
anectico activity list --limit 20
A limit of zero answers 429 and keeps the key valid; it is a throttle, not a stop. See
Manage agent budgets and Limits.
Stop the app
Revoke the key. It is the one action that stops the app's next request:
anectico apikey revoke <key-id>
Revoking ends the app's access, not the app: the process keeps running and should show "access ended" (each worked example does) rather than retrying or switching to another key. It does not retract data the app already read. The app's caches, exports, logs and messages are yours to delete; Anectico's erasure cannot reach them. Freezing a key leaves a read-only key reading. See Revoke an agent's access.
Related
Browser aggregate sharing
For browser aggregate sharing, provisioning additionally needs app_views:share, key read and write and
all base and source scopes. Runtime mint uses the grant's exact project parent key with app_views:mint,
analytics:read, persons:read and every result source scope. A mint-only key fails. The parent retains
ordinary project reads; only the issued app_read token is restricted to one approved result and projection,
at most five minutes without refresh. CLI mint requires a new protected --out; no secret goes to stdout.
See Share a saved aggregate with a browser page for the full credential, theft, lifetime, privacy and external-copy contract.