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 }
}successis the only thing to branch on.truemeans a real visitor cleared the challenge; trust the request.falsemeans drop it.error-codesappears whensuccessisfalse, naming what went wrong (a missing, expired, or already-used token, and so on).platformis 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
passevent 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
- Backend integration examples for this call in your language.
- Hosted verification to skip the backend entirely.