Error codes
Every error response has the same shape:
error response
{
"error": "ERR_<CODE>",
"detail": "Human-readable explanation (optional)",
"...": "extra fields specific to the error"
}Switch on error for programmatic handling. The HTTP status code is also semantically correct (400 / 404 / 429 / 500 etc.) so you can use either. detail is present on most validation errors but omitted on 5xx (server-side leakage prevention) and on some claim errors that already carry their own typed fields.
ERR_NOT_FOUNDHTTP 404Resource doesn't exist (FID, address, or generic 404).
ERR_INTERNALHTTP 500Database / RPC / upstream failure. No detail field is exposed (logged server-side only). Retry; report at github.com/jumpboxtech if persistent.
ERR_FID_INVALIDHTTP 400FID was non-numeric, ≤ 0, or non-integer.
ERR_ADDRESS_MALFORMEDHTTP 400Address didn't match /^0x[0-9a-fA-F]{40}$/.
ERR_PAYLOAD_INVALIDHTTP 400Claim payload missing required fields or with bad shape.
ERR_METHOD_UNSUPPORTEDHTTP 400Claim method not one of: eip191 | jfs | well-known.
ERR_ADDRESS_NOT_VERIFIEDHTTP 422Address not in the FID's verified set at snapshot time. The doctrine: only addresses Farcaster confirms can claim.
ERR_FID_MISMATCHHTTP 422Header/body FID disagrees with the FID derived from the signature/manifest.
ERR_SIG_INVALIDHTTP 400Cryptographic signature did not verify against the claimed signer.
ERR_SIG_EXPIREDHTTP 400Signature timestamp is outside the validity window (default ±15 minutes).
ERR_NONCE_USEDHTTP 409Replay protection: this (fid, method, nonce) was already submitted. Generate a fresh nonce.
ERR_JFS_PAYLOAD_INVALIDHTTP 400JFS token didn't decode as base64url-segmented JWT-style payload.
ERR_JFS_KEY_INACTIVEHTTP 422JFS signer key isn't currently registered as an active app-key for the FID on Farcaster's KeyRegistry.
ERR_JFS_FID_MISMATCHHTTP 422JFS payload FID disagrees with the request header FID.
ERR_MANIFEST_FETCH_FAILEDHTTP 422Couldn't fetch /.well-known/cairn.json from the host (network, 4xx, 5xx, or non-JSON response).
ERR_MANIFEST_ADDRESS_UNVERIFIEDHTTP 422An address in the manifest isn't in the FID's verified set. All-or-nothing: every manifest address must be verified.
ERR_RATE_LIMITHTTP 42960 req/min per IP exceeded. Retry-After: 60 seconds.
ERR_RATE_LIMIT_DAILYHTTP 4292000 req/day per IP exceeded. Retry-After: seconds-until-UTC-midnight.
ERR_RATE_LIMITEDHTTP 429Application-layer rate limit exceeded (claim flow specifically — separate from IP limits).
ERR_RATE_LIMITER_UNAVAILABLEHTTP 503Rate-limit subsystem misconfigured. Server-side bug; retry shortly.
Idempotency
All GET endpoints are idempotent and safe to retry on 5xx. POST /api/claim is replay-protected by a unique constraint — retrying a successful claim returns ERR_REPLAY with the original outcome, not a duplicate side-effect.