CAPTCHA handling
An instance can require a CAPTCHA solution on a small set of abuse-sensitive operations. A client reads the selected provider and its site key from instance discovery, renders that provider’s widget, and sends the solution on the gated request.
Discovering the provider
Section titled “Discovering the provider”GET /.well-known/fluxer publishes the CAPTCHA configuration object inside the instance discovery object. Its provider field names the selected CAPTCHA provider, and hcaptcha_site_key or turnstile_site_key is that provider’s site key. The other key is null, and both are null when provider is none.
The value none means the instance challenges no operation. A gated operation then proceeds with no CAPTCHA header. The values hcaptcha and turnstile name the provider whose widget a client renders.
Gated operations
Section titled “Gated operations”The following operations verify a CAPTCHA while discovery reports a provider other than none.
| Method | Route | Operation |
|---|---|---|
| POST | /v1/auth/register | Register an account |
| POST | /v1/auth/login | Log in with a password |
| POST | /v1/auth/forgot | Request password recovery |
| POST | /v1/oauth2/applications | Create application |
| POST | /v1/gifts/{code}/redeem | Redeem gift |
| POST | /v1/users/@me/channels | Create private channel |
| PUT | /v1/channels/{channel_id}/recipients/{user_id} | Add group direct message recipient |
Create private channel is gated only on the group direct message path, where the request body has a recipients member. A one-to-one direct message request omits the field and is never gated.
Exemption
Section titled “Exemption”Fluxer skips the check in three cases, and the operation then proceeds with no CAPTCHA header. The instance account policy grants the captcha_exempt capability to the authenticated account’s email address. The authenticated account holds the APP_STORE_REVIEWER flag. The request body has an email that belongs to an account holding that flag. Discovery does not report exemptions, so clients must handle a challenge on every gated operation.
Request headers
Section titled “Request headers”| Field | Type | Description |
|---|---|---|
| X-Captcha-Token?1 | string | The solution issued by the provider widget |
| X-Captcha-Type?2 | string | The provider that produced the solution, accepting hcaptcha or turnstile |
1 An absent or empty value on a gated operation returns 400 CAPTCHA_REQUIRED
2 An absent value selects the instance’s configured provider, and so does any value other than hcaptcha or turnstile. Naming a provider the instance holds no secret key for returns 400 INVALID_CAPTCHA.
The retry handshake
Section titled “The retry handshake”Send the request without CAPTCHA headers. On 400 CAPTCHA_REQUIRED, obtain a solution through the selected provider’s widget using its advertised site key. Retry the same request with X-Captcha-Token set to the solution and, optionally, X-Captcha-Type set to the provider.
An accepted solution allows the operation to proceed. A rejected solution returns 400 INVALID_CAPTCHA.
Provider verification
Section titled “Provider verification”A rejected solution or unavailable provider returns 400 INVALID_CAPTCHA. The response does not distinguish between these causes.
Error codes
Section titled “Error codes”| Code | Status | Description |
|---|---|---|
| CAPTCHA_REQUIRED1 | 400 | The operation is gated and the request has no solution |
| INVALID_CAPTCHA | 400 | The provider rejected the solution, or verification could not be completed |
1 Send phone verification also answers this code when Fluxer’s risk check on the phone attempt decides that the request needs a CAPTCHA. That operation is not gated and accepts no solution, so retrying it with X-Captcha-Token never helps
Both codes are defined in the API error code registry, and the body of each is the ordinary error response envelope.