API Endpoint Protection

Turnstile isn't just for HTML forms. This page shows how to protect a JSON API endpoint that a customer might expose (payment intents, account signup, password reset, etc.).

The story: Customers often assume Turnstile only fits browser-rendered forms. In reality, any client that can render the widget (mobile app WebView, embedded browser, iframe) can produce a token, and any server can verify it via siteverify. This makes it viable for protecting mobile API traffic, third-party integrations, and back-office tools.

Try it from the browser

Solve the widget, then submit. The browser posts JSON to /api/verify, the Worker validates with siteverify, and returns a signed response.

Response will appear here.

Try it from curl (will fail - as expected)

A direct curl to /api/verify without a valid Turnstile token gets rejected. Copy-paste this into a terminal to see:

curl -X POST https://turnstile.paulscouncil.com/api/verify \
  -H "Content-Type: application/json" \
  -H "X-Turnstile-Token: fake-token" \
  -d '{"payload":"attempt-from-cli"}'

You'll get {"success":false,"error":"invalid-turnstile-token"}. This is the point - even someone with valid API credentials can't hit the endpoint without proving they came through a real client.

Try it from a gentler endpoint (adaptive)

See GET /api/gentle - open by default, but requires a Turnstile token if you've made more than 5 requests in the last minute from your IP.

Refresh /api/gentle 6+ times quickly to trip the escalation.

Enterprise-grade pattern: Combine this with Cloudflare API Shield (schema validation + mTLS + JWT auth) for defence in depth. Turnstile proves "a real browser visited us"; API Shield proves "the request matches the OpenAPI contract"; mTLS/JWT proves "the client is who they say they are". Three orthogonal signals.