HumanGate(1) CAPTCHA-as-a-service HumanGate(1)
NAME
HumanGate - CAPTCHA verification gateway for Telegram bots and apps.
You bring your own CAPTCHA provider keys (Cloudflare Turnstile, Google
reCAPTCHA, Yandex SmartCaptcha) or use a HumanGate-native captcha. We host
the verification page, validate the answer, check Telegram initData, score
risk, and hand the result back via webhook, redirect code, or polling.
API base: https://humangate.vsecoder.vodka
Pages: /example (live demo) /docs (Swagger) /openapi.yaml
STATS
CAPTCHAs generated: —
CAPTCHAs passed: — (open: GET /public/v1/stats)
AUTH
Authorization: Bearer hg_live_... (or hg_test_... for test mode)
Self-service or admin CLI; every response carries "livemode".
QUICKSTART
# 0. Issue your own token (no auth) - returns a live and a test key.
# Or use the admin CLI / set OPEN_SIGNUP=false to disable this.
curl -X POST https://humangate.vsecoder.vodka/v1/signup -d '{"name": "My project"}'
# -> {"project":"t_...","live_key":"hg_live_...","test_key":"hg_test_...","scopes":[...]}
# Mint extra keys later: POST /v1/api-keys (scope api_keys:manage)
# 1. Save your CAPTCHA keys once (secret_key is encrypted, never returned).
# The first config for a (provider, mode) pair becomes the default.
curl https://humangate.vsecoder.vodka/v1/provider-configs \
-H "Authorization: Bearer hg_live_..." \
-d '{
"name": "main",
"provider": "cloudflare_turnstile",
"config": {"site_key": "0x4AAAA...", "secret_key": "0x4AAAA..."}
}'
# 2. Create a challenge per user. The response has "url" - send it to them.
curl https://humangate.vsecoder.vodka/v1/challenges \
-H "Authorization: Bearer hg_live_..." \
-d '{
"provider": "cloudflare_turnstile",
"action": "telegram_registration",
"subject": {"type": "telegram_user", "id": "123456789"},
"redirect": {"success_url": "https://t.me/your_bot?start=verify_{code}"}
}'
# -> {"id":"ch_...","status":"pending","url":"https://.../c/hgc_..."}
# 3. User passes the CAPTCHA and returns to your bot with /start verify_.
# Verify the code (single-use).
curl https://humangate.vsecoder.vodka/v1/verifications/verify \
-H "Authorization: Bearer hg_live_..." \
-d '{"code": "A7F2K9XW4M", "expected_action": "telegram_registration"}'
# -> {"valid":true,"subject":{...},"risk_score":14,
# "client":{"ip":"203.0.113.7","user_agent":"Mozilla/5.0 ...",
# "device":{"screen_width":390,"pixel_ratio":3,
# "connection":{"effective_type":"4g","downlink_mbps":12.5,"rtt_ms":80},
# "timing":{"ttfb_ms":120,"load_ms":640}},
# "telegram":{"valid":true,"user_id":"123456789","init_data":"query_id=..."}}}
PROVIDERS
cloudflare_turnstile external, needs provider-config keys
google_recaptcha_v2 external, checkbox widget
google_recaptcha_v3 external, invisible/score-based (config.min_score)
yandex_smartcaptcha external, normal or invisible (config.invisible)
text_image native, server-rendered distorted text, no keys
proof_of_work native, SHA-256 leading-zero-bits, no keys
browser_fingerprint native, anti-headless heuristics, no keys
Native captchas need no keys: the task is returned by /start (field "task")
and verified server-side against per-session state. The browser never learns
the expected answer.
WEBHOOK
Events: challenge.passed | challenge.failed | challenge.blocked | challenge.expired
Signature: HumanGate-Signature: v1=HMAC_SHA256(secret, "." + body)
Any 2xx response means delivered; retries use exponential backoff.
LIVE DEMO (test mode, no API key)
# Returns a challenge url you can open in a browser.
curl -X POST https://humangate.vsecoder.vodka/public/v1/demo -d '{"provider":"text_image"}'
# Available demo providers:
curl https://humangate.vsecoder.vodka/public/v1/demo
SEE ALSO
/example - live demo links (click a provider to try a captcha)
/docs - Swagger UI (interactive API explorer)
/openapi.yaml - machine-readable OpenAPI 3 spec