Captcha
Captcha token verification and widget issuance.
1. Overview
https://api.infrai.cc/v1/captchaAuthorization: Bearer $INFRAI_API_KEY# 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
Verify a token from an Infrai-managed browser widget.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
widget_record_id | string | Required | Infrai widget ID returned by captcha.widget.create.≥ 1 chars |
token | string | Required | One-time token returned by the browser widget.≥ 1 chars |
ip | string | Optional | Client IP for risk scoring. |
score_threshold | number | Optional | Minimum acceptable score (score-based vendors).0–1 |
Returns
CaptchaVerification { success, score?, vendor, hostname?, action?, reasons }| Name | Type | Description |
|---|---|---|
success | boolean | Whether the captcha verification passed |
score | number | null | 0=bot, 1=human (normalized).0–1 |
hostname | string | null | Hostname of the site where the captcha was solved |
action | string | null | Action performed (e.g. created, updated, deleted) |
challenge_ts | string | ISO 8601 timestamp when the captcha challenge was issuedformat: date-time |
vendor | string | Vendor 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):
# 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_..."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"}'# Zero-install REST call — no SDK required (short-term the API is REST-only).
import os, requests
resp = requests.post(
"https://api.infrai.cc/v1/captcha/verify",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
json={'widget_record_id': 'cwid_...', 'token': '<client-captcha-token>', 'ip': '203.0.113.5'},
)
resp.raise_for_status()
print(resp.json())// Browser prerequisite: fetch the public WidgetSetup from your server; never expose INFRAI_API_KEY.
const widget = await fetch("/captcha-config").then((r) => r.json());
const script = document.createElement("script");
script.src = widget.embed_url;
script.onload = () => turnstile.render("#captcha", {
sitekey: widget.sitekey, action: "signup",
callback: (token) => fetch("/signup", {
method: "POST", headers: { "Content-Type": "application/json" },
body: JSON.stringify({ token, widget_record_id: widget.widget_record_id }),
}),
});
document.head.appendChild(script); // page contains <div id="captcha"></div>
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/captcha/verify",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"widget_record_id": "cwid_...", "token": "<client-captcha-token>", "ip": "203.0.113.5"}),
},
);
console.log(await resp.json());declare const turnstile: { render(selector: string, options: { sitekey: string; action: string; callback(token: string): void }): void };
// Browser prerequisite: fetch the public WidgetSetup from your server; never expose INFRAI_API_KEY.
const widget = await fetch("/captcha-config").then((r) => r.json());
const script = document.createElement("script");
script.src = widget.embed_url;
script.onload = () => turnstile.render("#captcha", {
sitekey: widget.sitekey, action: "signup",
callback: (token) => fetch("/signup", {
method: "POST", headers: { "Content-Type": "application/json" },
body: JSON.stringify({ token, widget_record_id: widget.widget_record_id }),
}),
});
document.head.appendChild(script); // page contains <div id="captcha"></div>
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/captcha/verify",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"widget_record_id": "cwid_...", "token": "<client-captcha-token>", "ip": "203.0.113.5"}),
},
);
if (!resp.ok) throw new Error(`infrai ${resp.status}`);
const data: unknown = await resp.json();
console.log(data);// Zero-install REST call — no SDK required (short-term the API is REST-only).
package main
import (
"bytes"
"fmt"
"net/http"
"os"
)
func main() {
body := []byte(`{"widget_record_id": "cwid_...", "token": "<client-captcha-token>", "ip": "203.0.113.5"}`)
req, _ := http.NewRequest("POST", "https://api.infrai.cc/v1/captcha/verify", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRAI_API_KEY"))
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Println(resp.Status)
}// Zero-install REST call — no SDK required (short-term the API is REST-only).
import java.net.URI;
import java.net.http.*;
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create("https://api.infrai.cc/v1/captcha/verify"))
.header("Authorization", "Bearer " + System.getenv("INFRAI_API_KEY"))
.header("Content-Type", "application/json")
.method("POST", HttpRequest.BodyPublishers.ofString("{\"widget_record_id\": \"cwid_...\", \"token\": \"<client-captcha-token>\", \"ip\": \"203.0.113.5\"}"))
.build();
HttpResponse<String> resp = HttpClient.newHttpClient()
.send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(resp.body());// Zero-install REST call — no SDK required (short-term the API is REST-only).
using System;
using System.Net.Http;
var client = new HttpClient();
var req = new HttpRequestMessage(new HttpMethod("POST"), "https://api.infrai.cc/v1/captcha/verify");
var key = Environment.GetEnvironmentVariable("INFRAI_API_KEY");
req.Headers.Add("Authorization", "Bearer " + key);
req.Content = new StringContent("{\"widget_record_id\": \"cwid_...\", \"token\": \"<client-captcha-token>\", \"ip\": \"203.0.113.5\"}", System.Text.Encoding.UTF8, "application/json");
var resp = await client.SendAsync(req);
Console.WriteLine(await resp.Content.ReadAsStringAsync());<?php
// Zero-install REST call — no SDK required (short-term the API is REST-only).
$ch = curl_init("https://api.infrai.cc/v1/captcha/verify");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer " . getenv("INFRAI_API_KEY"),
"Content-Type: application/json",
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, "{\"widget_record_id\": \"cwid_...\", \"token\": \"<client-captcha-token>\", \"ip\": \"203.0.113.5\"}");
$response = curl_exec($ch);
curl_close($ch);
echo $response;# Zero-install REST call — no SDK required (short-term the API is REST-only).
require "net/http"
require "uri"
uri = URI("https://api.infrai.cc/v1/captcha/verify")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer #{ENV['INFRAI_API_KEY']}"
req["Content-Type"] = "application/json"
req.body = '{"widget_record_id": "cwid_...", "token": "<client-captcha-token>", "ip": "203.0.113.5"}'
res = http.request(req)
puts res.body// Zero-install REST call — no SDK required (short-term the API is REST-only). (uses the reqwest + tokio crates)
use std::env;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let resp = reqwest::Client::new()
.post("https://api.infrai.cc/v1/captcha/verify")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.header("Content-Type", "application/json")
.body(r#"{"widget_record_id": "cwid_...", "token": "<client-captcha-token>", "ip": "203.0.113.5"}"#)
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.2captcha.widget.create
Create a CAPTCHA widget entirely through Infrai and receive its public browser configuration.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
name | string | Required | Human-readable widget name.1–128 chars |
domains | string[] | Optional | Hostnames allowed to render this widget. |
widget_mode | "managed" | "non-interactive" | "invisible" | Optional | Vendor widget render mode.default: "managed" |
Returns
WidgetSetup { widget_record_id, vendor, sitekey, embed_url, embed_snippet, status }| Name | Type | Description |
|---|---|---|
widget_record_id | string | Infrai widget ID; pass it to widget.get and captcha.verify. |
name | string | Human label; doubles as verify-time sitekey_label hint. |
vendor | string | - |
status | any | The vendor widget and server-side verification secret were provisioned successfully. |
sitekey | string | Public; embed in client HTML.≥ 1 chars |
widget_id | string | null | Vendor-side widget identifier. |
domains | string[] | - |
embed_url | string | Public vendor browser script URL.format: uri |
embed_snippet | string | Copy-paste HTML snippet.≥ 1 chars |
dashboard_url | string | null | Vendor dashboard link for manual completion. |
message | string | null | Human-readable note (e.g. manual setup instructions). |
metadata | object | null | - |
error | string | null | - |
created_at | string | -format: date-time |
Example
One-time prep (each example is assumed to be complete):
# 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_..."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"}'# Zero-install REST call — no SDK required (short-term the API is REST-only).
import os, requests
resp = requests.post(
"https://api.infrai.cc/v1/captcha/widget/create",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
json={'name': 'signup', 'domains': ['app.example.com'], 'widget_mode': 'managed'},
)
resp.raise_for_status()
print(resp.json())// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/captcha/widget/create",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"name": "signup", "domains": ["app.example.com"], "widget_mode": "managed"}),
},
);
console.log(await resp.json());// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/captcha/widget/create",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"name": "signup", "domains": ["app.example.com"], "widget_mode": "managed"}),
},
);
if (!resp.ok) throw new Error(`infrai ${resp.status}`);
const data: unknown = await resp.json();
console.log(data);// Zero-install REST call — no SDK required (short-term the API is REST-only).
package main
import (
"bytes"
"fmt"
"net/http"
"os"
)
func main() {
body := []byte(`{"name": "signup", "domains": ["app.example.com"], "widget_mode": "managed"}`)
req, _ := http.NewRequest("POST", "https://api.infrai.cc/v1/captcha/widget/create", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRAI_API_KEY"))
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Println(resp.Status)
}// Zero-install REST call — no SDK required (short-term the API is REST-only).
import java.net.URI;
import java.net.http.*;
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create("https://api.infrai.cc/v1/captcha/widget/create"))
.header("Authorization", "Bearer " + System.getenv("INFRAI_API_KEY"))
.header("Content-Type", "application/json")
.method("POST", HttpRequest.BodyPublishers.ofString("{\"name\": \"signup\", \"domains\": [\"app.example.com\"], \"widget_mode\": \"managed\"}"))
.build();
HttpResponse<String> resp = HttpClient.newHttpClient()
.send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(resp.body());// Zero-install REST call — no SDK required (short-term the API is REST-only).
using System;
using System.Net.Http;
var client = new HttpClient();
var req = new HttpRequestMessage(new HttpMethod("POST"), "https://api.infrai.cc/v1/captcha/widget/create");
var key = Environment.GetEnvironmentVariable("INFRAI_API_KEY");
req.Headers.Add("Authorization", "Bearer " + key);
req.Content = new StringContent("{\"name\": \"signup\", \"domains\": [\"app.example.com\"], \"widget_mode\": \"managed\"}", System.Text.Encoding.UTF8, "application/json");
var resp = await client.SendAsync(req);
Console.WriteLine(await resp.Content.ReadAsStringAsync());<?php
// Zero-install REST call — no SDK required (short-term the API is REST-only).
$ch = curl_init("https://api.infrai.cc/v1/captcha/widget/create");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer " . getenv("INFRAI_API_KEY"),
"Content-Type: application/json",
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, "{\"name\": \"signup\", \"domains\": [\"app.example.com\"], \"widget_mode\": \"managed\"}");
$response = curl_exec($ch);
curl_close($ch);
echo $response;# Zero-install REST call — no SDK required (short-term the API is REST-only).
require "net/http"
require "uri"
uri = URI("https://api.infrai.cc/v1/captcha/widget/create")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer #{ENV['INFRAI_API_KEY']}"
req["Content-Type"] = "application/json"
req.body = '{"name": "signup", "domains": ["app.example.com"], "widget_mode": "managed"}'
res = http.request(req)
puts res.body// Zero-install REST call — no SDK required (short-term the API is REST-only). (uses the reqwest + tokio crates)
use std::env;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let resp = reqwest::Client::new()
.post("https://api.infrai.cc/v1/captcha/widget/create")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.header("Content-Type", "application/json")
.body(r#"{"name": "signup", "domains": ["app.example.com"], "widget_mode": "managed"}"#)
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.3captcha.widget.list
List this account''s Infrai-managed CAPTCHA widgets.
Returns
WidgetListResult { items: WidgetSetup[], total_count, next_cursor? }| Name | Type | Description |
|---|---|---|
items | object[] | - |
items[].widget_record_id | string | Infrai widget ID; pass it to widget.get and captcha.verify. |
items[].name | string | Human label; doubles as verify-time sitekey_label hint. |
items[].vendor | string | - |
items[].status | any | The vendor widget and server-side verification secret were provisioned successfully. |
items[].sitekey | string | Public; embed in client HTML.≥ 1 chars |
items[].widget_id | string | null | Vendor-side widget identifier. |
items[].domains | string[] | - |
items[].embed_url | string | Public vendor browser script URL.format: uri |
items[].embed_snippet | string | Copy-paste HTML snippet.≥ 1 chars |
items[].dashboard_url | string | null | Vendor dashboard link for manual completion. |
items[].message | string | null | Human-readable note (e.g. manual setup instructions). |
items[].metadata | object | null | - |
items[].error | string | null | - |
items[].created_at | string | -format: date-time |
total_count | integer | Optional; may be omitted for high-cardinality lists.≥ 0 |
next_cursor | string | null | Pass back into list() to fetch the next page. null = end. |
Example
One-time prep (each example is assumed to be complete):
# 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_..."curl -X GET https://api.infrai.cc/v1/captcha/widget/list \
-H "Authorization: Bearer $INFRAI_API_KEY"# Zero-install REST call — no SDK required (short-term the API is REST-only).
import os, requests
resp = requests.get(
"https://api.infrai.cc/v1/captcha/widget/list",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
)
resp.raise_for_status()
print(resp.json())// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/captcha/widget/list",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
console.log(await resp.json());// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/captcha/widget/list",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
if (!resp.ok) throw new Error(`infrai ${resp.status}`);
const data: unknown = await resp.json();
console.log(data);// Zero-install REST call — no SDK required (short-term the API is REST-only).
package main
import (
"fmt"
"net/http"
"os"
)
func main() {
req, _ := http.NewRequest("GET", "https://api.infrai.cc/v1/captcha/widget/list", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRAI_API_KEY"))
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Println(resp.Status)
}// Zero-install REST call — no SDK required (short-term the API is REST-only).
import java.net.URI;
import java.net.http.*;
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create("https://api.infrai.cc/v1/captcha/widget/list"))
.header("Authorization", "Bearer " + System.getenv("INFRAI_API_KEY"))
.method("GET", HttpRequest.BodyPublishers.noBody())
.build();
HttpResponse<String> resp = HttpClient.newHttpClient()
.send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(resp.body());// Zero-install REST call — no SDK required (short-term the API is REST-only).
using System;
using System.Net.Http;
var client = new HttpClient();
var req = new HttpRequestMessage(new HttpMethod("GET"), "https://api.infrai.cc/v1/captcha/widget/list");
var key = Environment.GetEnvironmentVariable("INFRAI_API_KEY");
req.Headers.Add("Authorization", "Bearer " + key);
var resp = await client.SendAsync(req);
Console.WriteLine(await resp.Content.ReadAsStringAsync());<?php
// Zero-install REST call — no SDK required (short-term the API is REST-only).
$ch = curl_init("https://api.infrai.cc/v1/captcha/widget/list");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer " . getenv("INFRAI_API_KEY"),
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;# Zero-install REST call — no SDK required (short-term the API is REST-only).
require "net/http"
require "uri"
uri = URI("https://api.infrai.cc/v1/captcha/widget/list")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
req = Net::HTTP::Get.new(uri)
req["Authorization"] = "Bearer #{ENV['INFRAI_API_KEY']}"
res = http.request(req)
puts res.body// Zero-install REST call — no SDK required (short-term the API is REST-only). (uses the reqwest + tokio crates)
use std::env;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let resp = reqwest::Client::new()
.get("https://api.infrai.cc/v1/captcha/widget/list")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.4captcha.widget.get
Get an Infrai-managed CAPTCHA widget''s public browser configuration.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
widget_record_id | string | Required | Infrai widget ID returned by captcha.widget.create. |
Returns
WidgetSetup { widget_record_id, vendor, sitekey, embed_url, embed_snippet, status }| Name | Type | Description |
|---|---|---|
widget_record_id | string | Infrai widget ID; pass it to widget.get and captcha.verify. |
name | string | Human label; doubles as verify-time sitekey_label hint. |
vendor | string | - |
status | any | The vendor widget and server-side verification secret were provisioned successfully. |
sitekey | string | Public; embed in client HTML.≥ 1 chars |
widget_id | string | null | Vendor-side widget identifier. |
domains | string[] | - |
embed_url | string | Public vendor browser script URL.format: uri |
embed_snippet | string | Copy-paste HTML snippet.≥ 1 chars |
dashboard_url | string | null | Vendor dashboard link for manual completion. |
message | string | null | Human-readable note (e.g. manual setup instructions). |
metadata | object | null | - |
error | string | null | - |
created_at | string | -format: date-time |
Example
One-time prep (each example is assumed to be complete):
# 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_..."curl -X GET https://api.infrai.cc/v1/captcha/widget/get/WIDGET_RECORD_ID \
-H "Authorization: Bearer $INFRAI_API_KEY"# Zero-install REST call — no SDK required (short-term the API is REST-only).
import os, requests
resp = requests.get(
"https://api.infrai.cc/v1/captcha/widget/get/WIDGET_RECORD_ID",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
)
resp.raise_for_status()
print(resp.json())// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/captcha/widget/get/WIDGET_RECORD_ID",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
console.log(await resp.json());// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/captcha/widget/get/WIDGET_RECORD_ID",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
if (!resp.ok) throw new Error(`infrai ${resp.status}`);
const data: unknown = await resp.json();
console.log(data);// Zero-install REST call — no SDK required (short-term the API is REST-only).
package main
import (
"fmt"
"net/http"
"os"
)
func main() {
req, _ := http.NewRequest("GET", "https://api.infrai.cc/v1/captcha/widget/get/WIDGET_RECORD_ID", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRAI_API_KEY"))
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Println(resp.Status)
}// Zero-install REST call — no SDK required (short-term the API is REST-only).
import java.net.URI;
import java.net.http.*;
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create("https://api.infrai.cc/v1/captcha/widget/get/WIDGET_RECORD_ID"))
.header("Authorization", "Bearer " + System.getenv("INFRAI_API_KEY"))
.method("GET", HttpRequest.BodyPublishers.noBody())
.build();
HttpResponse<String> resp = HttpClient.newHttpClient()
.send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(resp.body());// Zero-install REST call — no SDK required (short-term the API is REST-only).
using System;
using System.Net.Http;
var client = new HttpClient();
var req = new HttpRequestMessage(new HttpMethod("GET"), "https://api.infrai.cc/v1/captcha/widget/get/WIDGET_RECORD_ID");
var key = Environment.GetEnvironmentVariable("INFRAI_API_KEY");
req.Headers.Add("Authorization", "Bearer " + key);
var resp = await client.SendAsync(req);
Console.WriteLine(await resp.Content.ReadAsStringAsync());<?php
// Zero-install REST call — no SDK required (short-term the API is REST-only).
$ch = curl_init("https://api.infrai.cc/v1/captcha/widget/get/WIDGET_RECORD_ID");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer " . getenv("INFRAI_API_KEY"),
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;# Zero-install REST call — no SDK required (short-term the API is REST-only).
require "net/http"
require "uri"
uri = URI("https://api.infrai.cc/v1/captcha/widget/get/WIDGET_RECORD_ID")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
req = Net::HTTP::Get.new(uri)
req["Authorization"] = "Bearer #{ENV['INFRAI_API_KEY']}"
res = http.request(req)
puts res.body// Zero-install REST call — no SDK required (short-term the API is REST-only). (uses the reqwest + tokio crates)
use std::env;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let resp = reqwest::Client::new()
.get("https://api.infrai.cc/v1/captcha/widget/get/WIDGET_RECORD_ID")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}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/verifyVerify a client-submitted CAPTCHA token against the vendor and return the success result; idempotent.
Parameters (10)
| Name | Type | Required | Description |
|---|---|---|---|
widget_record_id | string | Required | Infrai widget ID returned by captcha.widget.create; selects the exact vendor and server-side secret.≥ 1 chars |
token | string | Required | One-time vendor response token from the client widget.≥ 1 chars |
vendor | string | null | Optional | Optional consistency assertion; must match the widget vendor when provided. |
ip | string | null | Optional | End-user IP for vendor-side risk scoring. Alias: `remoteip`. |
remoteip | string | null | Optional | Alias of `ip` (module accepts both; `ip = ip or remoteip`). |
action | string | null | Optional | Action name bound at challenge time; rejected if mismatched (anti cross-form replay). |
expected_hostname | string | null | Optional | If set, token hostname must match. |
score_threshold | number | null | Optional | Minimum acceptable score [0,1]; below → fail with low-score reason.0–1 |
mode | "default_vendor" | "verified_account" | Optional | Routing axis (CaptchaMode); orthogonal to widget_mode.default: "default_vendor" |
sitekey_label | string | Optional | Deprecated compatibility hint; widget_record_id selects the exact sitekey and secret.default: "default" |
captcha.widget.createPOST /v1/captcha/widget/createCreate and manage a CAPTCHA widget through Infrai; returns the public sitekey and browser embed snippet while keeping the vendor secret server-side.
Parameters (5)
| Name | Type | Required | Description |
|---|---|---|---|
name | string | Required | Human label; also the verify-time sitekey_label hint.1–128 chars |
domains | string[] | Optional | Allowed hostnames for this sitekey. |
vendor | "turnstile" | null | Optional | Optional vendor pin. Widget provisioning currently supports Turnstile. |
mode | "default_vendor" | "verified_account" | Optional | Routing axis (CaptchaMode).default: "default_vendor" |
widget_mode | "managed" | "non-interactive" | "invisible" | Optional | Vendor 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)
| Name | Type | Required | Description |
|---|---|---|---|
widget_record_id | string | Required | WidgetStore primary key. |
captcha.widget.listGET /v1/captcha/widget/listList this account's CAPTCHA widgets.
Parameters (3)
| Name | Type | Required | Description |
|---|---|---|---|
vendor | string | null | Optional | Optional filter by vendor. |
cursor | string | null | Optional | Opaque cursor from a previous page; null = first page. |
limit | integer | Optional | 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.
#!/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"}))
One-time prep (each example is assumed to be complete):
# 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_..."# 1) Auth: every call is a raw HTTPS request to the Infrai gateway carrying
# only your project key. No SDK, no install.
# Get your key: sign in with Google/GitHub at https://infrai.cc/login for a
# project key + $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_..." # from https://infrai.cc/login
# 2) captcha.verify
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": "sample", "token": "sample"}'
# 3) captcha.widget.create
curl -X POST https://api.infrai.cc/v1/captcha/widget/create \
-H "Authorization: Bearer $INFRAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "example"}'
# 4) captcha.widget.list
curl -X GET https://api.infrai.cc/v1/captcha/widget/list \
-H "Authorization: Bearer $INFRAI_API_KEY"
# 5) captcha.widget.get
curl -X GET https://api.infrai.cc/v1/captcha/widget/get/WIDGET_RECORD_ID \
-H "Authorization: Bearer $INFRAI_API_KEY"
# 1) Auth: every call is a raw HTTPS request carrying only your project key.
# No SDK to install — just the `requests` library.
import os, requests
BASE = "https://api.infrai.cc"
HEADERS = {
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
"Content-Type": "application/json",
}
# 2) captcha.verify
# Zero-install REST call — no SDK required (short-term the API is REST-only).
import os, requests
resp = requests.post(
"https://api.infrai.cc/v1/captcha/verify",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
json={'widget_record_id': 'sample', 'token': 'sample'},
)
resp.raise_for_status()
print(resp.json())
# 3) captcha.widget.create
# Zero-install REST call — no SDK required (short-term the API is REST-only).
import os, requests
resp = requests.post(
"https://api.infrai.cc/v1/captcha/widget/create",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
json={'name': 'example'},
)
resp.raise_for_status()
print(resp.json())
# 4) captcha.widget.list
# Zero-install REST call — no SDK required (short-term the API is REST-only).
import os, requests
resp = requests.get(
"https://api.infrai.cc/v1/captcha/widget/list",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
)
resp.raise_for_status()
print(resp.json())
# 5) captcha.widget.get
# Zero-install REST call — no SDK required (short-term the API is REST-only).
import os, requests
resp = requests.get(
"https://api.infrai.cc/v1/captcha/widget/get/WIDGET_RECORD_ID",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
)
resp.raise_for_status()
print(resp.json())
// 1) Auth: every call is a raw HTTPS request carrying only your project key.
// No SDK to install — just the built-in fetch().
const BASE = "https://api.infrai.cc";
const HEADERS = {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
};
// 2) captcha.verify
// Browser prerequisite: fetch the public WidgetSetup from your server; never expose INFRAI_API_KEY.
const widget = await fetch("/captcha-config").then((r) => r.json());
const script = document.createElement("script");
script.src = widget.embed_url;
script.onload = () => turnstile.render("#captcha", {
sitekey: widget.sitekey, action: "signup",
callback: (token) => fetch("/signup", {
method: "POST", headers: { "Content-Type": "application/json" },
body: JSON.stringify({ token, widget_record_id: widget.widget_record_id }),
}),
});
document.head.appendChild(script); // page contains <div id="captcha"></div>
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/captcha/verify",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"widget_record_id": "sample", "token": "sample"}),
},
);
console.log(await resp.json());
// 3) captcha.widget.create
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/captcha/widget/create",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"name": "example"}),
},
);
console.log(await resp.json());
// Browser code (public values only; never expose INFRAI_API_KEY):
// Your server exposes only the public create response at /captcha-config.
const widget = await fetch("/captcha-config").then((r) => r.json());
const script = document.createElement("script");
script.src = widget.embed_url;
script.onload = () => turnstile.render("#captcha", {
sitekey: widget.sitekey, action: "signup",
callback: (token) => fetch("/signup", {
method: "POST", headers: { "Content-Type": "application/json" },
body: JSON.stringify({ captcha_token: token, widget_record_id: widget.widget_record_id }),
}),
});
document.head.appendChild(script); // page contains <div id="captcha"></div>
// 4) captcha.widget.list
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/captcha/widget/list",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
console.log(await resp.json());
// 5) captcha.widget.get
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/captcha/widget/get/WIDGET_RECORD_ID",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
console.log(await resp.json());
// 1) Auth: every call is a raw HTTPS request carrying only your project key.
// No SDK to install — just the built-in fetch(), typed.
const BASE = "https://api.infrai.cc";
const HEADERS: Record<string, string> = {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
};
// 2) captcha.verify
declare const turnstile: { render(selector: string, options: { sitekey: string; action: string; callback(token: string): void }): void };
// Browser prerequisite: fetch the public WidgetSetup from your server; never expose INFRAI_API_KEY.
const widget = await fetch("/captcha-config").then((r) => r.json());
const script = document.createElement("script");
script.src = widget.embed_url;
script.onload = () => turnstile.render("#captcha", {
sitekey: widget.sitekey, action: "signup",
callback: (token) => fetch("/signup", {
method: "POST", headers: { "Content-Type": "application/json" },
body: JSON.stringify({ token, widget_record_id: widget.widget_record_id }),
}),
});
document.head.appendChild(script); // page contains <div id="captcha"></div>
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/captcha/verify",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"widget_record_id": "sample", "token": "sample"}),
},
);
if (!resp.ok) throw new Error(`infrai ${resp.status}`);
const data: unknown = await resp.json();
console.log(data);
// 3) captcha.widget.create
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/captcha/widget/create",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"name": "example"}),
},
);
if (!resp.ok) throw new Error(`infrai ${resp.status}`);
const data: unknown = await resp.json();
console.log(data);
// Browser code (public values only; never expose INFRAI_API_KEY):
declare const turnstile: { render(selector: string, options: { sitekey: string; action: string; callback(token: string): void }): void };
// Your server exposes only the public create response at /captcha-config.
const widget = await fetch("/captcha-config").then((r) => r.json()) as { sitekey: string; embed_url: string; widget_record_id: string };
const script = document.createElement("script");
script.src = widget.embed_url;
script.onload = () => turnstile.render("#captcha", {
sitekey: widget.sitekey, action: "signup",
callback: (token) => { void fetch("/signup", {
method: "POST", headers: { "Content-Type": "application/json" },
body: JSON.stringify({ captcha_token: token, widget_record_id: widget.widget_record_id }),
}); },
});
document.head.appendChild(script); // page contains <div id="captcha"></div>
// 4) captcha.widget.list
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/captcha/widget/list",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
if (!resp.ok) throw new Error(`infrai ${resp.status}`);
const data: unknown = await resp.json();
console.log(data);
// 5) captcha.widget.get
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/captcha/widget/get/WIDGET_RECORD_ID",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
if (!resp.ok) throw new Error(`infrai ${resp.status}`);
const data: unknown = await resp.json();
console.log(data);
5. Developer guides
Move from endpoint details to complete workflows, production patterns and troubleshooting guides verified against the live API.
Captcha developer guides