Concepts

Errors

The API returns conventional HTTP status codes. The body is always JSON in the shape { "error": "<machine_readable_code>" }. Human descriptions are intentionally not returned, as they can leak which keys exist, which IPs are allowlisted, and which credentials are valid.

Status code reference

Code error value Meaning
200 n/a Success.
400 invalid_cve_id The path didn't match CVE-YYYY-N{4,7}.
401 unauthorized Credential failure: missing, malformed, expired, or revoked key, or IP not allowed. Intentionally uniform.
402 insufficient_credits Organisation balance below 1 credit.
404 not_found Route doesn't exist, or the CPE vendor, product, or version isn't tracked.
405 method_not_allowed Only GET (and OPTIONS) are supported.
500 internal Unexpected server error. Email support with the x-request-id.

Why all credential errors look the same

Bad token, revoked key, expired key, IP not on the allowlist: all return:

{ "error": "unauthorized" }

…with no extra detail. This stops an attacker holding a leaked key from enumerating which credentials and IP rules you have in place.

If you're integrating and can't tell why you're getting 401s, the dashboard's Audit log shows the real reason for every authentication failure on your keys.

Always provided

Every error response also includes:

  • x-request-id header (quote this in support tickets).
  • x-credits-remaining once a charge has been attempted.

Retry strategy

Code Retry?
402 insufficient_credits No: top up credits first.
401 unauthorized No: fix the credential or IP allowlist, then retry once.
5xx internal Yes: exponential back-off, max 3 attempts.
Don't retry 4xx blindly

Retrying a 401 or 402 in a tight loop will never succeed. Fix the credential or top up credits before retrying.