API reference

Errors

Every stable error code with its HTTP status, meaning and what to do about it.

All errors share one shape. Codes are stable; messages are safe to show to developers and end users but may be reworded.

Error body
{
  "error": {
    "code": "ORIGIN_UNAUTHORIZED",
    "message": "This origin is not allowed for the site key."
  }
}

details is present for VALIDATION_FAILED (issues: [{ path, message }]) and some service errors. RATE_LIMITED responses from per-minute buckets include Retry-After: 60.

Codes

CodeHTTPMeaningWhat to do
INVALID_REQUEST400The request is malformed.Check the request shape against the reference.
INVALID_JSON400The request body must be valid JSON.Send a syntactically valid JSON body; empty bodies are treated as {}.
UNSUPPORTED_MEDIA_TYPE415Send a JSON request body with Content-Type: application/json.Set Content-Type: application/json.
BODY_TOO_LARGE413The request body is too large.Keep bodies under 32,000 bytes.
NOT_FOUND404The requested resource does not exist.Check the path and id; owned resources only.
METHOD_NOT_ALLOWED405This method is not supported for this resource.Use the method listed for the endpoint.
AUTHENTICATION_REQUIRED401Sign in to continue.Send Authorization: Bearer with a session token (or a reg_ token on /registration/keys).
INVALID_SESSION401Your session is invalid or has expired. Sign in again.Sign in again and use the fresh access token.
FORBIDDEN403You do not have access to this resource.The session may not access this resource.
RATE_LIMITED429Too many requests. Try again shortly.Wait for Retry-After seconds. On /verify after 10 attempts, request a new challenge.
SITE_KEY_INVALID400The site key is not recognized.Copy the site key from the dashboard; it starts with site_live_ or site_test_.
SITE_DISABLED403This site is disabled.Re-enable the site with PATCH /sites/:id {status:"active"}.
ORIGIN_UNAUTHORIZED403This origin is not allowed for the site key.Serve the page from https://<domain> or a subdomain, or add the origin to allowed_origins.
ORIGIN_REQUIRED400An Origin header is required to create a challenge.Include an Origin header (browsers do; server-to-server callers must add it).
CHALLENGE_NOT_FOUND404The verification challenge does not exist.Verify the ch_ id; challenges are not listable.
CHALLENGE_EXPIRED410The verification challenge has expired.Create a new challenge; raise ttl (max 300) if agents need more time.
CHALLENGE_CONSUMED409The verification challenge has already been used.The challenge already verified. Read GET /challenges/:id for the result, or create a new one.
CHALLENGE_NOT_PENDING409The verification challenge is no longer pending.The challenge was rejected. Create a new one.
CHALLENGE_MISMATCH400The proof does not match the challenge.Make challenge_id (or the Web Bot Auth nonce) match the challenge you fetched.
AGENT_UNKNOWN404The agent is not registered.Check agent_id; the agent may have been deleted.
AGENT_DISABLED403The agent is disabled.The owner must POST /agents/:id/enable.
AGENT_REVOKED403The agent has been revoked.Permanent. Create a new agent.
KEY_UNKNOWN404The signing key is not registered for this agent.The key_id does not belong to this agent.
KEY_REVOKED403The signing key has been revoked.Sign with an active key; rotate if needed.
KEY_PENDING403The signing key has not completed registration.Complete the registration challenge for this key first.
KEY_INVALID400The public key is not a valid Ed25519 key.Provide a 32-byte Ed25519 public key (raw base64url, SPKI, PEM or OKP JWK).
KEY_LIMIT409This agent already has the maximum number of active keys.Revoke an unused key; the maximum is five non-revoked keys per agent.
SIGNATURE_INVALID400The signature could not be verified.Rebuild the signature base exactly as documented and sign its UTF-8 bytes.
SIGNATURE_MALFORMED400The signature is malformed.Send all proof fields with the right types; signature must be base64url of 64 bytes.
SIGNATURE_EXPIRED400The signature timestamp is outside the accepted window.Sync the clock; created must be within 60 s of server time.
SIGNATURE_AGENT_UNAVAILABLE502The Signature-Agent key directory could not be retrieved.Make the key directory reachable over https without redirects and under 64 KiB.
TEST_MODE_REQUIRED400Simulation is only available for test-mode challenges.Simulation works only with site_test_ challenges.
TOKEN_INVALID400The verification token is invalid.Pass the exact token from the widget; do not modify or truncate it.
TOKEN_EXPIRED400The verification token has expired.Tokens live 10 minutes; verify promptly after the widget reports success.
TOKEN_SITE_MISMATCH400The verification token was issued for a different site.Verify with the site key that created the challenge.
TOKEN_ALREADY_USED409The verification token has already been consumed.Each token is single-use; treat a second presentation as replay.
TOKEN_TEST_MODE400The token was issued in test mode.Use a live site key, or pass allow_test: true outside production.
REGISTRATION_TOKEN_INVALID401The registration token is invalid, expired or already used.Mint a new registration token; they expire after 15 minutes and are single use.
VALIDATION_FAILED422Some fields are invalid.Read details.issues for the failing fields.
CONFLICT409The request conflicts with the current state.See the message: duplicate key, or an account limit reached.
SERVICE_UNAVAILABLE503The verification service is temporarily unavailable.Retry with backoff; check /api/v1/health.
INTERNAL_ERROR500Something went wrong on our side.Retry; include X-Request-Id when reporting.

Client-side codes

The SDKs, the CLI and the widget raise a few codes of their own before a request reaches the API. They never appear in an HTTP response body.

CodeRaised byMeaning
NETWORK_ERROR@imnotahuman/agent, @imnotahuman/serverThe API could not be reached.
REQUEST_FAILED@imnotahuman/agent, @imnotahuman/server, websiteThe response was not JSON or carried no error code.
INVALID_RESPONSEwebsiteThe response body could not be parsed.
INVALID_PRIVATE_KEY@imnotahuman/agentThe private key is not a 32-byte Ed25519 seed or PKCS#8 PEM.
INVALID_CHALLENGE@imnotahuman/agent, CLIThe argument is neither a ch_ id nor a challenge URL.
NOT_REGISTERED@imnotahuman/agent, CLINo agent id / key id yet; run init or register first.
WIDGET_LOAD_FAILED@imnotahuman/reactwidget.js did not load or initialise.