Build an integrationErrors and retries

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

StatusDo this
401Stop. Check the token is correct, enabled and not expired. Don't retry.
403Stop. The token lacks a permission. Change the token, not the code.
404The record or endpoint doesn't exist. Don't retry.
413The body is over 64 KB. Send fewer items per call.
422Validation failed. Read errors by field, fix the data and send again.
429Wait 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");
}

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.