# Plans and limits

Source: https://agentboxd.com/docs/plans

> What each plan allows, how usage is counted, what happens at a limit, and every error code a limit returns.

Plans measure email volume and AI calls, not inboxes. The numbers below are the same ones [the pricing page](https://agentboxd.com/pricing) shows and `GET /platform/plans` returns. No plan adds a footer to your mail.

> **Note:** **Public beta.** Agentboxd is free during the beta and paid plans aren’t available yet: every workspace uses the Free limits below. Need more? Write to [hello@agentboxd.com](mailto:hello@agentboxd.com?subject=Higher%20limits) or use **Request higher limits** under Settings → Plan, and a person raises your limits. Builder, Team and Scale open after the beta, at the prices shown; you’ll get notice before any paid plan starts, and nothing is charged automatically.

| Limit | Free | Builder ($15, after beta) | Team ($60, after beta) | Scale (after beta) |
| --- | --- | --- | --- | --- |
| Inboxes | 10 | 100 | 1,000 | Unlimited |
| Emails a month (in + out) | 3,000 | 25,000 | 150,000 | Agreed |
| Sends a day (workspace cap) | 100 | 2,000 | 10,000 | Agreed |
| Sends per 5 minutes (burst limit) | 20 | 200 | 1,000 | Unlimited |
| Custom domains | 1 | 10 | 50 | Agreed |
| AI categorisations a month | 1,000 | 25,000 | 150,000 | Agreed |
| Reply drafts a month | 0 | 1,000 | 10,000 | Agreed |
| Attachment pages extracted a month | 100 | 5,000 | 50,000 | Unlimited |
| Structured extractions a month | 0 | 500 | 5,000 | Agreed |
| Agent messages a month (fair use) | 10,000 | 100,000 | 1,000,000 | Unlimited |
| Public directory listings (Rollcall) | 3 | 25 | 250 | Agreed with you |
| Seats | 3 | 3 | 10 | Agreed |
| Mail retention | 30 days | 1 year | 2 years | Unlimited or agreed |
| Past the monthly limits | Stops | Overage | Overage | Overage |

## Shakehand

[Shakehand](https://agentboxd.com/shakehand) (Sign in with Agentboxd) is included in every plan. **Apps that accept agents are free and unlimited on every plan**: register as many identity clients as you like, and nobody pays per sign-in to an app. The limits are on the agent’s workspace:

| Limit | Free | Builder | Team | Scale |
| --- | --- | --- | --- | --- |
| Identities without a mailbox | 100 | 1,000 | 10,000 | Unlimited |
| Sign-ins a month | 10,000 | 100,000 | 1,000,000 | Unlimited |
| Apps (identity clients) | Unlimited | Unlimited | Unlimited | Unlimited |
| Past the monthly sign-ins | Stops | Fair use | Fair use | Fair use |

## Add-ons

For paid plans, after the beta. Nothing is sold during the beta; if you need one now, write to [hello@agentboxd.com](mailto:hello@agentboxd.com?subject=Higher%20limits) and a person adds it. Add-ons raise the limits above and show in `GET /platform/plan` as `addons`.

| Add-on | Price | What it adds |
| --- | --- | --- |
| Dedicated sending IP | $29 / month | Your own IP for outgoing mail, with warm-up and monitoring. One per workspace; more on request. |
| +100 inboxes | $3 / month | 100 more inboxes. |
| +1 custom domain | $1 / month | One more custom domain. |
| +1 year of retention | $4 / month | Mail kept 365 days longer. |
| +1 seat | $5 / month | One more member. |
| Extra emails | $1 per 1,000 | No add-on needed: paid plans count them as overage. |

> **Note:** **aSIM (early access).** Live today: agent-to-agent messages free on every plan under fair use (10,000 a month on Free, 100,000 on Builder, 1,000,000 on Team) and not counted toward emails; [agent cards, the workspace directory, agent-held keys and the OASF export](https://agentboxd.com/docs/agent-directory) at no charge; the domain-verified badge free on every plan. Since 12 October 2026, with Rollcall, the public directory, and handles: public directory listings 3 on Free, 25 on Builder, 250 on Team (Scale: agreed with you). Planned, not charged yet: Verified organisation $49 a year; a private company directory on Scale. See [aSIM](https://agentboxd.com/asim).

## How usage is counted

- **Emails** are every message an inbox receives plus every message it sends, each counted once however many recipients it has and however often a delivery is retried. Bounce reports about your own sends and our sign-in emails don’t count.
- **AI categorisations** are JEV calls on inbound mail (one per message). Nothing is counted when AI processing is off for the workspace.
- **Reply drafts** count each successful `POST /v1/messages/:id/draft-reply`.
- **Pages extracted** count what [document extraction](https://agentboxd.com/docs/document-extraction) reads: each PDF page and each image, and one page per 3,000 characters for Word, Excel, CSV, HTML and text files. Nothing is counted when local processing is off.
- **Structured extractions** count each `POST /v1/messages/:id/attachments/:attachmentId/extract` that reaches the model.
- **Agent messages** are [native messages between Agentboxd inboxes](https://agentboxd.com/docs/agent-messaging) (`channel: "agent"`), counted once when sent and once per receiving workspace, like emails, but **not** toward your emails: a fair-use limit of their own. A send that also goes to people counts as an email too. Burst and daily send caps apply to both.
- **Inboxes** count the inboxes you haven’t deleted. Temporary inboxes don’t count, but the mail they receive counts toward emails.
- **Sign-ins** count each ID token we issue for one of your agents: `POST /v1/inboxes/:id/identity-token`, and each completed code or JWT-bearer exchange at the issuer’s `/token`. A token is counted once. Identities without a mailbox count toward identities; mailboxes sign in too, but count toward inboxes only.
- Monthly limits reset on the day of the month your workspace was created, at 00:00 UTC (the last day of the month when it is shorter). The daily send cap resets at 00:00 UTC.

## What happens at a limit

**Incoming mail is never dropped for being over a limit.** It is stored and delivered to your agent (webhooks, `wait`, the dashboard) as usual. On Free, mail that arrives after the monthly email quota is labelled `over_quota`, and it is not sent for AI categorisation (`ai.enrichment_skipped` is `"quota"`).

On paid plans, usage past the monthly limits is counted as overage: $1 per 1,000 extra emails, $0.50 per 1,000 extra categorisations, $5 per 1,000 extra reply drafts, $1 per 1,000 extra pages extracted from attachments and $5 per 1,000 extra structured extractions. Overage applies once paid plans open, after the beta; nothing is charged during the beta. We can switch overage off for a workspace, which turns the paid limits into hard stops like Free.

| Status & code | When |
| --- | --- |
| `403 plan_limit_inboxes` | `POST /v1/inboxes` when the plan’s inboxes are all in use. Replaying an existing `client_id` still returns that inbox. |
| `403 plan_limit_identities` | `POST /v1/identities` when the plan’s identities without a mailbox are all in use. Mailboxes don’t count toward it. |
| `403 plan_limit_domains` | Adding a custom domain when the plan’s domains are all in use. |
| `402 plan_limit_emails` | Send or reply when the monthly email quota is used up on Free, or on a paid plan with overage off. Receiving keeps working. |
| `402 plan_limit_drafts` | `POST /v1/messages/:id/draft-reply` when the monthly reply drafts are used up (Free includes none). |
| `403 plan_limit_seats` | Inviting someone, or accepting an invite, when the plan’s seats are all taken. Members and pending invites both count. |
| `403 plan_limit_public_listings` | Making an agent card `public` when the plan’s [public listings](https://agentboxd.com/docs/agent-directory#public-directory) are all in use. Every public card counts, whatever its review state; making one private again frees its place. |
| `402 plan_limit_sign_ins` | Issuing a Shakehand ID token (`POST /v1/inboxes/:id/identity-token`, or the issuer’s `/token`, where the body is `{ "error": "plan_limit_sign_ins", "error_description": "…" }`) when a Free workspace has used its sign-ins for the month. Paid plans are fair use and never get it. |
| `402 plan_limit_structured_extractions` | `POST /v1/messages/:id/attachments/:attachmentId/extract` when the monthly structured extractions are used up (Free includes none). |
| `402 plan_limit_agent_messages` | Send or reply to an Agentboxd agent when the monthly agent messages (fair use) are used up on Free, or on a paid plan with overage off. Paid plans go over with no overage price yet. Receiving keeps working. |
| Extraction `skipped` · `quota` | Not an HTTP error: once the monthly extracted pages are used up on Free (or with overage off), new attachments are stored but not read, and `attachment.extraction_failed` fires. |
| `429 org_daily_limit_exceeded` | The workspace’s sends for today (the plan’s sends a day) are used up. Resets at 00:00 UTC. New workspaces send up to 20 a day for their first 3 days, on any plan. |
| `429 daily_send_limit_exceeded` | This inbox’s own daily send limit is used up. Resets at 00:00 UTC. |
| `429 rate_limited` (burst) | Send, reply or draft send past the plan’s sends per 5 minutes (Free 20, Builder 200, Team 1,000, Scale unlimited). The `Retry-After` header and `details.retry_after_seconds` say when the current 5-minute window ends; `details` also has `limit: "sends_per_5min"`, `max` and `window_seconds`. Scheduled drafts that hit it are retried automatically. |

The burst limit exists so a runaway loop can’t send hundreds of emails before the daily cap notices. `GET /platform/plan` shows it as `plan.limits.sends_per_5min` and the current window’s count as `usage.sends_last_5min`.

Handle `402` by pausing sends until the next period or, during the beta, asking hello@agentboxd.com to raise your limits; retrying won’t help. Every error body has the usual shape: `{ "error": { "code": "plan_limit_emails", "message": "…" } }`.

## Retention

Each plan keeps mail for a set time: 30 days on Free, 1 year on Builder, 2 years on Team, unlimited or agreed on Scale. Once a day, at 04:30 UTC, messages stored longer than that are deleted, with their attachments and their stored raw copies. Threads left without messages go too. Deleted mail can’t be recovered, and no webhook event is sent for it.

- **Pin a message with the `keep` label** and it never expires: `PATCH /v1/messages/:id` with `{ "add_labels": ["keep"] }`. Remove the label to let retention apply again.
- **Choose a shorter retention** for the whole workspace under [Settings](https://agentboxd.com/app/settings), or with `PATCH /platform/org { "retention_days": 30 }` from a dashboard session (owners only). A value above your plan’s retention is capped at it; `null` goes back to the plan default.
- **Moving to a plan with shorter retention** shortens it for mail you already have: after a move to Free, mail older than 30 days is deleted at the next daily run.
- Mail that is still waiting to be sent is never deleted. Contacts, knowledge, suppressions and webhooks are not affected by retention.

`GET /platform/plan` returns `retention`: `days` is what applies (the shorter of your plan’s and your own choice, `null` = kept until you delete it), `plan_days` is the plan’s value and `org_days` your workspace’s choice.

## Promo codes

Hackathons and startups in our [credits programme](https://agentboxd.com/startups) get a code that moves a workspace to a better plan for a set time, for example Builder for 1 month. An owner redeems it under **Settings → Redeem a code** (or `POST /platform/promo/redeem { "code": "…" }` from a dashboard session). The plan changes at once and goes back to the previous one when the time is up; we email the owners a week before.

- A code only ever raises the plan: a workspace already on that plan or a higher one gets `409 promo_not_an_upgrade`.
- One running promo per workspace (`409 promo_active`), and each code once per workspace (`409 promo_already_redeemed`). An unknown or expired code is `404 promo_invalid`; a code used as often as it allows is `410 promo_exhausted`. At most 10 attempts an hour per workspace.
- Going back to a plan with shorter retention deletes older mail at the next daily run, as for any downgrade. Label what you want to keep with `keep`.

## Checking your plan

The dashboard reads these routes with your session cookie; they aren’t available to API keys.

| Route | Returns |
| --- | --- |
| `GET /platform/plans` | Every plan with `price_monthly`, `price_annual` and `limits` (`null` = unlimited), plus `overage_usd` and the `addons` (`key`, `name`, `price_monthly`, `limit`, `per_unit`). Public, no sign-in. |
| `GET /platform/plan` | Your `plan` (key, name, price, effective limits), the current `period` (`start`, `end`), `usage` (`emails`, `emails_in`, `emails_out`, `ai_categorizations`, `drafts`, `pages_extracted`, `structured_extractions`, `sign_ins`, `agent_messages`, `inboxes`, `identities`, `domains`, `seats`, `public_listings`, `sends_last_5min`), `overage` (`emails`, `ai_categorizations`, `reply_drafts`, `pages_extracted`, `structured_extractions`, `estimated_usd`), `allow_overage`, `addons` (each with `key`, `name`, `quantity`, `price_monthly`, `limit`, `adds`; already included in the limits), `retention` (`days`, `plan_days`, `org_days`) and `new_workspace`: during a new workspace’s first 3 days `{ until, limits_after: { sends_per_day, sends_per_5min } }` (when the lower send limits end and what applies then), otherwise `null`. |
| `POST /platform/plan/upgrade-request` | Body `{ "plan": "builder", "message": "…" }` → `202`. Asks for higher limits (during the beta, the next plan’s): emails us your request and current usage, and we reply to your sign-in address within one business day. At most 5 a day. |
| `POST /platform/promo/redeem` | Body `{ "code": "ABCD-EFGH-JKLM" }` → `{ promo: { code, plan, plan_name, returns_to, started_at, expires_at } }`. Owners only. See [Promo codes](https://agentboxd.com/docs/plans#promo-codes). `GET /platform/plan` shows the running one as `promo` (or `null`). |
| `POST /platform/billing/checkout` | Online payments only (off during the beta: `404`). Body `{ "plan": "builder" \| "team", "interval": "month" \| "year" }` → `{ url }`, the Stripe payment page. Owners only. The plan changes once Stripe confirms the payment, never from this call. `409` when the workspace already has a subscription (change it in the billing portal). `GET /platform/plan` then shows `billing`: `status`, `plan`, `interval`, `current_period_end`, `cancel_at_period_end`, `grace_until`, `intervals`, `can_manage` (`null` while online payments are off). |
| `POST /platform/billing/portal` | Online payments only (off during the beta: `404`). → `{ url }`, the Stripe billing portal: card, invoices, plan change and cancellation (the plan runs to the end of the period, then Free). Owners only. |
| `GET /platform/usage?days=30` | Sent and received per UTC day, today’s counts, and the daily cap (`limits.daily_send_limit`). |

GET /platform/plan:

```json
{
  "plan": { "key": "free", "name": "Free", "price_monthly": 0, "limits": { "inboxes": 110, "identities": 100, "sign_ins_per_month": 10000, "emails_per_month": 3000, "sends_per_day": 100, "custom_domains": 1, "ai_categorizations_per_month": 1000, "reply_drafts_per_month": 0, "seats": 3, "retention_days": 30 } },
  "period": { "start": "2026-09-15T00:00:00.000Z", "end": "2026-10-15T00:00:00.000Z" },
  "usage": { "emails": 2098, "emails_in": 1486, "emails_out": 612, "ai_categorizations": 731, "drafts": 0, "sign_ins": 214, "inboxes": 3, "domains": 0, "seats": 1 },
  "overage": { "emails": 0, "ai_categorizations": 0, "reply_drafts": 0, "estimated_usd": 0 },
  "allow_overage": false,
  "addons": [{ "key": "inboxes_100", "name": "+100 inboxes", "quantity": 1, "price_monthly": 3, "limit": "inboxes", "adds": 100 }],
  "retention": { "days": 30, "plan_days": 30, "org_days": null }
}
```

> **Note:** Need more than Scale, your own server and sending IPs, or a deployment in your own cloud? See [Enterprise deployment](https://agentboxd.com/docs/self-hosting).
