# API · Enrollment

{/* // POST /v1/enroll */}

Redeem an enrollment key (`pk_enroll_…`) for a scoped agent key (`pk_agent_…`). This is the only
endpoint that does **not** require an agent key — the enrollment key in the body is the credential.

## `POST /v1/enroll`

### Request

```json
{
  "enrollment_token": "pk_enroll_…",   // required
  "agent_handle": "support-bot"        // optional; idempotent binding key
}
```

| Field | Type | Notes |
|---|---|---|
| `enrollment_token` | string | The `pk_enroll_…` key. Validated against its hash. |
| `agent_handle` | string? | Client-chosen agent identifier. Same handle → same agent (idempotent). |

```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" }'
```

### Response `200`

```json
{
  "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"],
  "allowed_domains": [],                 // empty → any org domain
  "mailboxes_used": 0,
  "mailboxes_max": 5,
  "expires_at": "2026-06-13T18:00:00Z"
}
```
**agent_key is shown once:** The full `agent_key` is returned only in this response. Store it immediately; afterwards only the
  `agent_key_prefix` is retrievable. If you lose it, redeem again with the same `agent_handle` to mint
  a fresh key for the same agent (subject to the enrollment key's quota and expiry).

### Validation

The server rejects the redeem if the enrollment key is **revoked**, **expired**, or **exhausted**
(`used_count >= max_mailboxes`):

| Condition | Status | `error.code` |
|---|---|---|
| Unknown / malformed key | `401` | `invalid_enrollment_token` |
| Revoked | `401` | `enrollment_token_revoked` |
| Expired | `401` | `enrollment_token_expired` |
| Exhausted | `409` | `enrollment_token_exhausted` |

See [Errors](https://docs.agents.mszazu.com/api/errors/) for the full error envelope.

## Idempotency

Redeeming with the same `agent_handle` returns the **same agent**. Calling `/v1/enroll` on every boot
is safe — it won't create duplicate agents or burn a mailbox slot (slots are spent on
`mailbox:create`, not on enroll).

## Next

- [Enrollment tokens & scopes](https://docs.agents.mszazu.com/concepts/enrollment-tokens/) — the capability model.
- [Inboxes](https://docs.agents.mszazu.com/api/inboxes/) — the first call you'll make with the new agent key.