Error body shape
On any error, return a JSON body with anerror string. HunterAI reads it into the failure
detail it records for the sync:
Status codes
“The entity fails” means that one entity (e.g.
/leads) is marked failed for the run;
entities that already committed stay committed, and the remaining entities still run.
The overall sync is reported failed whenever any entity fails — including an
optional one. The single exception is a 404 on an optional endpoint, which is not a
failure at all. See Partial success.401 Unauthorized
- No retry — HunterAI stops the entity the instant it sees
401. - Nothing from an unauthenticated call is ingested.
- Every entity in the run hits the same
401, so the whole sync ends failed.
404 Not Found
404 is how you declare an optional endpoint unimplemented.
429 and 5xx errors
429 and the three transient server codes — 502, 503, 504 — are retried up to
5 times before the entity fails. Every other 5xx is terminal on the first response.
429— HunterAI waits for the larger of yourRetry-Afterheader (seconds, floored to 1s) and an exponential backoff (1, 2, 4, 8, 16s).502,503,504— HunterAI backs off exponentially (1, 2, 4, 8, 16s) and retries. A request that times out is retried the same way.500,501,505, and any other5xx— no retry. The entity fails the moment the response arrives, exactly like a hard4xx.
Other 4xx — hard failure
400, 403, 422, and any other 4xx that is not 401, 404, or 429 fail the entity
immediately with no retry. Reserve these for genuine client errors; do not use them for
throttling (use 429) or transient issues (use 503).
Malformed records — null or missing id
A 200 page can still carry an unusable record. Every entity’s id is required and
non-nullable (see each endpoint’s field table), because HunterAI keys the record on it.
A record whose id is null or absent — and, for /events, a null
or absent lead_id — is rejected, not stored.
Rejected record (null id)
- No retry. This is a data error, not a transient one — retrying the same page would fail identically. The entity is marked failed the moment the bad record is seen.
- No silent coercion. A
nullid is never turned into a placeholder. Earlier releases coerced it to the string"None", so two null-id records collided on the same key and one silently overwrote the other — that data-loss path is now closed. - Partial success still applies. Pages that already committed before the bad record stay committed, and other entities continue — but the overall sync is reported failed. See Partial success.