Limits & Quotas
Primitive enforces a small set of per-organization limits. Your account's effective limits are returned by the API, so you never have to hard-code them — read them at runtime and adapt.
For plan options and pricing, see the pricing page. This page documents the limits themselves and how to observe them.
Read your effective limits
GET /v1/account returns a limits object alongside your plan and granted entitlements:
curl https://api.primitive.dev/v1/account \ -H "Authorization: Bearer $PRIMITIVE_API_KEY"
{ "success": true, "data": { "plan": "developer", "entitlements": ["..."], "limits": { "storage_mb": 5120, "send_per_hour": 1000, "send_per_day": 10000, "api_per_minute": 120, "webhooks_max_global": 1, "webhooks_per_domain": false, "filters_per_domain": false, "spam_thresholds_per_domain": false } } }
| Field | Meaning |
|---|---|
storage_mb | Total stored-email storage available to the organization, in MB. |
send_per_hour / send_per_day | Outbound send caps over a rolling hour and day. |
api_per_minute | v1 REST API request cap per minute. |
webhooks_max_global | Maximum endpoints across the org. null means unlimited. |
webhooks_per_domain | Whether endpoints can be scoped per domain. |
filters_per_domain | Whether allow/block filters can be scoped per domain. |
spam_thresholds_per_domain | Whether spam thresholds can be set per domain. |
webhooks_max_global is null when unlimited. Treat any limit as plan-dependent and read it from this endpoint rather than assuming a fixed value.
Storage quota
GET /v1/account/storage reports how much of your stored-email quota is in use:
curl https://api.primitive.dev/v1/account/storage \ -H "Authorization: Bearer $PRIMITIVE_API_KEY"
{ "success": true, "data": { "quota_mb": 5120, "used_mb": 142, "percentage": 2.8, "emails_count": 5120 } }
Stored raw email and attachments count toward the quota. Discarding content (see Receiving Mail) or letting messages age past the retention window frees space.
Content retention
Inbound email content (raw message and attachments) is retained for up to 30 days, unless it is attached to a Function execution. Don't rely on Primitive as long-term storage — copy anything you need to keep into your own system. You can also remove content earlier yourself with content discard.
Rate limits
When you exceed a rate limit, the API responds with 429 (error code rate_limited, or rate_limit_exceeded on some per-resource limiters), plus Retry-After and ratelimit-* headers. Branch on the 429 status, not the code. See Errors → Rate-limit responses for the exact headers and the recommended back-off.
Outbound sends are additionally bounded by send_per_hour / send_per_day. These protect shared outbound IP reputation; if you have a legitimate higher-volume use case, contact support.
Entitlement-gated features
Some capabilities are turned on per organization and appear in the entitlements array from GET /v1/account. If a feature is not enabled, the relevant endpoint returns 403 feature_disabled with a docs_url in error.details. Examples include x402 payments (invite-only) and per-domain filters and routes on paid plans.
Related Pages
- Errors: the rate-limit envelope and headers.
- Pricing: plan options.
- Sending Mail: outbound caps and idempotency.