Docs / Server verify / Python
Verify Playtcha from Python
This page is the server-side contract for Python apps. Your server receives a client-submitted result token, posts it to /v1/verify with your secret key, and decides whether to continue the request.
Minimal example
The shortest correct shape is still { secret, token } plus a timeout.
Production-ready example
In production, preserve the upstream error envelope in logs and remember that degraded still means success.
Common gotchas
- Do not verify from browser-side Python wrappers or edge client code that would expose the secret key.
- Fail open on 5xx and network errors; fail closed on 4xx. Opt into PLAYTCHA_FAIL_CLOSED=1 for high-fraud paths.
- Treat degraded=True as success. It is a usage-band signal, not a failed human check.
- 409 already_redeemed is single-use-by-design. In production it means replay, stuck retry, or duplicate POST. Log with request_id at warn level — do not retry.
- 429 rate_limited_ip means per-IP throttle. Honor the Retry-After header; do not retry tighter than 1s.
- The wire format has no success:false field on errors. The envelope is { error: { code, message, request_id, ... } }.
- On non-2xx verify responses, parse the upstream error envelope instead of assuming an error_codes array.
- Use a timeout so verify stays a bounded dependency in signup or contact-form flows.
Relevant failure codes
| Status | Code | Meaning |
|---|---|---|
| 401 | token_invalid | Bad signature or claims. Often wrong env (live vs test). |
| 401 | bad_secret | Secret does not match the project. Config error. |
| 404 | unknown_project | Project deleted or never existed. |
| 409 | already_redeemed | Security signal. Single-use by design. Log with request_id at warn level. |
| 410 | token_expired | Result token TTL elapsed (5 minutes). |
| 429 | rate_limited_ip | Per-IP throttle. Response has Retry-After header. |
| 500 | db_error | Playtcha-side. Fail open. |
Where to go next
Pair this with token lifecycle for the token model, or domain whitelist if you are debugging origin failures before verify ever runs.