Set up hosted verification with a test inbox
By the end of this tutorial you will have a working contact form whose submissions are verified by Caputchin and delivered to a webhook, and you will have watched a verified submission land in a test inbox you can inspect. We use webhook.site as the destination first, because it shows you the exact payload Caputchin sends before you commit to your own endpoint.
You need an Alpha, Troop, or Apex plan (hosted verification is not on Solo), a site key, and a page where you can edit the form's HTML. If you have not added the widget to a page yet, do add the widget first; this tutorial assumes a working <caputchin-widget>.
1. Get a test inbox
Open webhook.site in a new tab. It immediately gives you a unique URL that looks like https://webhook.site/#!/<uuid>, and a matching delivery URL of the form https://webhook.site/<uuid>. Copy the delivery URL (the one without the #!/). Leave the tab open; every request it receives appears there in real time.
This URL is a stand-in for your real webhook. Treat it as throwaway, since anyone with the URL can read what arrives.
2. Turn on hosted verification
In the dashboard, open the site key and go to its Hosted verification page.
- Paste the webhook.site delivery URL into the webhook URL field.
- Leave email empty for now.
- Save.
You do not have to flip the enabled toggle yet. The next step uses Test delivery, which works on a saved destination whether or not hosted verification is switched on, so you can confirm the wiring before going live.
3. Send a test delivery
On the same page, use Test delivery. Caputchin sends a synthetic submission straight to your destination without running a game or verifying a token, so it is a pure check of the destination wiring.
Switch to the webhook.site tab. A new POST appears within a second or two. Its JSON body looks like this:
{
"caputchin": {
"site_key": "cpt_pub_...",
"session_id": "test_...",
"game_id": null,
"score": null,
"duration_ms": null,
"verified_at": 1748640000000,
"test": true
},
"form": {
"email": "test@example.com",
"message": "Test submission from your Caputchin dashboard."
}
}The "test": true marker tells your handler this was a dashboard test, not a real visitor; it is absent on real submissions. If you see this payload, the destination works. If nothing arrives, re-check that you copied the delivery URL (not the #!/ viewer URL) and saved it.
4. Point your form at the forwarder
Now make a real submission go through Caputchin. The only change to your form is its action: instead of your own backend, it posts to the forwarder URL the site key shows you on the Hosted verification page.
<form action="https://caputchin.com/api/forward/cpt_pub_..." method="POST">
<input name="email" type="email" />
<input name="message" />
<caputchin-widget sitekey="cpt_pub_..."></caputchin-widget>
<button type="submit">Send</button>
</form>Nothing else changes. The widget still injects the hidden caputchin-token field when the visitor clears the challenge; the forwarder reads that field, verifies it, and strips it before delivering the rest to your destination.
5. Enable hosted verification
Back on the Hosted verification page, flip the enabled toggle on and save. The forwarder rejects submissions for a site key that is not enabled, so this switch is what makes step 4 live.
6. Submit the form for real
Load your page, fill the form, clear the challenge, and submit. Watch the webhook.site tab: a second POST arrives, this time with no test field and with real verification metadata.
{
"caputchin": {
"site_key": "cpt_pub_...",
"session_id": "...",
"game_id": "caputchin/games/leaf-memory",
"score": 847,
"duration_ms": 4200,
"verified_at": 1748640000000
},
"form": {
"email": "visitor@example.com",
"message": "Hello!"
}
}That is the whole path: visitor submits, Caputchin verifies, your destination receives only the verified submission. A submission that fails verification (a missing, expired, or reused token) never reaches your destination at all.
Treat the caputchin block the way you would a backend verdict: game_id, score, and duration_ms are client-claimed metadata for your analytics, not a trust signal. The trust decision is the fact that the submission arrived at all. Any of those three can be null on a real submission (for example a verification with no game), so guard for null before you read them.
7. Try the email destination too
webhook.site also gives each inbox an email address, so you can test email delivery the same way. On the webhook.site page, find your inbox's unique email address and copy it; at the time of writing it looks like <your-inbox-id>@emailhook.site, but check the page for the current form since webhook.site owns that detail. Then:
- Back on the Hosted verification page, paste that address into the email field.
- Save, and use Test delivery again.
The email arrives in the webhook.site inbox alongside the requests: a plain message carrying the form fields and a footer noting Caputchin verified the submission. Email is delivered through Caputchin's email provider, so it can take a little longer to land than a webhook POST. With both a webhook URL and an email address set, a single submission fans out to both, and counts as delivered if either one succeeds.
8. Swap in your real destination
When the test inbox has shown you what to expect, replace it with your own:
- Your own webhook. Put your endpoint's URL in the webhook URL field. It must be a public
httpsURL; Caputchin refuses URLs that resolve to private, loopback, or cloud-metadata addresses, and it will not follow redirects. Your handler receives exactly the JSON shape above. Deliveries are not signed, so keep the URL secret, since its secrecy is what authenticates the call. - Email instead, or as well. Put your own address in the email field, the same way you tested it above. You can run both at once, for example a webhook for processing plus an email copy to yourself.
Send one more real submission against the live destination to confirm, then you are done.
Where to go next
- Hosted verification statistics: watch delivery health over time.
- Hosted verification: the concepts, the privacy posture, and what is intentionally left out.
- Verify on your backend: the alternative if you later add a server.