Rate Limits
Our APIs limit how often you can call each query and mutation. Sandbox and Production enforce the same limits.
Limits
| API | Applies to | Limit |
|---|---|---|
| Partner API | Each query and each mutation | 250 calls per 60 seconds |
| OAuth App API | Each query | 100 calls per 60 seconds |
How Calls Are Counted
Each query and mutation has its own count. A query or mutation is a top-level field of a request, such as individuals or createOrganization. Calls to individuals do not count against the limit for organizations.
Counts are kept per caller:
- Partner API: per set of API credentials. Every access token issued for the same
client_idshares one count, so a new access token does not reset it. - OAuth App API: per First Dollar user. Each user has one count, shared by every app the user has authorized.
Each selection is one call. Selecting the same query under two aliases counts as two calls.
The window is fixed. It starts with the first call that is counted and lasts 60 seconds. When the window ends, the count resets. Calls that are rejected do not extend the window.
When You Exceed a Limit
The API responds with HTTP status 429 and an error for each query or mutation over its limit. The error has extensions.code set to RATE_LIMITED. extensions.resetAt is when the window resets and extensions.now is when the error was raised, both as ISO 8601 timestamps in UTC from our servers. The response has no Retry-After header. Read code, resetAt and now. Other fields in extensions, such as http, are internal and can change.
query {
individuals(first: 50) {
... on IndividualsResults {
nodes {
id
}
}
}
}
{
"errors": [
{
"message": "Too many requests.",
"locations": [{ "line": 2, "column": 3 }],
"path": ["individuals"],
"extensions": {
"code": "RATE_LIMITED",
"now": "2026-10-14T18:30:12.418Z",
"resetAt": "2026-10-14T18:30:41.007Z",
"http": { "status": 429 }
}
}
],
"data": {
"individuals": null
}
}
A request can select more than one query or mutation. The ones within their limits still run and return data, even though the status is 429. Check errors for each path before you discard the response.
Retrying
- Wait for the reset. Retry a limited query or mutation after
extensions.resetAt. UseresetAtminusnowas the wait, so that clock differences between your servers and ours do not matter. - Back off when you cannot read the reset time. Use exponential backoff with jitter. For example, wait 1 second, then 2, then 4, up to 60 seconds.
- Retry limited calls safely. A query or mutation that is over its limit returns the error without running. A limited mutation is not applied, so retrying it after the reset applies it exactly once.
- Replay idempotent mutations with the same key. When a mutation takes an
idempotencyKeyand you do not know whether it ran, for example after a timeout, retry it with the same key, input and selected fields. The API returns the first result and does not apply the change again. - Reuse your access token. Request a new token when the current one expires, not for each call.