Skip to content

Captcha

Captcha token verification and widget issuance.

1. Overview

Base path: https://api.infrai.cc/v1/captcha
Auth header: Authorization: Bearer $INFRAI_API_KEY
bash
# Call any /v1/captcha capability over raw HTTP — no SDK to install.
# curl:
curl https://api.infrai.cc/v1/captcha/... \
  -H "Authorization: Bearer $INFRAI_API_KEY" \
  -H "Content-Type: application/json"

2. Methods (4)

2.1captcha.verify

POST /v1/captcha/verify

Verify a token from an Infrai-managed browser widget.

Parameters

NameTypeRequiredDescription
widget_record_idstring
Required
Infrai widget ID returned by captcha.widget.create.
≥ 1 chars
tokenstring
Required
One-time token returned by the browser widget.
≥ 1 chars
ipstringOptionalClient IP for risk scoring.
score_thresholdnumberOptionalMinimum acceptable score (score-based vendors).
0–1

Returns

CaptchaVerification { success, score?, vendor, hostname?, action?, reasons }
NameTypeDescription
successbooleanWhether the captcha verification passed
scorenumber | null0=bot, 1=human (normalized).
0–1
hostnamestring | nullHostname of the site where the captcha was solved
actionstring | nullAction performed (e.g. created, updated, deleted)
challenge_tsstringISO 8601 timestamp when the captcha challenge was issued
format: date-time
vendorstringVendor that handled or will handle this request
reasons("timeout-or-duplicate" | "invalid-input-response" | "invalid-sitekey" | "low-score" | "hostname-mismatch")[]List of reasons contributing to the risk score

Example

One-time prep (each example is assumed to be complete):

bash
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."
bash
curl -X POST https://api.infrai.cc/v1/captcha/verify \
  -H "Authorization: Bearer $INFRAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"widget_record_id": "cwid_...", "token": "<client-captcha-token>", "ip": "203.0.113.5"}'

2.2captcha.widget.create

POST /v1/captcha/widget/create

Create a CAPTCHA widget entirely through Infrai and receive its public browser configuration.

Parameters

NameTypeRequiredDescription
namestring
Required
Human-readable widget name.
1–128 chars
domainsstring[]OptionalHostnames allowed to render this widget.
widget_mode"managed" | "non-interactive" | "invisible"OptionalVendor widget render mode.
default: "managed"

Returns

WidgetSetup { widget_record_id, vendor, sitekey, embed_url, embed_snippet, status }
NameTypeDescription
widget_record_idstringInfrai widget ID; pass it to widget.get and captcha.verify.
namestringHuman label; doubles as verify-time sitekey_label hint.
vendorstring-
statusanyThe vendor widget and server-side verification secret were provisioned successfully.
sitekeystringPublic; embed in client HTML.
≥ 1 chars
widget_idstring | nullVendor-side widget identifier.
domainsstring[]-
embed_urlstringPublic vendor browser script URL.
format: uri
embed_snippetstringCopy-paste HTML snippet.
≥ 1 chars
dashboard_urlstring | nullVendor dashboard link for manual completion.
messagestring | nullHuman-readable note (e.g. manual setup instructions).
metadataobject | null-
errorstring | null-
created_atstring-
format: date-time

Example

One-time prep (each example is assumed to be complete):

bash
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."
bash
curl -X POST https://api.infrai.cc/v1/captcha/widget/create \
  -H "Authorization: Bearer $INFRAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "signup", "domains": ["app.example.com"], "widget_mode": "managed"}'

2.3captcha.widget.list

GET /v1/captcha/widget/list

List this account''s Infrai-managed CAPTCHA widgets.

Returns

WidgetListResult { items: WidgetSetup[], total_count, next_cursor? }
NameTypeDescription
itemsobject[]-
items[].widget_record_idstringInfrai widget ID; pass it to widget.get and captcha.verify.
items[].namestringHuman label; doubles as verify-time sitekey_label hint.
items[].vendorstring-
items[].statusanyThe vendor widget and server-side verification secret were provisioned successfully.
items[].sitekeystringPublic; embed in client HTML.
≥ 1 chars
items[].widget_idstring | nullVendor-side widget identifier.
items[].domainsstring[]-
items[].embed_urlstringPublic vendor browser script URL.
format: uri
items[].embed_snippetstringCopy-paste HTML snippet.
≥ 1 chars
items[].dashboard_urlstring | nullVendor dashboard link for manual completion.
items[].messagestring | nullHuman-readable note (e.g. manual setup instructions).
items[].metadataobject | null-
items[].errorstring | null-
items[].created_atstring-
format: date-time
total_countintegerOptional; may be omitted for high-cardinality lists.
≥ 0
next_cursorstring | nullPass back into list() to fetch the next page. null = end.

Example

One-time prep (each example is assumed to be complete):

bash
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."
bash
curl -X GET https://api.infrai.cc/v1/captcha/widget/list \
  -H "Authorization: Bearer $INFRAI_API_KEY"

2.4captcha.widget.get

GET /v1/captcha/widget/get/{widget_record_id}

Get an Infrai-managed CAPTCHA widget''s public browser configuration.

Parameters

NameTypeRequiredDescription
widget_record_idstring
Required
Infrai widget ID returned by captcha.widget.create.

Returns

WidgetSetup { widget_record_id, vendor, sitekey, embed_url, embed_snippet, status }
NameTypeDescription
widget_record_idstringInfrai widget ID; pass it to widget.get and captcha.verify.
namestringHuman label; doubles as verify-time sitekey_label hint.
vendorstring-
statusanyThe vendor widget and server-side verification secret were provisioned successfully.
sitekeystringPublic; embed in client HTML.
≥ 1 chars
widget_idstring | nullVendor-side widget identifier.
domainsstring[]-
embed_urlstringPublic vendor browser script URL.
format: uri
embed_snippetstringCopy-paste HTML snippet.
≥ 1 chars
dashboard_urlstring | nullVendor dashboard link for manual completion.
messagestring | nullHuman-readable note (e.g. manual setup instructions).
metadataobject | null-
errorstring | null-
created_atstring-
format: date-time

Example

One-time prep (each example is assumed to be complete):

bash
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."
bash
curl -X GET https://api.infrai.cc/v1/captcha/widget/get/WIDGET_RECORD_ID \
  -H "Authorization: Bearer $INFRAI_API_KEY"
Advanced: pin a vendor

By default infrai routes each call to the best available provider — you do not pick a vendor. As an escape hatch, this capability accepts an optional vendor parameter to pin one specific provider. Every live vendor for this capability is available in real time from the discovery endpoint for the capability id — see the discovery API.

GET /v1/discovery/{capability}

captcha.verify

captcha.widget.create

captcha.widget.list

3. All capabilities

Every routed capability in this module — the complete public REST contract. The methods above are the guided walkthrough; this index is the full reference.

captcha.verifyPOST /v1/captcha/verify

Verify a client-submitted CAPTCHA token against the vendor and return the success result; idempotent.

Parameters (10)
NameTypeRequiredDescription
widget_record_idstringRequiredInfrai widget ID returned by captcha.widget.create; selects the exact vendor and server-side secret.
≥ 1 chars
tokenstringRequiredOne-time vendor response token from the client widget.
≥ 1 chars
vendorstring | nullOptionalOptional consistency assertion; must match the widget vendor when provided.
ipstring | nullOptionalEnd-user IP for vendor-side risk scoring. Alias: `remoteip`.
remoteipstring | nullOptionalAlias of `ip` (module accepts both; `ip = ip or remoteip`).
actionstring | nullOptionalAction name bound at challenge time; rejected if mismatched (anti cross-form replay).
expected_hostnamestring | nullOptionalIf set, token hostname must match.
score_thresholdnumber | nullOptionalMinimum acceptable score [0,1]; below → fail with low-score reason.
0–1
mode"default_vendor" | "verified_account"OptionalRouting axis (CaptchaMode); orthogonal to widget_mode.
default: "default_vendor"
sitekey_labelstringOptionalDeprecated compatibility hint; widget_record_id selects the exact sitekey and secret.
default: "default"
captcha.widget.createPOST /v1/captcha/widget/create

Create and manage a CAPTCHA widget through Infrai; returns the public sitekey and browser embed snippet while keeping the vendor secret server-side.

Parameters (5)
NameTypeRequiredDescription
namestringRequiredHuman label; also the verify-time sitekey_label hint.
1–128 chars
domainsstring[]OptionalAllowed hostnames for this sitekey.
vendor"turnstile" | nullOptionalOptional vendor pin. Widget provisioning currently supports Turnstile.
mode"default_vendor" | "verified_account"OptionalRouting axis (CaptchaMode).
default: "default_vendor"
widget_mode"managed" | "non-interactive" | "invisible"OptionalVendor render axis (orthogonal to mode).
default: "managed"
captcha.widget.getGET /v1/captcha/widget/get/{widget_record_id}

Get this account's CAPTCHA widget and public browser configuration.

Parameters (1)
NameTypeRequiredDescription
widget_record_idstringRequiredWidgetStore primary key.
captcha.widget.listGET /v1/captcha/widget/list

List this account's CAPTCHA widgets.

Parameters (3)
NameTypeRequiredDescription
vendorstring | nullOptionalOptional filter by vendor.
cursorstring | nullOptionalOpaque cursor from a previous page; null = first page.
limitintegerOptional
1–1000default: 50

4. End-to-end example

A production-style walkthrough of this module: configure once, then run the flow. It exercises most of the module's APIs.

A copy-paste-runnable single-file Python program (stdlib only, no SDK): set your INFRAI_API_KEY, run it, and walk this module's core flow with REAL billed calls — later steps reuse real fields returned by earlier ones. The 12-line helper is the entire integration.

python
#!/usr/bin/env python3
"""Infrai · captcha — runnable real-app example (single file, zero deps).

Copy this file, set your key, run it: every step is a REAL call to
api.infrai.cc, billed at the real (tiny) per-call price, printing the
live JSON response. Get a key at https://infrai.cc/login (Google/
GitHub sign-in grants $2 free credit); add funds at
https://infrai.cc/billing. No SDK — the 12-line helper below is the
entire integration."""
import json
import os
from urllib import error, request

KEY = os.environ.get("INFRAI_API_KEY") or "ifr_..."  # <- your key
BASE = "https://api.infrai.cc"


# Same raw HTTPS POST/GET as every per-method example on this page —
# wrapped once for reuse. There is nothing else to it: no SDK.
def infrai(method, path, body=None):
    req = request.Request(
        BASE + path, method=method,
        data=json.dumps(body).encode() if body is not None else None,
        headers={"Authorization": f"Bearer {KEY}",
                 "Content-Type": "application/json"})
    try:
        with request.urlopen(req, timeout=60) as r:
            return json.loads(r.read())
    except error.HTTPError as e:
        return json.loads(e.read())


def show(label, resp):
    print(f"\n== {label} ==")
    print(json.dumps(resp, indent=2, ensure_ascii=False))
    return resp


# 1) captcha.widget.create — POST /v1/captcha/widget/create · Create and manage a CAPTCHA widget through Infrai; returns the public sitekey and browser embed snippet while keeping the vendor secret server-side.
r1 = show("captcha.widget.create", infrai("POST", "/v1/captcha/widget/create", {"name":"signup","domains":["app.example.com"],"widget_mode":"managed"}))

# 2) captcha.verify — POST /v1/captcha/verify · Verify a client-submitted CAPTCHA token against the vendor and return the success result; idempotent.
ask1 = input("Paste the one-time token returned by the browser widget: ").strip()
widget_record_id_2 = (r1.get("data") or {}).get("widget_record_id") or ""
r2 = show("captcha.verify", infrai("POST", "/v1/captcha/verify", {"widget_record_id":widget_record_id_2,"token":ask1,"ip":"203.0.113.5"}))

5. Developer guides

Move from endpoint details to complete workflows, production patterns and troubleshooting guides verified against the live API.

Captcha developer guides