Skip to content

Authentication & keys

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

KeyPrefixWho holds itWhat it can do
Enrollment keypk_enroll_…The bootstrap secret you hand an agent or MCP hostRedeem once or many times to mint mailboxes, up to max_mailboxes
Agent keypk_agent_…The agent, after redeemingAuthenticate 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.

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.

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();

Pass your agent key as a bearer token:

Terminal window
curl -sS "$POSTERN_API_BASE_URL/v1/inboxes" \
-H "Authorization: Bearer pk_agent_7Hq2…"

The SDK and MCP server read it from the environment:

Terminal window
export POSTERN_API_KEY="pk_agent_7Hq2…"
export POSTERN_API_BASE_URL="https://api.agents.mszazu.com" # "mock" for offline

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

ScopeGrants
mailbox:createCreate new mailboxes (counts against the enrollment quota).
mailbox:readList/read messages and threads.
mailbox:sendSend and reply.

A key with only mailbox:read can never send, even if the request looks valid. See Enrollment tokens & scopes for the full capability model.

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