caputchin
All docs
View raw .md

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