CompuDime API docs

Rate limits

Each key has its own budget of requests. Over it, you get 429 with a Retry-After header. A 429 is never charged.

Per key

Each key may send 120 requests a minute. The budget refills all the time, and a key may use a whole minute's budget at once.

It counts every call made with the key: free calls, estimates, and calls that fail. It is checked before anything is billed or sent to the store. One key never uses up another key's budget, except that the keys of one store owner's approval share one budget for each capability, so a replacement key does not start a new one; its live keys and its test keys have one budget each (see Working across stores).

Per plan

The store's plan can also limit billed calls a minute. Over that limit you get the same 429, with Retry-After: 60.

Per address

There is also a high limit on all traffic from one network address. It answers the same 429, with Retry-After: 30. No key was checked yet, so the body has no integrationId or storeId, and its requestId is always one the API made.

What to do on a 429

  1. Wait at least the number of seconds in Retry-After before the next request with that key. It is always there, in whole seconds.
  2. Then go on at a steadier pace.
  3. If 429 comes again, double the wait each time, up to about a minute, and add a random part, so workers that were stopped together do not all retry in the same second.
HTTP/1.1 429 Too Many Requests
Retry-After: 3
Content-Type: application/json; charset=utf-8

{
  "type": "https://api.compudime.com/docs/errors#rate_limited",
  "title": "Too Many Requests",
  "status": 429,
  "code": "rate_limited",
  "detail": "This API key is sending requests too quickly; retry after the number of seconds in the Retry-After header.",
  "requestId": "req_0123456789abcdef",
  "integrationId": "0b9f6c1e-5a44-4d0e-9a3b-2f6d1c7e8a90",
  "storeId": "5d2c7f7e-91a3-4c58-b1de-3e8a4f0c6b12",
  "retryable": true,
  "docsUrl": "https://api.compudime.com/docs/errors#rate_limited",
  "statusUrl": "https://status.compudime.com",
  "support": "mailto:support@compudime.com"
}
// JavaScript
async function callWithBackoff(url, init, maxAttempts = 6) {
  for (let attempt = 0, backoff = 1; attempt < maxAttempts; attempt++, backoff = Math.min(backoff * 2, 60)) {
    const response = await fetch(url, init);
    if (response.status !== 429) return response;
    const retryAfter = Number(response.headers.get("Retry-After")) || 1;
    const waitSeconds = Math.max(retryAfter, backoff) + Math.random();
    await new Promise((resolve) => setTimeout(resolve, waitSeconds * 1000));
  }
  throw new Error("still rate limited after " + maxAttempts + " attempts");
}

A sync that reads 500 rows a page needs few requests a minute. If a real workload needs more, write to support@compudime.com. Do not spread the load over several keys.