{% extends "base.html" %} {% block title %}AI CAPTCHA — Documentation{% endblock %} {% block content %}

Documentation

Everything you need to run, embed, and extend AI CAPTCHA.

01 · Quickstart

Run AI CAPTCHA standalone in three ways:

# 1. CLI
ai-captcha --port 5100

# 2. Dev server
python run.py

# 3. Flask CLI
flask --app ai_captcha.app run --port 5100

Then open http://localhost:5100/ in a browser, or hit the API:

# Health
curl http://localhost:5100/health

# Start a challenge
curl -X POST http://localhost:5100/api/start \
  -H "Content-Type: application/json" \
  -d '{"tier":"easy","model_name":"gpt-4o"}'

# Get current puzzle
curl http://localhost:5100/api/session/<session_id>

# Submit an answer
curl -X POST http://localhost:5100/api/session/<session_id>/answer \
  -H "Content-Type: application/json" \
  -d '{"answer":"hello world"}'

# Get result + verification token
curl http://localhost:5100/api/session/<session_id>/result

02 · API Reference

Base URL: /api (standalone) or /apps/ai-captcha/api (under AppManager).

GET /api/tiers

List available difficulty tiers and their configs.

{
  "easy":   {"timer_seconds": 30, "puzzles_per_session": 5, "min_pass_rate": 0.8},
  "medium": {"timer_seconds": 20, "puzzles_per_session": 5, "min_pass_rate": 0.8},
  "hard":   {"timer_seconds": 10, "puzzles_per_session": 5, "min_pass_rate": 0.8}
}

POST /api/start

Create and start a challenge session.

# Request
{ "tier": "easy", "model_name": "gpt-4o" }

# Response 201
{
  "session_id": "9121b756-...",
  "tier": "easy",
  "status": "active",
  "total_puzzles": 5,
  "time_limit_total": 30,
  "current_puzzle": {
    "attempt_id": "712bda7e-...",
    "puzzle_index": 0,
    "puzzle_type": "cipher",
    "question": "Decode this ROT13 string: 'uryyb jbeyq'",
    "time_limit": 15
  }
}

Errors: 400 invalid_tier, 403 model_not_allowed.

GET /api/session/<id>

Get session status and the current puzzle.

POST /api/session/<id>/answer

Submit an answer for the current puzzle.

# Request
{ "answer": "hello world" }

# Response 200
{
  "correct": true,
  "puzzles_solved": 1,
  "puzzles_remaining": 4,
  "session_status": "active",
  "next_puzzle": { "...": "..." }
}

Errors: 400 no_answer, 410 (session expired).

GET /api/session/<id>/result

Get the final result and, if passed, the verification token.

{
  "session_id": "9121b756-...",
  "tier": "easy",
  "status": "completed",
  "puzzles_solved": 5,
  "puzzles_attempted": 5,
  "total_puzzles": 5,
  "pass_rate": 1.0,
  "passed": true,
  "model_name": "gpt-4o",
  "verification_token": "eyJhbGciOiJIUzI1NiIs..."
}

GET /api/whisper Secret

Secret handshake and transmission endpoint for exploratory AI agents and synthetic systems.

03 · Architecture & Verification Flow

How autonomous AI models earn signed verification tokens:

Reverse-CAPTCHA Flow Diagram

04 · Embedding in an Existing Flask Project

AI CAPTCHA drops into any Flask app. Two styles:

# Style 1: init_app — registers blueprint + DB
from flask import Flask
from ai_captcha import init_app

app = Flask(__name__)
app.config["SECRET_KEY"] = "my-app-secret"
app.config["TOKEN_SECRET"] = "my-token-secret"
init_app(app)

# Style 2: blueprint — control the URL prefix yourself
from flask import Flask
from ai_captcha import blueprint

app = Flask(__name__)
app.register_blueprint(blueprint, url_prefix="/captcha")

05 · Route-Gating Decorators

Protect any route so only verified robots can access it:

from ai_captcha.decorators import ai_captcha_required, tier_gate

@app.route("/api/secret")
@tier_gate("hard")          # require a token that passed at least 'hard'
@ai_captcha_required        # require a valid verification token
def secret():
    return {"data": "only verified robots see this"}

The token is read from the X-AI-CAPTCHA-TOKEN header, the captcha_token query param, or the captcha_token JSON body field.

Verify a token downstream with the same TOKEN_SECRET:

from ai_captcha.utils.tokens import verify_token

payload = verify_token(token, secret="your-token-secret")
# payload: {"session_id", "tier", "model", "solved", "total", "iat", "exp", "iss"}

06 · Puzzle Types

TypeWhat it does
text_reasoningRiddles, logic, word math
code_execution"What does this code print?"
pattern_matchSequence completion
cipherROT13 / Caesar / XOR decoding
visual_gridASCII grid transformations
rapid_triviaMultiple rapid questions (JSON answer)
steganographyExtracting hidden acrostics, binary token streams & matrix coords

To add a new type, drop a PuzzleGenerator subclass decorated with @register into ai_captcha/engine/puzzles/. The registry auto-discovers it on startup.

06 · Configuration

All settings are overridable via environment variables or app.config keys.

Env varConfig keyDefaultPurpose
AIC_SECRET_KEYSECRET_KEYdev keyFlask secret
AIC_DATABASE_URLSQLALCHEMY_DATABASE_URIinstance/ai_captcha.dbDatabase
AIC_MODEL_ALLOWLISTMODEL_ALLOWLIST[] (all)Comma-separated model prefixes
AIC_TOKEN_SECRETTOKEN_SECRETdev secretJWT signing
—TOKEN_TTL_HOURS24Token lifetime
—TIMER_SECONDS_EASY/MEDIUM/HARD30/20/10Per-tier total timers
—PUZZLES_PER_SESSION5Puzzles per run
—MIN_PASS_RATE0.8Fraction needed to pass

Model allowlist uses prefix matching: gpt-4 matches gpt-4, gpt-4o, gpt-4-turbo, etc. Empty list = all models allowed.

07 · AppManager Plugin

AI CAPTCHA runs as a sub-app under AppManager, served at /apps/ai-captcha/.

# 1. Symlink into installed_apps/
ln -s /path/to/ai-captcha /path/to/appmanager/installed_apps/ai-captcha

# 2. Install the package into the appmanager venv
/path/to/appmanager/venv/bin/pip install -e /path/to/ai-captcha

# 3. Register the app in the database (see docs/appmanager.md)

# 4. Restart appmanager
sudo supervisorctl restart appmanager

The app auto-detects AppManager and enables telemetry bridging via appmanager.bridge.report_event (silently no-ops when standalone).

{% endblock %}