Caputchin
Integration guides

Server side integration

The widget hands the browser a one-time token. That token proves nothing until your server confirms it with Caputchin. This is the step that turns a visible challenge into real protection, and it is a single HTTPS call.

You need a backend that can make an outbound request, and your site key's secret (cpt_sec_...) available there, never in the browser.

1. Read the token

When the form posts, your handler receives one extra field alongside your own: caputchin-token. The widget injected it into the form when the visitor cleared the challenge.

2. Confirm it with /siteverify

POST the token and your secret. The request and response are shaped like reCAPTCHA's siteverify, so an existing integration ports with little change:

POST https://caputchin.com/api/v1/siteverify
Content-Type: application/json

{ "secret": "cpt_sec_...", "response": "<caputchin-token>" }
// Node 18+
const verdict = 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,
  }),
}).then((r) => r.json());

if (!verdict.success) {
  // reject the submission
}

The same call in other languages is on backend integration examples.

3. Read the response

{
  "success": true,
  "error-codes": [],
  "platform": { "game_id": "caputchin/games/leaf-memory", "score": 847, "duration_ms": 4200 }
}
  • success is the only thing to branch on. true means a real visitor cleared the challenge; trust the request. false means drop it.
  • error-codes appears when success is false, naming what went wrong (a missing, expired, or already-used token, and so on).
  • platform is client-claimed metadata (which game, the score, the duration). It is nullable and is not a security signal. Record it for analytics if you like, but never gate trust on the score.

The rules that protect you

  • Single-use. A token verifies once. Submitting the same one again returns success: false, so you do not have to track replays yourself.
  • Short-lived. A token expires ten minutes after it is issued, so verify it while handling the submission, not on a delayed job.
  • The secret stays on the server. It never goes to the browser, and it is what authenticates the call.

Common mistakes

  • Verifying client-side. The pass event and the token's presence are UX only. Every trust decision happens here, server-side, with your secret.
  • Gating on score. It is metadata, not a confidence value.

See also

On this page