postcaptcha

A contact form gated by a Trust Check

This form runs in keyless mode against the production API: no site key, no account, no secret. Nothing you type is stored; the server only verifies the Trust Check.

  1. The page renders the widget in explicit mode and keeps Send disabled.
  2. You click the box. The widget asks Polyguard for this page’s link, then shows a code to scan with your phone.
  3. Your phone completes the Trust Check. The widget puts the result in a hidden pg-trust-check-response input and calls its callback, which enables Send.
  4. Send posts the form to /api/submit on this site. That handler calls /v2/siteverify, compares hostname with the hostname this page was served from, and returns what it received.
  5. The result verifies once. The widget resets, so a second message needs a new Trust Check.
// app/api/submit/route.ts (abridged)
const response = form.get('pg-trust-check-response');
const body = new URLSearchParams({ response, remoteip });
if (process.env.POLYGUARD_SITEVERIFY_SECRET) body.set('secret', ...);

const siteverify = await fetch('https://api.polyguard.ai/v2/siteverify', {
  method: 'POST', body,
}).then((r) => r.json());

const verified = siteverify.success && siteverify.hostname === requestHost;
return Response.json({ verified, hostname_matched, siteverify });

The full handler is app/api/submit/route.ts in the repo. Moving from another CAPTCHA? See the reCAPTCHA and Turnstile guides.

Live demo: send us a note

After you send, this page shows the JSON our server received from /v2/siteverify.