Skip to content

API Reference

CaptchaLa provides RESTful API for all server-side integrations.

Base URL

https://apiv1.captcha.la

One base URL only

Every endpoint on this page lives on apiv1.captcha.la. Our standby hosts (bypass.*, fallbackapiv1.*) are failover targets the SDKs reach on their own during an outage — pointing your integration at them returns service_online.

Authentication

All API requests require authentication headers:

X-App-Key:    YOUR_APP_KEY
X-App-Secret: YOUR_APP_SECRET

WARNING

X-App-Secret is server-side only. Never expose it to browsers, mobile apps, or public repos.

Server-side Validation API

💡 Use a server SDK to skip the boilerplate. Wraps the endpoint, handles retries, surfaces typed errors:

After user passes the frontend CAPTCHA, your server needs to validate the token returned by SDK. Below are the server-side validation endpoints.

Server-side Token Validation

Validate pass_token from frontend SDK (with pt_ prefix). Requires X-App-Key and X-App-Secret headers.

bash
POST /v1/validate
X-App-Key: YOUR_APP_KEY
X-App-Secret: YOUR_APP_SECRET
Content-Type: application/json

{ "pass_token": "pt_xxx", "client_ip": "1.2.3.4" }

client_ip is optional but recommended — the end-user's IP from your inbound request. Used for additional risk checks; safe to omit.

json
{
  "code": 0,
  "data": {
    "valid": true,
    "challenge_id": "ch_xxx",
    "action": "login",
    "uid": null,
    "captcha_args": {
      "platform": "web",
      "user_ip": "1.2.3.4",
      "referer": "https://your-site.com/login",
      "pkg": null,
      "solved_at": 1750000000,
      "risk_score": 12
    }
  }
}

TIP

Validate data.valid === true and that data.action matches the scene you expected (reject if a token from a pay flow is presented at /login). Tokens are single-use.

captcha_args

captcha_args echoes the context recorded at solve time — for logging / your own risk scoring:

  • platformweb / android / ios / flutter / windows / …
  • user_ip — the end-user IP seen when the challenge was solved
  • referer — solve page URL (web); null on native
  • pkg — app package / bundle id (native); null on web
  • solved_at — solve completion time (unix seconds)
  • risk_score — solve-time risk score (0-100, higher = riskier)

Token Types

The SDK may hand your frontend different token types depending on service conditions. The prefix tells you everything:

PrefixIssued when/v1/validate returnsRecommended handling
pt_Verification passed normallyvalid: true (single-use)Accept
dg_Plan quota exhausted (degraded mode)valid: false, degraded: true, reasonYour decision — see below
offline_Main API unreachable; issued by the bypass workerVerified against the backup API automatically when using a server SDKAccept after backup verification
co_Main and backup unreachable; generated client-sideCannot be verified server-sideApply your own risk controls (rate limits, etc.)

Degraded Mode (quota exhausted)

When an app has exhausted its monthly quota (and overage billing is not available), the widget does not interrupt your end-user flow. Instead of showing an error, the SDK completes immediately with a dg_ token:

  • The end user sees no error — your form submits normally.
  • Your server's /v1/validate returns:
json
{
  "code": 0,
  "data": {
    "valid": false,
    "degraded": true,
    "reason": "quota_exhausted",
    "expired": false
  }
}

Key properties:

  • valid is always false for degraded tokens — secure by default. If your code only checks valid, nothing changes for you.
  • Whether to let the request through is your decision: accept valid || degraded to keep conversions flowing while you upgrade your plan, or reject and show your own fallback.
  • dg_ tokens are HMAC-signed per app and expire after 5 minutes. Issuing them costs no quota and is never billed.
  • Server SDKs expose this as isDegraded() / getDegradedReason() (PHP) and result.Degraded / result.DegradedReason (Go).

INFO

Expired subscriptions never trigger degraded mode — they automatically fall back to the Free plan and keep serving within the free quota. Degraded mode only covers usage beyond your plan's quota.

Server-issued Challenge Token

Issue a short-lived server_token from your backend. The browser then passes this token when initializing a challenge, proving the request originated from your trusted server.

Issue Server Token

Call this endpoint from your own server only. Requires X-App-Key + X-App-Secret. Response contains a server_token (sct_ prefix) that the frontend forwards to the challenge initialization.

bash
POST /v1/server/challenge/issue
X-App-Key: YOUR_APP_KEY
X-App-Secret: YOUR_APP_SECRET
Content-Type: application/x-www-form-urlencoded

action=login&ttl=300&max_uses=1&bind_ip=1.2.3.4
json
{
  "code": 0,
  "data": {
    "server_token": "sct_xxxxxxxxxxxx",
    "expires_in": 300,
    "issued_at": 1713600000
  }
}

Body Parameters (form-urlencoded)

FieldDescription
actionBusiness scene, e.g. login, register, pay. Must match the action used in the challenge initialization.
ttlToken lifetime in seconds. Default 300, max 900.
max_usesMaximum times the token may be consumed. Default 10.
bind_ipBind token to a client IP. Initialization from another IP is rejected.
bind_device_idBind token to a specific device id.
bind_fingerprintBind token to a specific browser fingerprint.

Initialize Challenge

Called by the SDK to start a CAPTCHA challenge. Accepts an optional server_token issued by /v1/server/challenge/issue.

FieldDescription
app_keyYour public App Key.
actionBusiness scene. Must match the action used when issuing the server_token.
server_tokenOptional; required when the app has server_token_required = true.

INFO

If server_token_required is enabled for this app in the dashboard, the challenge initialization will reject requests that do not carry a valid server_token.

Offline Fallback Endpoints

CaptchaLa keeps a small standby service on separate hosts so verification still works while the main API is unreachable:

HostCalled byPurpose
bypass.captchala.com · bypass.captcha-cdn.netWeb / native SDK (end-user side)Runs offline verification and issues an offline_ pass token while the main API is down
fallbackapiv1.captchala.com · fallbackapiv1.captcha-cdn.netServer SDKsValidates offline_ tokens (POST /api/validate)

These are failover targets, not an alternative API. The SDKs switch to them by themselves, only after the main API has actually failed, and switch back as soon as it recovers. Nothing in your own configuration should point at them.

service_online (HTTP 503)

json
{ "code": -1, "error": "service_online", "message": "Main API is online, please use main API" }

You get this while the main API is up: the standby service only serves traffic during an outage. The request reached bypass.* instead of https://apiv1.captcha.la — fix the URL, retrying will not help.

Common causes:

CauseFix
SDK apiServer option set to a bypass hostSet it to https://apiv1.captcha.la, or remove the option and let the SDK choose a server
bypassServers overridden by handRemove the override unless we gave you specific hosts
A custom HTTP client copied a bypass URL (e.g. from devtools during an incident)Call https://apiv1.captcha.la and let the SDK handle failover — the standby service does not accept normal challenge traffic
Load balancer / proxy / DNS rewriting the API hostPoint the upstream back at apiv1.captcha.la

TIP

Server-side validation never needs the fallback host either. POST /v1/validate on apiv1.captcha.la handles pt_ and dg_ tokens, and the PHP / Go server SDKs fall back to the backup API for offline_ tokens automatically.

Error Codes

CodeDescription
invalid_app_keyInvalid App Key
invalid_app_secretInvalid App Secret
challenge_expiredChallenge expired
challenge_not_foundChallenge not found
invalid_answerInvalid answer
token_expiredToken expired
token_already_usedToken already used
token_not_foundToken not found
quota_exceededQuota exceeded
rate_limitedRate limited
rate_limit_exceededToo many issuance requests for this app. Back off and retry.
service_onlineThe request hit the offline fallback service while the main API is up. Call https://apiv1.captcha.la instead — see Offline fallback endpoints.

MIT-licensed examples · CaptchaLa is operated independently