Skip to content
TruePointTruePointData

Documentation

Errors

Every failure the API returns, in RFC 9457 problem+json — and which of them cost you credits.

Errors are returned as RFC 9457 problem details with the content type application/problem+json. The HTTP status tells you the class of failure; the `code` member names the specific one, and is the value to branch on in code — never the `title`, which is prose we may reword.

json
{
  "type": "https://truepoint.in/errors/insufficient_credits",
  "title": "Insufficient credits",
  "status": 402,
  "code": "insufficient_credits",
  "detail": "This call costs 1 credit; balance is 0.",
  "balance": 0,
  "required": 1
}

`type` is a URI: the code appended to https://truepoint.in/errors/. Some errors carry extra members beyond the standard four — insufficient_credits carries balance and required, rate_limited carries retryAfterSeconds — so you can act on the failure without a second call.

StatusTypeWhat it means
422validation_errorThe request failed validation — a missing identifier, or a value we could not parse. 422 rather than 400: the request was well-formed, its contents were not.
401invalid_tokenMissing, malformed, unknown or revoked API key. All four answer identically on purpose — the endpoint must not confirm which keys exist.
403insufficient_scopeThe key is valid but was not minted with the scope this endpoint requires.
402insufficient_creditsThe balance cannot cover this call. Nothing was charged and nothing was returned. Carries `balance` and `required`.
429rate_limitedToo many requests for this key. Carries `retryAfterSeconds`. Retries are safe and are not billed.
500internalSomething failed on our side. Nothing was charged. Retry with backoff.

A no-match is not an error at all

There is no error code for "we found nothing", and that is deliberate. A miss answers 200 with matched:false and charges nothing. A lookup that finds nothing is a normal outcome, not a fault, and giving it a 4xx is how integrations end up treating our coverage gaps as outages — retrying them, alerting on them, and eventually routing around a working endpoint.

So branch on the `matched` field, not on a status code. Do not retry a miss: the answer will not change until the graph does.

What to retry

  • 429 rate_limited — wait the `retryAfterSeconds` the body carries, then retry. Always safe. (The interval is in the body rather than a Retry-After header; read it from there.)
  • 500 internal — retry with exponential backoff and a cap. Always safe: nothing was charged.
  • 5xx without a problem body — treat as 500.
  • 422, 401, 403 and 402 — never retry. The request will fail identically until something on your side, or your plan, changes.

Retries are safe by construction

Send an `Idempotency-Key` header on any billable call. If a request with that key has already succeeded, we replay the original response instead of re-executing it — so a retry after a timeout cannot double-charge you. Use a fresh key per distinct call and reuse it only for retries of that same call.