v1.22.0
Serves the Turnstile / reCAPTCHA / hCaptcha siteverify contract, so an existing backend integration works against FCaptcha by changing the base URL.
Added
POST /turnstile/v0/siteverify,/recaptcha/api/siteverifyand/siteverifyon all three servers. Form-encoded and JSON bodies;secret,response,remoteip,idempotency_key; the upstream response shape and error-code vocabulary, plusscore.- Tokens carry a signed
hostname,actionandcdata. The hostname is derived server-side fromOrigin(thenReferer), so a backend can reject a token minted on another site or for a different action. FCAPTCHA_VERIFY_SECRET— the credential a backend presents when verifying, separable from the signing key.FCAPTCHA_ALLOWED_HOSTNAMES— optional allowlist of origins permitted to mint tokens.cdataon the client:FCaptcha.execute(siteKey, { action, cdata }).
Breaking
POST /api/token/verify now requires secret. It was previously accepted and ignored, so any caller who could reach the endpoint could spend a token. Set FCAPTCHA_LEGACY_UNAUTH_VERIFY=true to restore the old behaviour for one release.
Fixed
The three servers emitted mutually unverifiable tokens: Go used padded base64url, Node unpadded, and Python signed a payload with different JSON separators. This only surfaced in a mixed fleet, where the instance validating a token is not the one that minted it. All three now emit unpadded base64url over compact sorted-key JSON and accept the old encodings, so rolling deploys and in-flight tokens are unaffected.
See Upgrading to 1.22.0.