HomeDocs

Error Codes

Every API error has the same envelope:

{
  "success": false,
  "error": {
    "statusCode": 400,
    "code": "INVALID_ANSWER",
    "message": "The answer was incorrect, please try again",
    "details": { "remaining": 2 }
  }
}

statusCode is also returned as the HTTP status. details is optional and depends on the error.

4xx — Client errors

CodeStatusMeaning
UNSUPPORTED_CHALLENGE400Unknown challenge type.
INVALID_DOMAIN400Malformed domain name.
INVALID_ANSWER400Wrong answer; details.remaining shows attempts left.
CHALLENGE_EXPIRED400Challenge older than its TTL.
CHALLENGE_SOLVED400Challenge already solved.
CHALLENGE_FAILED400Too many failed attempts.
CHALLENGE_NOT_FOUND404Unknown challenge ID.
INVALID_SECRET400Site secret does not match any site.
TOKEN_SITE_MISMATCH400Token was issued for a different site.
INVALID_TOKEN400Malformed or unsigned token.
TOKEN_EXPIRED400Token older than 120 seconds.
TOKEN_REPLAYED400Token already redeemed — replay attempts are rejected.
INVALID_2FA_CODE400/401Wrong TOTP code.
TWO_FACTOR_NOT_ENABLED4002FA is not enabled for this account.
INVALID_PASSWORD400Current password is wrong.
INVALID_RESET_TOKEN400Unknown/expired password reset token.
INVALID_KEY_PREFIX400Blocked-key input does not start with nlx_.
UNAUTHORIZED401Missing authentication.
INVALID_TOKEN / INVALID_API_KEY / INVALID_REFRESH_TOKEN / INVALID_PREAUTH401Bad or expired credentials.
ACCOUNT_DISABLED403Account deactivated by an admin.
ADMIN_REQUIRED403Admin role required.
DOMAIN_NOT_ALLOWED403Request hostname is not on the site's domain whitelist.
DOMAIN_BLOCKED403Request hostname is on the global blocklist.
SITE_KEY_BLOCKED403Site key is on the global blocklist.
SITE_SUSPENDED403Site has been suspended by an admin.
SCOPE_FORBIDDEN403API key lacks the required scope.
EMAIL_TAKEN409Email already registered.
DOMAIN_EXISTS409Domain already registered for this site.
DOMAIN_ALREADY_BLOCKED409Domain already on blocklist.
KEY_ALREADY_BLOCKED409Key already on blocklist.
NOT_FOUND404Generic resource not found.
SITE_NOT_FOUND404Unknown site.
DOMAIN_NOT_FOUND404Domain not registered for this site.
USER_NOT_FOUND404Unknown user.
API_KEY_NOT_FOUND404Unknown API key.
RATE_LIMITED429Too many requests — retry later.

5xx

CodeStatusMeaning
INTERNAL_ERROR500Unexpected server error.

Handling in the widget

The widget surfaces human-readable messages for the common cases (wrong answer, expired challenge, network error) via onError. Re-verification is automatic after reset().

Handling in your backend

Verify failures must never block a legitimate user permanently. Recommended handling:

if (!result.success || result.score < 0.5) {
  // notify the user, do NOT process the form
}