Code snippets
Copy-paste examples for calling /siteverify from common backends. The canonical request and response shape lives in api.md; this page is the convenience layer. There is no first-party SDK — see ADR-0011 for why.
For an OpenAPI spec you can feed to a code generator, see api.md — OpenAPI spec.
Server-side
Each example sends the customer's secret + the wrapped token from the form, and reads success from the response. All examples assume environment variables hold the secret.
Node (fetch, built-in since 18)
const res = await fetch('https://api.caputchin.com/siteverify', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
secret: process.env.CAPUTCHIN_SECRET,
response: token,
}),
});
const result = await res.json();
if (!result.success) throw new Error('verification failed');
Python (requests)
import os, requests
res = requests.post(
'https://api.caputchin.com/siteverify',
json={'secret': os.environ['CAPUTCHIN_SECRET'], 'response': token},
timeout=10,
)
res.raise_for_status()
if not res.json()['success']:
raise RuntimeError('verification failed')
PHP (cURL)
$ch = curl_init('https://api.caputchin.com/siteverify');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
CURLOPT_POSTFIELDS => json_encode([
'secret' => getenv('CAPUTCHIN_SECRET'),
'response' => $token,
]),
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);
if (!$result['success']) throw new Exception('verification failed');
Go (net/http)
body, _ := json.Marshal(map[string]string{
"secret": os.Getenv("CAPUTCHIN_SECRET"),
"response": token,
})
res, err := http.Post(
"https://api.caputchin.com/siteverify",
"application/json",
bytes.NewReader(body),
)
if err != nil { return err }
defer res.Body.Close()
var result struct{ Success bool `json:"success"` }
json.NewDecoder(res.Body).Decode(&result)
if !result.Success { return fmt.Errorf("verification failed") }
Ruby (Net::HTTP)
require 'net/http'
require 'json'
uri = URI('https://api.caputchin.com/siteverify')
res = Net::HTTP.post(
uri,
{ secret: ENV['CAPUTCHIN_SECRET'], response: token }.to_json,
'Content-Type' => 'application/json',
)
result = JSON.parse(res.body)
raise 'verification failed' unless result['success']
.NET (HttpClient)
using var http = new HttpClient();
var payload = JsonSerializer.Serialize(new {
secret = Environment.GetEnvironmentVariable("CAPUTCHIN_SECRET"),
response = token,
});
var res = await http.PostAsync(
"https://api.caputchin.com/siteverify",
new StringContent(payload, Encoding.UTF8, "application/json"));
var result = JsonSerializer.Deserialize<JsonElement>(await res.Content.ReadAsStringAsync());
if (!result.GetProperty("success").GetBoolean()) throw new Exception("verification failed");
Shell (curl) — for quick testing
curl -sS https://api.caputchin.com/siteverify \
-H 'Content-Type: application/json' \
-d "{\"secret\":\"$CAPUTCHIN_SECRET\",\"response\":\"$TOKEN\"}"
Client-side
The browser surface is a web component, which works in every JavaScript framework natively. There are no first-party framework wrappers — see roadmap.
Plain HTML
<script src="https://cdn.jsdelivr.net/npm/@caputchin/widget@1/dist/widget.js" async defer></script>
<form action="/contact" method="POST">
<caputchin-widget sitekey="cpt_pub_..." game="bubble-pop"></caputchin-widget>
<button>Submit</button>
</form>
React
import { useEffect } from 'react';
function ContactForm() {
useEffect(() => {
import('https://cdn.jsdelivr.net/npm/@caputchin/widget@1/dist/widget.js');
}, []);
return (
<form action="/contact" method="POST">
<caputchin-widget sitekey="cpt_pub_..." game="bubble-pop"></caputchin-widget>
<button>Submit</button>
</form>
);
}
Vue / Svelte / Angular / Solid / Qwik
Same pattern — load the script once, use the <caputchin-widget> element directly. Web components are first-class in all current major frameworks. See the widget reference for the full element shape and event API.
Generating your own typed client
If you'd rather work with a typed client in your language, run an OpenAPI generator against the spec served by the Web app — see api.md — OpenAPI spec. The contract is small (three endpoints) so the generated output is short.
Community-maintained libraries
When community-maintained wrappers emerge, they'll be listed here. We do not commission, host, or vouch for them.
| Language | Library | Maintainer |
|---|---|---|
| none yet |