Skip to content
firmus.shdocs

Every page's text, headings and title. Code samples are not indexed.

Rate limits

The four allowances, the headers that report them, and what 402 and 429 mean.

Four allowances exist, and which of them apply depends on the key, the plan and the endpoint. They are checked cheapest first, and any of them can refuse a request.

PolicyCounted perApplies to
public-ipCalling address, per dayPublishable keys, on every plan
requestsOrganization, per secondEvery key
quotaOrganization, per calendar monthSecret keys on Free, which includes 1 000 lookups a month
rowsOrganization, per calendar month/resolve, /enrich and file-job rows, counted together, on every plan: 1 000 on Free, 25 000 on Pro, 250 000 on Scale

The per-second rate is bought by the organization, so minting more keys does not buy more of it. On a paid plan lookups are unlimited and the quota policy is absent from the headers entirely: outside /resolve, /enrich and submitting a file job, the rate is the whole of what bounds you. The console still shows your calls this month.

One request is one call; there is no per-result unit. A resolve or enrich batch is one call too, however many rows it holds, and its rows are counted separately, against rows: each row it looks up is one row, and a row repeated in a batch counts each time. A file job reserves its rows when it is admitted — every remaining row, once per step — and until it finishes those count as used here, so rows shows them as spent and a batch is not admitted on them. A batch can also be refused with 429 concurrency_limited, which no RateLimit member counts; see errors.

A plan's published rate is the ordinary one, and a contract can set a different one for a single account — so your own RateLimit-Policy header is the authority on what you are allowed, not the number beside your plan on the pricing page.

A publishable key gets a free lane on every plan: the first 100 calls a day from any one calling address are never counted against anything. Above that lane the plan decides — Free refuses with 429, and a paid plan serves the call within the plan's own per-second rate. A publishable key cannot call resolve or enrich. The lane is per address, not per key.

Reading your allowance

Every response that had to ask the question carries both headers — a 200, a 404 and a 429 alike — so a client can pace itself without first being refused. They are the IETF draft's structured lists, one member per policy in force:

RateLimit-Policy: "requests";q=15;w=1
RateLimit:        "requests";r=14;t=1

That is a Pro key's whole header on every endpoint but /resolve, /enrich and POST /v1/{country_code}/jobs. Those three add a rows member, on every plan:

RateLimit-Policy: "requests";q=15;w=1, "rows";q=25000
RateLimit:        "requests";r=14;t=1, "rows";r=18700;t=1209600

On Free there is a quota member on every endpoint, because Free is the one plan with a monthly allowance of lookups. On /resolve and /enrich the order is requests, quota, rows:

RateLimit-Policy: "requests";q=2;w=1, "quota";q=1000
RateLimit:        "requests";r=1;t=1, "quota";r=873;t=1209600

q is what the policy allows, w its window in seconds, r what is left and t the seconds until it resets. quota and rows carry no w: a calendar month is not a window, and t already says when it ends. The numbers above are examples — read your own out of the response rather than hard-coding them.

A refusal adds Retry-After, in seconds. All three headers are exposed through CORS.

If a policy's member is absent, that allowance is not in force for this request. On a paid plan there is no quota member at all, and outside /resolve and /enrich there is no rows member; there is nothing to infer from either absence except that no allowance is being spent.

public-ip can read r=0 on a response that succeeded. On a paid plan, a publishable call past the free lane is served, the policy reports zero remaining, and no Retry-After is written. Read the absence of Retry-After as the signal: r=0 with one means you were refused, r=0 without one means the call went through.

The window is fixed, and aligned to the clock

The per-second limit is counted into one fixed bucket per clock second — the boundary falls where the clock says, not where your first request did — with no burst allowance and no smoothing on top of it. Two things follow, and they are easier to hold together than apart.

Inside one clock second the number is absolute. At 15 requests per second the sixteenth request in the same second is refused: not fifteen a second on average over a minute, and no credit carried from a quiet second into a busy one. The published figure is a sustained limit and an instantaneous one at once. A caller that paces itself at the number never sees a 429; one that fires forty inside a single clock second and none in the next two sees twenty-five of them refused.

Across a boundary the two buckets are independent. A full allowance spent in the last instant of one clock second and another full allowance in the first instant of the next are both allowed, so an arbitrary moving one-second span can hold up to twice the limit. That is a property of the fixed window rather than an allowance on offer: the next boundary arrives when the clock reaches it and not when your burst does, so there is nothing there to plan against. Size a batch job against the published number and it will never meet either edge.

The same is true of public-ip, whose window is a UTC day: 100 a day means 100 per UTC day, and the counter starts again at midnight UTC rather than 24 hours after your first call.

The rung is keyed on the organization, not on the calling address. Every key you hold draws on the same per-second bucket, and so does every one of your users. A browser autocomplete emitting three or four calls a second per visitor therefore saturates Free with one person typing and Pro with roughly four — which is the case to size for if you are putting a search box in front of the public, and the reason the publishable key's free lane exists beside it.

The monthly allowances are spent, not paced

quota and rows refuse with 402 quota_exceeded rather than 429: they are allowances, and they return at the start of the next calendar month, UTC, rather than in a second. Retry-After on the refusal counts the seconds to that instant.

  • quota exists on Free alone. On Pro and Scale lookups are unlimited, and no endpoint but /resolve, /enrich, POST /v1/{country_code}/jobs, the two that add watched numbers, a segment save and a segment export can answer 402.
  • rows exists on every plan, on /resolve, /enrich and POST /v1/{country_code}/jobs only. It is the one 402 a Pro or Scale key can meet. Beyond a plan's figure is the next plan; beyond Scale's 250 000 a month, more rows are a contract rather than a plan. On Free a batch needs both: one lookup left for the call, and one row left for its rows.

The code is quota_exceeded for both. To tell which one refused, read the member at r=0 in the response's RateLimit header.

A third 402 quota_exceeded is not a policy and has no member in these headers: the watched companies of a plan, 5 on Free, 1 000 on Pro, 10 000 on Scale, refused when POST /v1/{country_code}/watchlists or POST /v1/{country_code}/watchlists/{id}/watches would add more numbers than are left. It carries no Retry-After, because no month frees it: removing watched numbers does. The watch configuration endpoints are not counted as calls, and the watched-events feed is one call per page; the requests rate applies to all of them. See watch companies.

Two more have no member in these headers either. The saved segments of a plan, 3 on Free, 100 on Pro, 1 000 on Scale, refused when POST /v1/{country_code}/segments with save: true would save one more, carry no Retry-After: deleting a segment frees its place. The exported rows, 1 000 a month on Free, 25 000 on Pro, 250 000 on Scale, refused when a segment export does not fit in what is left this month, carry Retry-After to the start of the next calendar month, UTC. Running a segment is one call, like a lookup; listing and deleting saved segments are not calls. See run a segment.

It bites on the next request. Both are checked before a request is served and counted once it is. A batch is one call, so it never takes you past quota. Against rows it is admitted while any row is left, so it can take you past the allowance by up to its own size, 500 rows. The batch after it is refused. A file job is checked differently: it is admitted only if all of its rows, once per step, fit in what is left. Treat 402 as "stop until the month rolls over or the plan changes", and the quota and rows members as the numbers to watch on the way there.

Calling from a browser

Any origin may call /v1. There are no cookies and none are read: the key is the whole of the credential. Alongside the three rate-limit headers, ETag and X-Request-Id are readable cross-origin — quote X-Request-Id when reporting a problem.

Sending a publishable key as ?key= avoids a preflight on every keystroke, and works on /suggest alone. Everywhere else a publishable key travels as Authorization: Bearer and costs one preflight, which the browser caches for up to a day — Chromium caps it at two hours. Authentication covers why the query form is the narrower one.