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
    }
  }
}
FieldMeaning
storage_mbTotal stored-email storage available to the organization, in MB.
send_per_hour / send_per_dayOutbound send caps over a rolling hour and day.
api_per_minutev1 REST API request cap per minute.
webhooks_max_globalMaximum endpoints across the org. null means unlimited.
webhooks_per_domainWhether endpoints can be scoped per domain.
filters_per_domainWhether allow/block filters can be scoped per domain.
spam_thresholds_per_domainWhether 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