Plans and limits
| Limit | Free | Pro | Scale |
|---|---|---|---|
| Price (USD, monthly / yearly) | Free | $19 / $190 | $79 / $790 |
| Price (INR, monthly / yearly) | Free | ₹1,499 / ₹14,990 | ₹5,999 / ₹59,990 |
| Inboxes | 3 | 25 | 250 |
| Sends per month | 300 | 10,000 | 100,000 |
| Sends per day (whole org) | 100 | not capped separately | not capped separately |
| Custom domains | 0 | 1 | 10 |
| Webhooks | 1 | 10 | 100 |
Prices on this page are illustrative while the service is in early access. Receiving is not metered in v1. Yearly plans cost ten times the monthly price. On Pro and Scale, custom domains give you DNS record generation and verification; sending from and receiving on your own domain is not connected yet (see domains).
Enforcement#
When an action would exceed your plan, the API answers 402 with code plan_limit_exceeded, a fix message and the plan that would allow it. Limits apply to the organization, not to a pod: inbox count when you create an inbox, domain and webhook counts when you create those, and monthly and daily sends when you send. Sends are counted per unique recipient at send time, in UTC calendar months and days, so deleting an inbox does not reset usage and a send the provider rejects still counts.
GET /v0/billing returns your plan, status, limits and current usage; GET /v0/billing/usage returns just the limits and usage. In the dashboard, the Overview and Billing screens show the same numbers.
All limits#
| Limit | Value |
|---|---|
| Inboxes, sends per month, custom domains, webhooks | By plan (table above) |
| Sends per day, whole organization | 100 on Free, not capped separately on Pro and Scale |
| Sends per inbox | 100 in any rolling 24 hours by default, on every plan (429 rate_limited) |
| Recipients per message | 50 unique addresses across to, cc and bcc |
| Attachments per message | 50 |
| Inline attachment content | 6 MB combined; use url for larger files |
Attachment fetched by url | 10 MB per file, 25 MB total, https only, 10 second timeout |
| Request body | 40 MB |
Page size (limit) | 1 to 100, default 50 |
| Batch endpoints | 100 ids |
| Webhook scope ids | 10 per webhook (inbox ids, pod ids) |
| Webhook delivery | 10 second timeout, 8 attempts |
| Webhook signature tolerance | 5 minutes (recommended) |
| Idempotency keys | Kept 48 hours |
| Download links (raw, attachments) | 1 hour |
| Metrics window | start within the last 90 days; at most 1000 buckets; at most 200,000 events scanned for rates |
| Requests per IP | 600 per minute |
| Requests per API key | 1200 per minute |
/auth/* requests per IP | 30 per minute |
| MCP request body | 256 KB |
| Agent verification code | Expires in 24 hours, 10 attempts, human replaceable twice |
| Verification email links | Expire in 24 hours |
Rate limits are counted in memory on a single server and reset when it restarts. Exceeding one returns 429 with Retry-After; see errors.
Billing#
- Customers with an Indian billing country pay through Razorpay in INR; everyone else through Stripe in USD. You can override the choice at checkout.
GET /v0/billingshows the current plan, status, period end, limits and usage.POST /v0/billing/checkoutreturns aurlto complete payment,POST /v0/billing/portalopens the Stripe customer portal (Razorpay has no hosted portal) andPOST /v0/billing/cancelcancels at the end of the period. Billing routes need an organization-level key.- Your plan only changes when the payment provider's signed webhook says so; checkout alone grants nothing.
- No free trial. A downgrade takes effect at the end of the paid period.
- If a payment fails the plan becomes
past_due. After a 7 day grace period Free limits apply. - Tax invoicing (GST or VAT) is not handled yet.
- Early access: the checkout, portal and cancel code has been tested against simulated providers, not yet against live Stripe or Razorpay test accounts. See status.
Usage metrics#
GET /v0/metrics/usage returns time series for storage, messages, threads, inboxes, domains and pods at organization, pod and inbox level (needs metrics_read). GET /v0/metrics/events counts events by type. The dashboard overview draws them as charts. The Python SDK has methods for them; the TypeScript SDK has none for usage (it has metrics.rates).