Errors and retries
Handle rate limits, validation errors and failed rows in your code.
The error format and limits are in Limits and errors. This guide shows what to do about them.
What to do for each status
| Status | Do this |
|---|---|
401 | Stop. Check the token is correct, enabled and not expired. Don't retry. |
403 | Stop. The token lacks a permission. Change the token, not the code. |
404 | The record or endpoint doesn't exist. Don't retry. |
413 | The body is over 64 KB. Send fewer items per call. |
422 | Validation failed. Read errors by field, fix the data and send again. |
429 | Wait and try again. See below. |
Staying under the limits
The limits are 60 requests a minute per token, 300 per organisation and 120 per IP address. Spread bulk work out, use the 50 item bulk endpoints, and use updated_since instead of reloading everything.
async function call(url, options, tries = 5) {
for (let attempt = 0; attempt < tries; attempt++) {
const res = await fetch(url, options);
if (res.status !== 429) return res;
const wait = Math.min(2 ** attempt * 1000, 30000);
await new Promise((r) => setTimeout(r, wait));
}
throw new Error("Still rate limited");
}
import time
import requests
def call(method, url, tries=5, **kwargs):
for attempt in range(tries):
res = requests.request(method, url, **kwargs)
if res.status_code != 429:
return res
time.sleep(min(2 ** attempt, 30))
raise RuntimeError("Still rate limited")
Bulk calls
Bulk endpoints save each item on its own, so a call can partly succeed. Read the result for every row. Retry only the failed rows after fixing them, not the whole batch.
Use dry_run where it exists to find problems before anything is saved.
Log the message and errors from failed calls. They say what to fix.