Scoped API keys

Issue limited keys for CI pipelines, agent sessions, and MCP clients — without full team admin access. Restrict by inbox label prefix and optional read-only mode.

Scope fields

FieldEffect
labelPrefix Inbox label must start with this prefix (e.g. ci-, agent-)
readOnly GET/list/wait/extract only — no create, delete, open, or agent verify without inboxId

Full admin keys: both fields empty / false (legacy and primary team keys).

Create a scoped key

Team API (admin key required)

POST /v1/team/keys
Authorization: Bearer <ADMIN_TEAM_KEY>
Content-Type: application/json

{
  "label": "ci-bot",
  "scope": {
    "labelPrefix": "ci-",
    "readOnly": false
  }
}

Response includes the full key once — store it in CI secrets.

MCP client registration (DCR)

POST /v1/oauth/register
Authorization: Bearer <ADMIN_TEAM_KEY>

{
  "client_name": "cursor-ci",
  "scope": {
    "labelPrefix": "agent-",
    "readOnly": true
  }
}

CLI (self-host / ops)

npm run issue:key:db -- ci-bot --label-prefix=ci-
npm run issue:key:db -- ci-readonly --label-prefix=ci- --read-only

Rules

Error codes

CodeWhen
scope_read_onlyPOST/DELETE/open on read-only key
label_requiredCreate without label when prefix is set
label_prefix_mismatchLabel does not match prefix
scope_admin_requiredTeam admin / DCR / billing with restricted key
inbox_not_foundInbox outside your prefix (404)

CI example

export MAILAGENT_API_KEY=ma_ci_scoped...

curl -X POST https://api.webmailagent.com/v1/inboxes \
  -H "Authorization: Bearer $MAILAGENT_API_KEY" \
  -d '{"label":"ci-nightly-42","service":"github"}'

curl -X DELETE "https://api.webmailagent.com/v1/inboxes?labelPrefix=ci-nightly-" \
  -H "Authorization: Bearer $MAILAGENT_API_KEY"

More