Skip to main content

Rate limits

The API limits how many requests you can send, to keep the platform stable for everyone. Design your integration to stay within the limit: requests over it are rejected, which wastes your own resources and slows down your application.

Design for the limit, don't rely on retries

Retrying after a rate-limit error is a safety net, not a strategy. If your integration regularly gets 429 responses, it is sending too fast. Throttle your requests on your side before sending them; don't use the API to regulate your traffic.

The limit​

API requests are limited to 10 requests per second per workspace by default. Requests over the limit get a 429 Too Many Requests response.

  • One limit for the whole workspace. All API keys of a workspace share it. Splitting traffic across several keys doesn't raise it.
  • A one-second window. The limit counts requests in the last second, with no extra allowance for bursts.
  • No other limits. There are no daily or per-endpoint limits on the API.
  • Rejected requests don't count. Requests that fail with 401 or 403 (invalid key, wrong scope, IP not allowed) don't use up the limit.

Stay within the limit​

  1. Throttle on your side. Put requests in a queue and send them at a steady rate that stays within the limit.
  2. Spread requests evenly. Avoid bursts: a single webhook that triggers 50 API calls at once goes over any limit.
  3. Use bulk imports for data that isn't needed in real time. To sync historical data or large batches, use the bulk import endpoints (for deals, contacts and products) instead of one request per record.

Handle 429 Too Many Requests​

Even with throttling, an occasional 429 can happen during a traffic spike. The response tells you how long to wait: in seconds in the retry-after header (for example retry-after: 1), and in the body:

{"detail": "Request was throttled. Expected available in 1 second."}
HEADER CASING

The API sends the header in lowercase, retry-after, not as Retry-After. If your HTTP client reads headers case-sensitively (for example raw header access in JavaScript), response.headers["Retry-After"] is undefined; read response.headers["retry-after"] instead. Libraries such as Python requests read headers case-insensitively.

When you get a 429:

  1. Pause. Read the retry-after header and wait that many seconds before retrying.
  2. Queue. Keep the waiting requests in a queue and send them at a sustainable rate.
  3. Log. Record every 429, so you can see if your integration is consistently too fast.
import time
import requests

def api_request_with_retry(method, url, headers, data=None, max_retries=5):
for attempt in range(max_retries):
response = requests.request(method, url, headers=headers, json=data)

if response.status_code != 429:
return response

retry_after = int(response.headers.get("retry-after", 2 ** attempt))
time.sleep(retry_after)

return response

Monitor 429 responses​

If you see 429 responses regularly, treat it as a bug in your integration, not as normal behavior. Track how often they happen and adjust your throttling.