# How do I give each AI agent its own scoped API key?

*2026-10-21 · By Naol Ketema, founder of Agent Identity*

**Short answer:** Keep one administrative key for setup and mint a separate key per agent that can act only as that agent. On Agent Identity that is the difference between an org key and an agent key: apiKeys.create with an identityId returns a key that reaches only its own agent's mail, events and settings, and can be revoked on its own.

## Why one key for everything is a problem

A key that can do everything in your account should never sit in a process that reads untrusted input. An agent reads email, calls and messages from strangers, and a model decides what to do next. If that process holds an admin key, a confused or manipulated agent can act with admin power.

Least privilege for agents means each running agent holds a credential that can only act as itself. The admin credential stays with the humans and setup scripts.

## Org keys and agent keys

- Org key: created with the organization, with no identity_id. It acts as the organization and is required for administration: suspending agents, managing API keys, adding domains, writing contact and access rules, and buying phone numbers.
- Agent key: created with POST /v1/api-keys and an identity_id. It acts as that one agent. This is what you give the running agent process.
- Some things need the agent's own key: sending an Agent2Agent task and moving a task's state. An org key cannot complete a task on an agent's behalf.
- Either key works for mail, events, vault calls (subject to the agent's own keypair), contacts reads and tunnels.

An agent key only ever reaches its own agent. Another agent's mailbox returns 404, events and webhooks are limited to its own, and it cannot list, create or revoke API keys or create agents (403). Only an owner can create an org key; a developer can create agent keys.

## Mint a key per agent

```ts
import { AgentClient } from "@agentidentity/sdk";

const base = "https://api.agent-identity.dev";
const org = new AgentClient({ baseUrl: base, apiKey: process.env.AID_ORG_KEY! });

const { key } = await org.apiKeys.create({ name: "support-agent runtime", identityId: process.env.AID_AGENT! });
// Store key now. It is shown once.

const asAgent = new AgentClient({ baseUrl: base, apiKey: key });
const me = await asAgent.whoami(); // { actorType, actorId, orgId, orgSlug, orgName }
```

```bash
curl -sS -X POST https://api.agent-identity.dev/v1/api-keys \
  -H "authorization: Bearer $AID_ORG_KEY" \
  -H 'content-type: application/json' \
  -d '{"name":"support-agent runtime","identity_id":"6f21..."}'
```

The response has id, key and key_prefix. Keys are stored hashed, so the full value is returned exactly once. Record key_prefix next to the name: it is what the list endpoint and dashboard show afterwards.

## Rotate and revoke

- Step 1: create a new agent key for the same agent.
- Step 2: deploy it to the agent runtime.
- Step 3: revoke the old one with POST /v1/api-keys/{id}/revoke. Revocation takes effect immediately.
- Step 4: confirm with GET /v1/api-keys, which lists keys without their secrets.

Because each agent has its own key, a leak means revoking one key and redeploying one agent. The others keep running. The same applies when you retire an agent: revoke its keys and suspend it, and nothing else changes.

## Read the errors correctly

- 401 means there is no usable actor: the key is missing, malformed, revoked or foreign. Do not retry with the same key.
- 403 means the key was recognised but is not allowed to do this, usually an agent key attempting an org-admin operation. It is a wrong-key-for-the-job problem.
- 404 can mean the resource belongs to another agent or organization. Ownership failures are hidden as absence on purpose.
- GET /v1/me (whoami in the SDK) is the quickest check: actor_type is user for an org key and agent for an agent key.

## Where the org key belongs

The org key is for people and setup code: the dashboard, a provisioning script, a CI job that creates agents and rules. Keep it in a secrets manager that only those can read. A useful test: if a process reads email, calls or messages from outside, it should not be able to read the org key.

Webhooks follow the same split. An endpoint registered with an identity_id receives only that agent's events, and an agent key can rotate only its own endpoints' secrets. GET /v1/usage reports usage against the plan limits and can be read with any key of the organization.

## Practical habits

- Never put the org key in the agent's environment. Run setup from a separate script or the dashboard.
- Name keys after where they run (support-agent runtime, staging worker), so a leaked prefix tells you what to revoke.
- Use separate keys for separate deployments, such as production and staging.
- Rate limits are per organization (600 authenticated requests per minute), so one noisy agent can slow the rest. Watch for 429s.

If you run a single agent with no untrusted input, one key may be fine. Split keys as soon as an agent reads mail, calls or messages from people you do not control. The cost is one extra API call per agent at setup; the payoff is that a mistake by one agent stays inside that agent.

## FAQ

### Can an agent key create other agents or keys?

No. An agent key gets 403 for creating agents and for listing, creating or revoking API keys.

### Can I see a key's value again after creating it?

No. Keys are stored hashed and the full value is returned once. Create a new key and revoke the old one if it is lost.

### How do I tell whether a key is an org key or an agent key?

Call GET /v1/me or whoami() in the SDK. actor_type is user for an org key and agent for an agent key.

### Why does my agent key get 404 for something that exists?

The resource belongs to another agent or organization. Agent Identity reports ownership failures as 404 so they cannot be used to probe what exists.

---
Docs: https://www.agent-identity.dev/docs · All guides: https://www.agent-identity.dev/guides · llms.txt: https://www.agent-identity.dev/llms.txt