EmailGuard
  • Pricing
Log inRegister
DocumentationAPI ReferenceKnowledge Base

Knowledge base

Knowledge base

Short reference articles

API
  • API key scopes
Teams
  • Team roles and permissions
Security
  • Audit log events
Reference
  • API rate limiting
Email detection
  • Detection overview
  • Valid syntax
  • Normalization
  • Subaddressing
  • Role addresses
  • Public domains
  • Relay detection
  • Disposable detection

API rate limiting

How /api/v1 throttles traffic, which response headers to read, and how that relates to monthly API quotas.

Loading article…

On this page

  • Standards and headers
    • HTTP 429 Too Many Requests
    • Retry-After
    • X-RateLimit-* (informal convention)
  • How limits work
    • Fixed one-minute window
    • What shares a limit
  • Limits by endpoint type
  • Example: read headers with curl
  • Recommended client behavior
  • Monthly API quota
  • Related docs

The public API applies two separate limits:

  • Per-minute rate limits — cap short bursts so the service stays responsive for everyone.
  • Monthly API quota — caps total successful usage for your team’s plan (when your deployment includes billing).

This guide explains per-minute limits and response headers. Monthly quotas are summarized at the end.

Standards and headers

HTTP 429 Too Many Requests

When you exceed a per-minute limit, the API responds with 429 and a JSON body:

{
  "code": "RATE_LIMIT_EXCEEDED",
  "message": "Rate limit exceeded, please try again in 42s"
}

The 429 status code is defined for this purpose in RFC 6585 and described in RFC 9110 (HTTP Semantics) as the appropriate response when the client has sent too many requests in a given period.

Retry-After

On 429 responses from rate limiting, we send a Retry-After header whose value is a delay in seconds (not an HTTP-date). That matches the delay-in-seconds interpretation documented for Retry-After in RFC 9110, Section 10.2.3.

Retry-After: 42

Wait at least that many seconds before retrying. For automated clients, combine this with exponential backoff and jitter.

X-RateLimit-* (informal convention)

Authenticated /api/v1 responses include:

HeaderWhen presentMeaning
X-RateLimit-LimitSuccess and throttleMaximum requests allowed in the current window
X-RateLimit-RemainingSameRequests left in the window (0 when exhausted)
X-RateLimit-ResetSameSeconds until the window resets, not a Unix timestamp
Retry-AfterOnly on 429Same value as X-RateLimit-Reset for that response

These names follow the widespread X-RateLimit-* pattern used by many HTTP APIs. They are not defined by an IETF RFC. The IETF is standardizing similar fields (for example RateLimit-Limit) in draft-ietf-httpapi-ratelimit-headers; our headers use the same ideas (limit, remaining, reset interval) with the familiar X- prefix.

Read header names case-insensitively per RFC 9110. In browsers, exposed header names may appear with different casing.

How limits work

Fixed one-minute window

Per-minute limits use a fixed window (typically 60 seconds from your first request in that window):

  1. Each request counts toward the limit for that window.
  2. When you exceed the limit, further requests receive 429 until the window resets.
  3. After the window ends, the counter starts fresh.

This is not a sliding window. Traffic at the end of one minute and the start of the next can briefly exceed the per-minute number across a two-minute span.

What shares a limit

Request typeLimit applies to
/api/v1/team/... with an API keyEach API key has its own counter
GET /api/v1/openapi.json (no API key)Client IP address

Keys on the same team do not share one per-minute counter. Use one key per integration; do not rotate keys to get around limits.

Limits by endpoint type

Endpoint typeLimitWindow
Authenticated team API (/api/v1/team/...)60 requests1 minute
OpenAPI document (GET /api/v1/openapi.json)30 requests1 minute (per IP)
Tool result polling (GET /api/v1/tools/.../results)300 requests1 minute (per API key), when your deployment exposes tool routes

Starting an async tool job (POST /api/v1/tools/...) counts toward the same 60/min limit as other authenticated team API calls. Polling results uses the higher limit so you can poll every few seconds without exhausting the general cap.

Example: read headers with curl

curl -sS -D - -o /dev/null \
  -H "Authorization: Bearer YOUR_KEY" \
  "https://YOUR_DOMAIN/api/v1/team"

A successful response:

HTTP/2 200
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 59
X-RateLimit-Reset: 58

After you are throttled:

HTTP/2 429
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 37
Retry-After: 37
Content-Type: application/json
 
{"code":"RATE_LIMIT_EXCEEDED","message":"Rate limit exceeded, please try again in 37s"}

Recommended client behavior

On 429 with code RATE_LIMIT_EXCEEDED:
  wait at least Retry-After seconds (or use X-RateLimit-Reset)
  retry with backoff and jitter; cap retry attempts
 
On 429 with code API_QUOTA_EXCEEDED:
  stop tight-looping; check plan usage or wait for the billing period to reset

Track X-RateLimit-Remaining on success to slow down before you hit 429. For tool jobs, poll results on an interval of a few seconds rather than hammering the API.

If you use the TypeScript SDK (emailguard-sdk), honor Retry-After in your retry logic when you handle PublicApiError from throttled responses.

Monthly API quota

On plans with API usage metering, each successful /api/v1 call may count toward your team’s monthly allowance. Limits depend on your subscription tier.

Per-minute rate limitMonthly quota
ScopePer API key (or per IP for unauthenticated routes)Per team
HTTP status429429
Error codeRATE_LIMIT_EXCEEDEDAPI_QUOTA_EXCEEDED
Response headersX-RateLimit-*, Retry-AfterNo dedicated quota headers
What to doWait for the minute window to resetUpgrade your plan or wait for the billing period to reset

When the monthly quota is exceeded, the API returns API_QUOTA_EXCEEDED and does not include X-RateLimit-* headers on that response.

Per-minute throttles (RATE_LIMIT_EXCEEDED) do not count against your monthly quota.

View current usage with GET /api/v1/team/billing/usage when your API key includes the billing:read scope.

Related docs

  • SDK clients — published clients and authentication
  • API key scopes — scopes for tools, billing, and deliverability
  • MCP integration — same limits apply to MCP-forwarded REST calls