Aetherfy API keys
The format of an Aetherfy API key
An Aetherfy API key is a prefix followed by exactly 32 hexadecimal characters.
| Prefix | What it records |
|---|---|
afy_live_ | The key was issued by Aetherfy production — this is what keys created at app.aetherfy.com carry |
afy_test_ | The key was issued by an Aetherfy pre-production environment |
The prefix is a record of which Aetherfy environment issued the key, not a
mode you select. There is no control that mints a test key, and one is not a
sandbox against your production account: each prefix binds the key to the
environment that created it, and Aetherfy never falls back from one to the
other. Keys you create yourself are afy_live_ keys.
Aetherfy stores only a SHA-256 hash of the key. It also keeps a display-only prefix — the first 12 characters — so you can identify a key in a list without the plaintext existing anywhere in the system.
That 32-hexadecimal shape is what Aetherfy generates. The client-side validators are deliberately more permissive than the generator, so they keep working if the issued format ever widens — neither is a statement about what Aetherfy issues today:
- The Aetherfy generator issues
afy_live_orafy_test_followed by exactly 32 hexadecimal characters. This is the canonical, issued format. - Both Aetherfy SDKs validate against
^afy_(live|test)_[a-zA-Z0-9]{16,}$— 16 or more alphanumeric characters, not necessarily hexadecimal. - The Aetherfy CLI requires the prefix plus at least 32 alphanumeric characters.
A key that passes an SDK or CLI check is therefore not necessarily a key Aetherfy issued; only the server decides that. The looser client-side rules exist so an older SDK or CLI does not reject a future key format.
The one-time reveal of an Aetherfy key
The plaintext of an Aetherfy API key is shown exactly once, at creation, and never again. There is no endpoint that returns it afterwards, and Aetherfy support cannot recover it, because only the hash was kept.
On first login the Aetherfy welcome modal reveals your default key’s plaintext
once. A second attempt at that reveal returns HTTP 410 with the code
ALREADY_REVEALED. If you lose the plaintext, the answer is always to create a
new key.
Where to manage Aetherfy API keys
Create, rename and revoke keys at https://app.aetherfy.com/dashboard/settings/api-keys .
Revoking a key in Aetherfy takes effect at once, with no grace window for in-flight clients. The agents API checks that a key still exists on every request, so it refuses a revoked key on its very next request. The vector API refuses it as soon as each region drops its cached copy of the key, which revoking does at once; a region that missed that still refuses the key within 60 seconds, because it re-checks a cached key against the key list at least that often.
What an Aetherfy API key is scoped to
An Aetherfy API key you create is per account. It is not per workspace and not per project, and holding one of your keys rather than another does not narrow what you can reach: every key you create reaches everything your account reaches, on the Aetherfy agents API and on the Aetherfy vector database alike.
Tenant isolation in Aetherfy is enforced per request on the server, derived from the account the key belongs to.
The one narrower key is the one Aetherfy issues to an agent, described in the next section. On the Aetherfy agents API it can call only the routes an agent’s own runs need, and only for its own agent and runs. On the Aetherfy vector API it reaches only the collections of its own workspace and of the workspaces you grant it.
Agent-scoped keys issued by Aetherfy
An Aetherfy agent receives an automatically-generated key, injected into its
environment as AETHERFY_API_KEY. These keys behave differently from the ones
you create:
| Property | Agent-injected key |
|---|---|
| Visible in the dashboard | No |
| Counts against your key quota | No |
| Lifecycle | Issued per deployment and region — one for each region a service deployment runs in, one for each task run — and removed when that deployment ends or the agent is deleted |
| Bound to | One agent and one of its deployments; every point written with the key records both (attested authorship) |
| Access on the Aetherfy agents API | Only the routes in the table below, and only for its own agent and runs |
| Access on the Aetherfy vector API | Only the collections of its own workspace and of the workspaces you grant it, and none of the account-level routes (below) |
You do not create, rotate or revoke these yourself.
The injected key is bound to the deployment that is running, so a version that
has been superseded cannot use the vector database or the agents API any more.
Replacing a service deployment replaces its keys, and a task run’s key stops
working when the run finishes: the Aetherfy agents API answers it 401 INVALID_API_KEY from then on.
On the Aetherfy agents API, an agent’s key can make exactly these calls — the ones the Aetherfy SDK agent helpers make for spawning, reading and waiting on runs, and fetching a run’s payload:
| Aetherfy agents API route | Scope | Allowed only when |
|---|---|---|
POST /api/v1/agents/{agent}/spawn | runs:spawn | {agent}, by UUID or name, is the agent the key was issued to. An agent spawns as itself, never as another parent |
GET /api/v1/deployments/{id} | runs:read | {id} is the key’s own deployment, or a run the key’s agent spawned |
GET /api/v1/deployments/{id}/wait | runs:read | The same as the read above |
GET /api/v1/deployments/{id}/payload | runs:payload | {id} is the key’s own deployment — a task run reading its own input |
Every other Aetherfy agents API route answers an agent’s key with 403 AUTH_AGENT_KEY_OUT_OF_SCOPE, and so does an allowed route whose path names
another agent or another agent’s run. The error carries detail.agent_id, the
agent the key was issued to, and detail.required_scope: the scope the route
needs, or null for a route no agent key can call. Deploying, deleting,
listing agents, secrets and workspaces are all outside the list, so code
running in an agent cannot change another agent — or itself — through the
Aetherfy agents API.
The refusal comes before every account check, so a suspended account’s agent
key calling a route outside the table gets AUTH_AGENT_KEY_OUT_OF_SCOPE, not
ACCOUNT_SUSPENDED.
A refused request does not count as a use of the key: its last-used time is not updated.
When an agent genuinely needs account-level access to the Aetherfy agents API —
a deploy pipeline that runs as an agent, say — give it that deliberately:
create a key yourself and store it as one of the agent’s secrets under a name
of your own, such as DEPLOY_KEY. Aetherfy rejects every secret name beginning
AETHERFY_, because that prefix is reserved for the variables the platform
injects, so the injected AETHERFY_API_KEY is never replaced by yours.
Then send your key explicitly wherever the agent needs account access, because
inside an agent AETHERFY_API_KEY is always the injected one. On a REST call,
put it in the header yourself (Authorization: Bearer $DEPLOY_KEY). The
Aetherfy CLI reads AETHERFY_API_KEY before anything else, so set it for the
one command:
AETHERFY_API_KEY="$DEPLOY_KEY" afy deploy --yesThe 403 an agent’s key gets says which of the two problems it hit: a route its key cannot call at all, or an allowed route whose path names another agent or another agent’s run.
What an agent’s key reaches on the Aetherfy vector API
On the Aetherfy vector API, an agent’s injected key reaches the collections of its own workspace — or, for an agent with no workspace, the collections in no workspace — plus the workspaces you grant it. A workspace is a wall: the agent’s code cannot read, write, list, create or delete a collection anywhere else, and neither can anything it passes the key to.
| An agent’s key calls | Aetherfy vector API answer |
|---|---|
| A collection in its own workspace, or in a workspace granted to it | Served, like any key |
| A collection, list or create in any other workspace | 403 AGENT_KEY_WORKSPACE_FORBIDDEN; error.workspace names the workspace, or is null for the collections in no workspace |
A collection named in a request body — a query’s lookup_from, a grouped query’s with_lookup, an alias change — in another workspace | 403 AGENT_KEY_WORKSPACE_FORBIDDEN, the same as by path |
The account-level routes: GET /api/v1/analytics/usage and GET /api/v1/analytics/metrics | 403 AUTH_AGENT_KEY_OUT_OF_SCOPE, with the same agent_id and required_scope fields the Aetherfy agents API sends |
| Anything, while Aetherfy cannot read which workspaces the agent may use | 503 AGENT_ACCESS_UNAVAILABLE, retryable; nothing is applied |
The refusal is decided on the workspace the request names, before any collection is looked up, so it is the same whether or not the collection — or the workspace — exists. An agent cannot learn what another workspace holds by being refused.
Both Aetherfy SDKs raise the refusal as a typed error carrying the workspace:
AgentWorkspaceForbiddenError in Python (aetherfy_vectors) and in JavaScript,
with a workspace attribute and a message that says how to grant access. It is
not retryable. An AGENT_ACCESS_UNAVAILABLE answer arrives as the SDKs’
service-unavailable error, which is.
A key you create is not affected: it reaches every workspace of your account.
Granting an agent another workspace
Only you can grant access, from your account — never the agent itself:
- Dashboard: the agent’s page, under Workspace access. Granting asks first and says which data becomes reachable; removing does not ask.
- CLI:
afy access <agent>lists what the agent reaches,--add <workspace>grants and--remove <workspace>revokes, with""for the collections in no workspace. See the Aetherfy CLI. - Aetherfy agents API:
GET /api/v1/agents/{agent}/access,POSTandDELETEon/api/v1/agents/{agent}/access/workspaces[/{workspace}], andPUTandDELETEon/api/v1/agents/{agent}/access/workspaceless.
The rules a grant follows:
- A grant belongs to the agent, not to a key. Redeploying, which replaces the agent’s keys, keeps its grants.
- It takes effect within 60 seconds on the Aetherfy vector API, and so does removing it.
- An agent’s key cannot grant. The access routes answer an agent’s key
403 AUTH_AGENT_KEY_OUT_OF_SCOPE, andaetherfy.yamlhas no field for access, so an agent’s own code cannot widen what it reaches. - Granting what the agent already owns is refused,
422 AGENT_WORKSPACE_GRANT_REDUNDANT, and nothing is stored: its own workspace, or the collections in no workspace for an agent that has no workspace. Adding a workspace it already has, or removing one it does not, changes nothing and is not an error. - A grant is to one workspace, not to a name. Deleting a workspace deletes the grants to it, and a new workspace created later under the same name is not granted to anyone.
How many API keys each Aetherfy plan allows
| Plan | Maximum API keys |
|---|---|
| Free | 2 |
| Starter | 5 |
| Performance | 10 |
| Enterprise | 50 |
Exceeding the limit returns HTTP 400 from Aetherfy, with a message naming your plan and its allowance. Agent-injected keys are excluded from this count.
Rotating an Aetherfy API key
There is no rotate endpoint in Aetherfy. Rotation is a three-step procedure you perform yourself:
- Create a new key at https://app.aetherfy.com/dashboard/settings/api-keys and capture the plaintext at creation time.
- Update every client, environment variable and secret store that carries the old key.
- Revoke the old key.
Do the steps in that order. Revocation is immediate, so revoking before step 2 is complete will break live traffic.
How Aetherfy clients read the key
| Client | Where the key comes from |
|---|---|
| Python SDK | AETHERFY_API_KEY, then AETHERFY_VECTORS_API_KEY |
| JavaScript SDK | AETHERFY_API_KEY, then AETHERFY_VECTORS_API_KEY |
| CLI | credentials.yaml, written with permissions 0600; also honours AETHERFY_API_KEY |
Both Aetherfy SDKs check the environment in that order, so setting
AETHERFY_API_KEY covers every client at once. The CLI is documented at the Aetherfy CLI.
Authenticating directly against the Aetherfy HTTP API
Send the key as a bearer token:
Authorization: Bearer afy_live_0123456789abcdef0123456789abcdefAetherfy answers a bad or absent credential with:
| Condition | Status | Code |
|---|---|---|
| Header missing or malformed | 401 | MISSING_API_KEY |
| Key not recognised | 401 | INVALID_API_KEY |
| An agent’s key calling a route outside its list | 403 | AUTH_AGENT_KEY_OUT_OF_SCOPE |
| An agent’s key naming a workspace it was not granted (Aetherfy vector API) | 403 | AGENT_KEY_WORKSPACE_FORBIDDEN |
All four are terminal for the request — retrying the same key will not change
the answer. The codes are the same on both Aetherfy surfaces, since the same key
authenticates both; only the envelope differs, error.code on the vector API and
detail.code on the control plane. AGENT_KEY_WORKSPACE_FORBIDDEN exists only on
the vector API, because only the vector API holds collections. The one retryable
answer an agent’s key can get here is 503 AGENT_ACCESS_UNAVAILABLE, described
above.