Blog

Which enrichment API errors to retry, and which ones cost a credit if you do

Only 429, 502, and 503 are worth retrying. Retry a 404 and you pay a credit every time. The full status table, which codes are free, and the backoff that works.

The Triguna team 30 August 2026

This API returns eight status codes you will actually see in production. Two of them cost you a credit. The other six are free. Retrying the wrong one is how you pay twice for a single failure.

The only two billed statuses are the two that answered you

A credit buys a retrieval, not a freshness guarantee, so the price attaches to any lookup that ran to an answer. A 200 from the Person API or the Company API is an answered lookup. A 404 is also an answered lookup: you asked whether a record exists at that identifier, and the answer came back “no”. Both charge one credit and report it in X-Credits-Charged: 1. Everything else fails before it retrieves anything, so it is free.

That single rule decides the whole retry policy. Retrying a free status wastes wall-clock. Retrying a 404 wastes money, one credit per attempt, for an answer that will not change.

The whole table

Status  Meaning                         Billed   Retry?
200     record returned                 1 credit no, you already have it
404     valid lookup, no record         1 credit never, it costs a credit each try
400     malformed identifier            free     no, fix the input
401     bad or missing ApiKey           free     no, fix the key
402     out of credits                  free     no, top up
429     rate limited                    free     yes, honour Retry-After
502     bad gateway                     free     yes, bounded backoff
503     service unavailable             free     yes, bounded backoff

Never retry the client-side four

400, 401, 402, and 404 all describe a condition a retry cannot change. The identifier is still malformed on the second attempt, the key is still wrong, the balance is still zero, the record still does not exist. A 402 is loud about it:

HTTP/1.1 402 Payment Required
content-type: text/plain; charset=utf-8

insufficient credits

That body is free to receive, which is the one mercy here: running out of credits does not cost a credit. Top up on the pricing page and continue. The 404 is the expensive trap, because it looks retryable and is not. Most 404s come from four input mistakes, a display name where a slug belongs being the common one, and each retry bills again. Resolve the identifier before you spend, which is the whole subject of why a lookup 404s when the identifier looks correct.

Retry the server-side three, on the server’s terms

429, 502, and 503 are transient and free. They are worth retrying because the same request can succeed a moment later. The rule is to back off on the server’s schedule, not your own. A 429 carries the only signal that reflects real server state:

HTTP/1.1 429 Too Many Requests
Retry-After: 2
X-RateLimit-Remaining: 0

Honour Retry-After when it is present, fall back to exponential backoff when it is not, add jitter so a throttled batch does not retry in lockstep, and bound the attempts so a persistent outage does not become an infinite loop. In Node:

const RETRYABLE = new Set([429, 502, 503]);

// Retries only the three transient statuses. 400, 401, 402, 404 return immediately.
async function lookup(url, { max = 3 } = {}) {
  for (let attempt = 0; ; attempt++) {
    const res = await fetch(url, { headers: { ApiKey: process.env.TRIGUNA_KEY } });
    if (!RETRYABLE.has(res.status) || attempt >= max) return res;
    const after = Number(res.headers.get('Retry-After'));
    const wait = Number.isFinite(after) && after > 0 ? after * 1000 : 2 ** attempt * 1000;
    await new Promise((r) => setTimeout(r, wait + Math.random() * 250)); // jitter
  }
}

The published rate is 10 requests per second, but as a separate post on rate limits that ignore your request rate documents, a 429 often has nothing to do with your throughput, so tuning a throttle against it is usually wasted work. Back off, jitter, bound, and put the effort elsewhere.

Why the split matters at volume

On a single lookup the difference is invisible. On a backfill it is the whole cost model. A run that retries every non-200 treats a 404 like a 502 and pays a credit for each doomed attempt; a run that reads the table above spends exactly one credit per real answer and zero on the free failures. The pattern for pacing a large job without overspending is in running a nightly backfill, and the same free-versus-billed logic keeps a bad identifier from blocking the request path when you enrich a user on signup.

The full status conventions live in the errors reference. The short version fits on a sticky note: two codes are billed because they answered you, three are worth a bounded retry, and the rest are yours to fix before you send.

Next

error-handlingreliabilitycost

Start with one request

Free credits on signup, no card required. Usage-based pricing after that.