Server-Side Verification API
The token your frontend receives can only be trusted after it's checked on the server. This endpoint is compatible with the reCAPTCHA / hCaptcha siteverify API (it accepts both JSON request bodies and form encoding) — when migrating from them, your backend usually only needs to change one URL. See the migration guide for a side-by-side walkthrough.
Endpoint
POST https://api.capcat.ai/<site-key>/siteverify
Content-Type: application/json
{ "secret": "<secret_key>", "response": "<captcha_token>" }secret— the secret generated when you created the site in the console (shown only once, at creation or rotation);response— the token produced by the frontend widget (thecap-tokenfield in your form, ore.detail.tokenfrom thesolveevent).
A successful verification returns:
json
{ "success": true }The token is single-use: it becomes invalid immediately after a successful verification, and replaying it returns a failure.
Examples in multiple languages
sh
curl "https://api.capcat.ai/<site-key>/siteverify" \
-X POST \
-H "Content-Type: application/json" \
-d '{ "secret": "<secret_key>", "response": "<captcha_token>" }'js
const { success } = await (
await fetch("https://api.capcat.ai/<site-key>/siteverify", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ secret: "<secret_key>", response: "<captcha_token>" }),
})
).json();
if (!success) throw new Error("CAPTCHA verification failed");py
import requests
success = requests.post(
"https://api.capcat.ai/<site-key>/siteverify",
json={"secret": "<secret_key>", "response": "<captcha_token>"},
).json().get("success")php
<?php
$ctx = stream_context_create([
"http" => [
"method" => "POST",
"header" => "Content-Type: application/json",
"content" => json_encode([
"secret" => "<secret_key>",
"response" => "<captcha_token>",
]),
],
]);
$data = json_decode(file_get_contents(
"https://api.capcat.ai/<site-key>/siteverify", false, $ctx
), true);
var_dump($data["success"] ?? false);