Skip to main content

The hourly quota, the abuse controls in front of it, the headers that report them and how to pace a client.

Four controls sit inside the API, and an edge throttle sits in front of them. One is your plan’s budget; the others keep a single client from degrading the service for everyone. Only the budget is reported in headers, because only the budget is something a well-behaved client will ever reach.

The hourly quota

Your organization’s key requests share one budget per clock hour (UTC), reset at the top of the hour.

PlanRequests per hour
HobbyistNo API access: a key on this plan is refused with 401.
Pro (including a Pro trial)1,000
EnterpriseNo hourly quota. Usage is still recorded per key, and the per-address limits below still apply.

Every request that reaches the quota is counted, whatever the handler then does: a 404, a 405 or a permission 403 spends budget like a 200. Requests rejected before the quota, by an abuse control below or because the key is bound to another organization, are not counted.

Headers

Every metered response carries these headers. Only requests that authenticate with an API key are metered; dashboard sessions carry none of these headers and spend nothing. On an unlimited plan none are sent either, because a limit of zero would read as no budget at all.

HeaderMeaning
X-RateLimit-LimitThe hourly budget.
X-RateLimit-RemainingRequests left in the current hour.
X-RateLimit-ResetUnix time (seconds) at which the budget resets.
RateLimit-PolicyThe same budget as an IETF structured field, for example "hourly";q=1000;w=3600.
RateLimitThe same remaining count and seconds-to-reset: "hourly";r=<remaining>;t=<seconds>.
Retry-AfterOnly on a rejection: seconds until the reset.
Example http
HTTP/1.1 200 OK
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 999
X-RateLimit-Reset: 1767229200
RateLimit-Policy: "hourly";q=1000;w=3600
RateLimit: "hourly";r=999;t=1800

Reading a 429

A 429 from the API carries a code so a client can tell the remedies apart; one from the edge carries nothing:

codeCauseRemedy
quota_exceededThe hourly budget is spent.Wait until X-RateLimit-Reset. Backing off sooner does not help.
rate_limitedAn abuse control rejected the request.Sleep for Retry-After seconds and retry. No quota headers are sent, because no budget was touched.
no JSON bodyThe client address was throttled at the edge before reaching the API.Back off exponentially; there is no header to read.

Abuse controls

These are sized so a real client never meets them. They exist for loops that have gone wrong.

  • Per address, before authentication. 300 requests per minute from one client address, counted before the key is checked and whatever the plan. A flood of bad keys is stopped before it costs a lookup. This bucket is shared by every request from that address, dashboard sessions included, so a revoked key in a tight loop can lock an office or a CI runner out for a minute.
  • Heavy routes. Endpoints marked heavy route in the reference run expensive aggregations or reach out to DNS. Across all of them, an organization’s keys get 120 requests per hour. This hour starts at your first heavy request rather than at the top of the clock hour, no header reports what is left of it, and the Retry-After on its 429 can run to the end of that hour. Cache these responses.
  • Concurrency-capped routes. The heavy routes marked concurrency-capped may only run a few at a time per organization. A request that cannot get a slot within a couple of seconds gets 503 with Retry-After. Those slots are shared with people using the dashboard in your organization, so a tight polling loop can slow your own team down.

In front of all of them, the edge caps bursts and concurrent connections per client address. A client that trips it receives 429 with no body and no headers until its rate drops. Abuse that puts the service at risk is covered by the Terms, but we would rather hear from you first: if you have a legitimate reason to exceed these limits, such as a one-time backfill, write to contact@dmarcguard.io before you start.

Pacing a client

  • Read X-RateLimit-Remaining and slow down before it reaches zero, rather than retrying on 429.
  • Spread scheduled work across the hour instead of running everything at the top of it, when the budget has just reset for every other client too.
  • Prefer one aggregated call to many small ones: the organization overview and domain health endpoints already join what a dashboard needs.
  • Use limit up to 200 when paging; more rows per request means fewer requests.

Search the guides, the API reference and the learn articles.