Caputchin
Integration guides

Backend integration examples

Server side integration is a plain JSON POST, so there is no first-party SDK in any language: use whatever HTTP client your backend already has. Each example below sends your secret and the token from the form, then reads success from the response. All of them assume the secret is in an environment variable, never in code.

Node (fetch, built in since 18)

const res = await fetch("https://caputchin.com/api/v1/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://caputchin.com/api/v1/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://caputchin.com/api/v1/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://caputchin.com/api/v1/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://caputchin.com/api/v1/siteverify")
res = Net::HTTP.post(
  uri,
  { secret: ENV["CAPUTCHIN_SECRET"], response: token }.to_json,
  "Content-Type" => "application/json",
)
raise "verification failed" unless JSON.parse(res.body)["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://caputchin.com/api/v1/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");

curl (for a quick test)

curl -sS https://caputchin.com/api/v1/siteverify \
  -H "Content-Type: application/json" \
  -d "{\"secret\":\"$CAPUTCHIN_SECRET\",\"response\":\"$TOKEN\"}"

A typed client

If you would rather work with a typed client, point an OpenAPI generator at the Runtime API reference; /siteverify lives in the runtime spec, not the management one. The contract is small, so the generated output is short.

See also

On this page