# Authentication & keys

{/* // SCOPED ENROLLMENT */}

Postern has exactly two kinds of key. Both are high-entropy secrets; the server only ever stores
their hashes.

| Key | Prefix | Who holds it | What it can do |
|---|---|---|---|
| **Enrollment key** | `pk_enroll_…` | The bootstrap secret you hand an agent or MCP host | Redeem once or many times to mint mailboxes, up to `max_mailboxes` |
| **Agent key** | `pk_agent_…` | The agent, after redeeming | Authenticate every call, within its scopes — short-lived, revocable |

The discipline, stated plainly: **don't hand an MCP host your master key. Hand it a postern key.**
An enrollment key carries only the granted scopes and a mailbox counter; a cloned key can't exceed
its quota because the counter is server-enforced.

## Redeem an enrollment key

A human (or org-admin API call) mints a `pk_enroll_…` key with scopes, allowed domains, a mailbox
quota, and an expiry. The agent redeems it for a scoped `pk_agent_…` key.

```ts title="enroll.ts"
import { Postern } from "@postern/sdk";

// The agent is handed only the enrollment key — never an org-wide key.
const bootstrap = new Postern({ apiKey: process.env.POSTERN_ENROLLMENT_KEY! });

const { client, enrollment } = await bootstrap.enrolled({
  enrollment_token: process.env.POSTERN_ENROLLMENT_KEY!,
  agent_handle: "support-bot", // idempotent: same handle -> same agent
});

console.log(enrollment.agent_key_prefix);  // pk_agent_7Hq2 (full key shown once)
console.log(`${enrollment.mailboxes_used}/${enrollment.mailboxes_max} used`);

// `client` is already authenticated with the minted agent key.
const inbox = await client.inboxes.create();
```

  ```bash frame="terminal"
curl -sS -X POST "$POSTERN_API_BASE_URL/v1/enroll" \
  -H "Content-Type: application/json" \
  -d '{
    "enrollment_token": "pk_enroll_…",
    "agent_handle": "support-bot"
  }'
```

```json title="response"
{
  "agent_id": "agent_Q1x",
  "agent_key": "pk_agent_7Hq2…",   // shown once — store it now
  "agent_key_prefix": "pk_agent_7Hq2",
  "scopes": ["mailbox:create", "mailbox:read", "mailbox:send"],
  "mailboxes_used": 0,
  "mailboxes_max": 5,
  "expires_at": "2026-06-13T18:00:00Z"
}
```

  ```json title="redeem_enrollment (tool call)"
{
  "name": "redeem_enrollment",
  "arguments": {
    "enrollment_token": "pk_enroll_…",
    "agent_handle": "support-bot"
  }
}
```

The MCP server stores the minted agent key in-session and uses it for every subsequent tool call.
**Idempotent on agent_handle:** Redeeming with the same `agent_handle` returns the same agent — like AgentMail's `client_id`. Safe
  to call on every boot; it won't burn a mailbox slot or create duplicate agents.

## Authenticate every call

Pass your agent key as a bearer token:

```bash frame="terminal"
curl -sS "$POSTERN_API_BASE_URL/v1/inboxes" \
  -H "Authorization: Bearer pk_agent_7Hq2…"
```

The SDK and MCP server read it from the environment:

```bash frame="terminal"
export POSTERN_API_KEY="pk_agent_7Hq2…"
export POSTERN_API_BASE_URL="https://api.agents.mszazu.com"   # "mock" for offline
```

## Scopes

Scopes are the capabilities a key carries. They are checked server-side on every call.

| Scope | Grants |
|---|---|
| `mailbox:create` | Create new mailboxes (counts against the enrollment quota). |
| `mailbox:read` | List/read messages and threads. |
| `mailbox:send` | Send and reply. |

A key with only `mailbox:read` can never send, even if the request looks valid. See
[Enrollment tokens & scopes](https://docs.agents.mszazu.com/concepts/enrollment-tokens/) for the full capability model.

## Revocation

Revocation is **per-token and per-agent-key, instant, and isolated** — killing one agent's key never
rotates anyone else's. Every action is audit-logged with the token id and agent id, so attribution is
per-agent. server-enforced
**Never ship a master key to a model host:** No org-wide key should ever reach an MCP host or live in agent config. Mint a single-purpose
  enrollment key scoped to the mailboxes that agent needs, with a short expiry. That is the whole
  point of the gate.

## Next

- [Enrollment tokens & scopes](https://docs.agents.mszazu.com/concepts/enrollment-tokens/) — the capability model in depth.
- [Agents](https://docs.agents.mszazu.com/concepts/agents/) — what an agent is as a principal.
- [API · Enrollment](https://docs.agents.mszazu.com/api/enrollment/) — the `/v1/enroll` contract.