Rate Limiting Policy

Rate Limiting Policy

Core data import requests are subject to two independent limits: a request limit and a record
limit
. Both are evaluated on every request, and a request is rejected when either is exceeded.

Limits are applied at the organization level rather than per client or per API key. Where
several integrations import into the same organization, a single allowance is shared between them.
Organizations belonging to a holding are additionally subject to a shared holding allowance.

Request limit

ScopeLimit
Organization500 requests per minute
Holding2,500 requests per minute

This limit counts requests irrespective of their contents.

Record limit

Import endpoints are additionally metered by the number of records contained in the request
body, as each record generates one unit of downstream processing. A maximum of 100 records may
be submitted per request.

EndpointPer organizationPer holding
Contacts600 records per minute (burst 1,000)900 records per minute (burst 1,500)
All other core data types3,000 records per minute (burst 5,000)4,800 records per minute (burst 8,000)

Contacts are subject to a lower allowance because contact records require more downstream
processing than other core data types.

Allowance replenishment

The record allowance is replenished continuously rather than reset at fixed intervals. Submitted
records reduce the available balance; elapsed time restores it at the sustained rate, up to the
burst ceiling stated above.

Two properties follow. No window boundary applies, so there is no fixed time at which the allowance
resets. The balance does not accumulate beyond the ceiling, so an extended idle period confers no
greater allowance than a short one.

Example — contacts, 100 records per request

ConditionResult
Balance at ceiling following an idle period1,000 records available
10 consecutive requests submittedAll accepted
An 11th request submitted immediatelyRejected, with Retry-After: 10
A request submitted after 10 secondsAccepted; 100 records have been replenished
Submission continued at that rateSustained throughput of one request per 10 seconds
Submission suspended for 100 secondsBalance restored to the 1,000-record ceiling

Effective limits by batch size

The record limit is the binding constraint for batch imports. The request limit becomes binding only
where requests contain few records.

Records per requestContactsAll other types
100 (maximum)10 requests, then 1 per 10 seconds50 requests, then 1 per 2 seconds
10100 requests, then 1 per second500 requests, then 5 per second
1Request limit applies: 500 per minuteRequest limit applies: 500 per minute

Each value indicates the number of requests accepted immediately from a full balance, followed by
the sustained rate thereafter.

Exceeded limits

A request exceeding either limit receives a 429 Too Many Requests response.

Whether it carries a Retry-After header depends on which limit was exceeded:

Limit exceededRetry-AfterRecommended client behaviour
Record limitPresent, in whole secondsWait exactly the stated interval
Request limitNot presentRetry using your own backoff interval

The record limit's value is calculated from how far the request exceeded the remaining allowance,
so waiting the stated interval is the fastest route to a successful retry.

Rejected requests have no side effects in either case. No records are imported, no partial
import is recorded, and no import history entry is created. The identical request body may be
resubmitted once the applicable interval has elapsed; no deduplication or reconciliation is
required.

HTTP/1.1 429 Too Many Requests
Retry-After: 10

{
  "errorCode": "TOO_MANY_REQUEST",
  "message": "Import record budget exhausted. Retry after 10 seconds.",
  "requestId": "..."
}

Implementation guidance

  1. Observe the Retry-After header where it is present. Its value is derived from how far the
    request exceeded the remaining allowance rather than from a fixed backoff interval, so a retry
    submitted before the stated interval has elapsed is rejected again. Where the header is absent,
    which is the case for the request limit, apply your own backoff interval.
  2. Base pacing on the header rather than on the published values. The limits stated above are
    current values and are subject to change. Integrations that pace on Retry-After remain
    compliant if they are adjusted.
  3. Submit full batches. A request containing 100 records consumes the allowance considerably
    more efficiently than 100 requests containing one record each.
  4. Account for concurrent importers. Where several processes import into the same organization
    the allowance is shared, and repeated pacing should be expected. Waiting the stated interval
    admits the retry unless another request consumes the replenished allowance first.
  5. Submit large migrations at a steady rate. A one-off import of several hundred thousand
    records will be paced. Steady submission completes in the same total time as submission in
    concentrated bursts, with fewer rejections.

Import status

Requests to the import status endpoint contain no records and are subject to the request limit only.


Did this page help you?