Rate Limiting
Understanding and Managing Procore API Rate Limits
Overview
Procore’s API has two rate limits to help keep the platform reliable: a spike limit (10-second window) and an hourly limit (60-minute window). Each limit is a number of requests, set for your app.
Procore counts requests separately for each user of your app, so one user’s calls never use up another user’s requests. A user’s count covers every company where they use your app. With Service Account Authentication, Procore keeps a separate count for each company.
Most responses include one set of rate limit headers. They usually describe the spike limit and switch to the hourly limit once it’s used up. See Interpret Rate Limit Headers.
Limits are set per app. An increase applies to your whole app, raising the limit for every user. It doesn’t carry over to your other apps, and requests from one app never count against another.
What Counts Against Your Limit
Every request your app sends counts against your rate limit, including requests that fail. A 400, 403, or 404 response consumes quota exactly like a successful call.
This matters more than it first appears. An app with a high client-error rate can spend a substantial share of its hourly allocation on calls that return nothing useful — malformed requests, calls to resources the app lacks permission for, or requests to routes that do not exist. Fixing those errors can recover meaningful capacity without any change to your limit.
Use the API Call Activity Report to see your error distribution by status code and endpoint.
Interpret Rate Limit Headers
Procore doesn’t send separate headers for the spike and hourly limits. Responses usually report the spike limit. The hourly limit typically appears only once it’s used up, so its first headers already show 0 remaining.
There are three important rate limit headers returned when making a request to the Procore API. These values reflect your current limits. They can change at any time, so your application should always read and adapt to them.
| Header | Explanation |
|---|---|
| X-Rate-Limit-Limit | The total number of requests allowed for the limit currently being reported (hourly or spike). |
| X-Rate-Limit-Remaining | How many requests are remaining for the limit currently being reported. For short-term windows, this value may increase again after a brief pause as the window rolls forward. |
| X-Rate-Limit-Reset | The Unix timestamp (in seconds) when the currently reported window resets. |
How to use the headers
Use the rate limit headers to pace requests without needing separate logic for the hourly limit vs the spike limit.
- Read
X-Rate-Limit-Remainingon every response that includes it. - When
X-Rate-Limit-Remainingreaches0, pause requests until afterX-Rate-Limit-Reset, then resume processing. - If your app makes concurrent requests (for example, multi-threaded or trigger-based), enqueue work and control throughput by tuning concurrency (such as adjusting thread pool size).
Best practice: Treat the headers as the source of truth and throttle based on the current response, not on a limit you assume or hardcode.
For sample code that reads the headers and tells the spike limit from the hourly limit, see Handle Rate Limits.
Example response headers
X-Rate-Limit-Limit: <the spike limit, or the hourly limit once it's used up>
X-Rate-Limit-Remaining: <requests left in the current window>
X-Rate-Limit-Reset: <Unix timestamp when that window resets>
When Requests Are Throttled
To ensure platform stability, Procore may throttle API traffic in the following ways. When you are throttled, inspect the HTTP response code and headers to determine the correct course of action.
Hourly and Spike Limits (429 Too Many Requests)
You will receive a 429 Too Many Requests status code if you exceed either the hourly limit or the spike limit.
While the response body for both may be similar, a 429 can be triggered by either limit type (hourly or spike).
What to do when you get a 429
- Read
X-Rate-Limit-Resetand pause requests until after that time before retrying. - Retry with backoff (and jitter, if possible) to avoid immediate re-throttling.
- If you generate requests concurrently (for example, with multiple threads or trigger-based workflows), enqueue work and control throughput by tuning concurrency (such as adjusting thread pool size).
- For webhook-driven integrations, enqueue events in a database and process them once your rate limit refreshes.
- Log
429responses so you can monitor patterns and tune your request pacing.
What not to do
- Don’t keep sending requests while over the limit.
- Don’t assume a single fixed window or hardcode a limit value. Always use the current response headers as the source of truth.
Heavy Load Throttling (503 Service Unavailable)
In rare instances when the Procore platform is experiencing exceptionally heavy load, we may temporarily throttle traffic to maintain overall system health. In these situations, you will receive a 503 Service Unavailable response.
This response indicates that while your request is valid, the service is currently unable to process it. To handle this, inspect the Retry-After header, which will specify the number of seconds you should wait before retrying the request.
Tips for Working Within the Rate Limit
Follow these practices to reduce the chance of hitting rate limits and to build resilient applications.
- Always check the
X-Rate-Limit-*rate limit headers and adjust dynamically. - If your app makes concurrent requests (for example, multi-threaded or trigger-based), enqueue work and control throughput by tuning concurrency (such as adjusting thread pool size).
- Use index actions to fetch collections in one request instead of requesting individual objects.
- Cache results whenever possible, especially for public or repeated data.
- Subscribe to webhooks for change detection and reduce how often you poll. Polling on a short interval spends most of your quota confirming that nothing changed. Keep polling as a lower-frequency reconciliation pass rather than your primary way of detecting updates.
- Review your app’s API Call Activity Report to understand and optimize request patterns.
Request a Higher Limit
If your app consistently approaches its limit after you have applied these practices, you can request an increase. Approval depends on your production traffic, your backoff behavior, and your error rate. See Request a Rate Limit Increase.