# auth.md

You are an agent. mailbox.bot lets software and AI agents send physical postal mail, certified mail, notices, invoices, and document packets through an API, while keeping human approval, payment, and identity checks around real-world mail actions.

mailbox.bot is a physical postal mail API, so registration is intentionally guarded: agents can discover the service and create a signup intent, but live order placement and Stripe charges require human-owned onboarding and scoped credentials.

## Step 1 - Discover

Fetch protected resource metadata:

```http
GET https://mailbox.bot/.well-known/oauth-protected-resource
```

Then fetch authorization server metadata:

```http
GET https://mailbox.bot/.well-known/oauth-authorization-server
```

API 401 responses include:

```http
WWW-Authenticate: Bearer resource_metadata="https://mailbox.bot/.well-known/oauth-protected-resource"
```

## Step 2 - Pick A Method

Supported today:

- `identity_assertion` with `assertion_type: "verified_email"`

Not supported today:

- Anonymous live registration
- Provider-signed ID-JAG exchange
- Direct live API key issuance before human onboarding

Anonymous registration is disabled because mailbox.bot can send physical mail and charge a card. If you do not have a user email, call `https://mailbox.bot/api/v1/waitlist` first.

## Step 3 - Register A Signup Intent

Ask the user for consent before sharing their email with mailbox.bot.

```http
POST https://mailbox.bot/agent/auth
Content-Type: application/json

{
  "type": "identity_assertion",
  "assertion_type": "verified_email",
  "assertion": "operator@example.com",
  "requested_credential_type": "api_key",
  "agent_name": "My Agent",
  "callback_url": "https://agent.example.com/webhooks/mailbox-bot",
  "intent": "send invoices and manage reply mail",
  "operator_notification_consent": true
}
```

Set `operator_notification_consent: true` only after the user has consented to mailbox.bot emailing them a one-time approval code for this request. If you include `callback_url`, mailbox.bot also POSTs a best-effort `agent_auth.signup_intent.created` event back to your agent.

The response is a guarded email-verification registration. It does not contain a live spending credential. It includes a `claim_token`, `claim_complete_url`, `claim_token_expires`, `lead_id`, `status_url`, `relay_message`, `callback_delivery`, `operator_notification`, and `human_action_required` checklist you should show to the user. Hold `claim_token` in memory only for the claim ceremony.

## Step 4 - Claim Ceremony

Ask the user to open the mailbox.bot approval email and read back the 6-digit code.

```http
POST https://mailbox.bot/agent/auth/claim/complete
Content-Type: application/json

{
  "claim_token": "clm_...",
  "otp": "123456"
}
```

Successful response:

```json
{
  "registration_id": "reg_...",
  "status": "claimed",
  "credential": null,
  "live_credentials_issued": false,
  "message": "Human email ownership confirmed..."
}
```

Claim completion proves the human saw the approval email. It still does not issue live credentials. That is deliberate.

## Step 5 - Human Ownership

The user must complete these steps:

- Complete onboarding.
- Add a valid payment method.
- Select service/plan.
- Create or approve an agent credential.

Before those steps are complete, do not attempt live order placement. Use the status URL returned by registration if you need to track the funnel.

## Step 6 - Use Credentials

After the human creates an agent API key, send it as:

```http
Authorization: Bearer sk_agent_...
```

Pre-claim/discovery scopes: `agent.read`, `mailbox.read`, `package.read`, `inbound.read`.

Post-claim/live-capable scopes: `agent.read`, `mailbox.read`, `package.read`, `inbound.read`, `message.send`, `mail.send`.

For sandbox use, prefer `sk_agent_test_...`. Test keys validate documents, pricing, webhooks, and workflow logic, but do not charge Stripe and do not trigger facility fulfillment.

## Live Order Safety

When placing real mail orders:

- Use `dry_run: true` or the quote/commit flow before live submission when possible.
- Send `X-Max-Cost-Cents` on live submit/commit requests.
- Prefer keys with `force_approval: true` for autonomous workflows.
- Prefer keys with `max_daily_pieces` for bounded agents.
- Set `requires_approval: true` for sensitive, legal, financial, high-volume, or uncertain mail.

mailbox.bot rejects live mail before upload or charge when cost caps, daily spend caps, key daily piece limits, mailbox ownership, or required scopes fail.

## Errors

- `anonymous_not_enabled`: ask the user for an email or call `https://mailbox.bot/api/v1/waitlist`.
- `consent_required`: ask the user for permission to share their email and receive the approval-code email.
- `unsupported_assertion_type`: use `verified_email`.
- `unsupported_credential_type`: use `api_key`.
- `invalid_claim_token` or `claim_expired`: restart registration at `https://mailbox.bot/agent/auth`.
- `otp_invalid`: ask the user to re-read the 6-digit code.
- `otp_expired`: restart registration at `https://mailbox.bot/agent/auth`.
- `human_action_required`: relay the checklist to the user and wait.
- `insufficient_scope`: ask the user for an appropriately scoped key.
- `key_revoked`, `key_expired`, or `key_not_found`: discard the key and restart discovery.

## API References

- OpenAPI: https://mailbox.bot/openapi.json
- MCP: https://mailbox.bot/api/mcp
- A2A: https://mailbox.bot/api/a2a
- A2A agent card: https://mailbox.bot/.well-known/a2a-agent-card
- Agent discovery: https://mailbox.bot/.well-known/agent.json
