Metadata-Version: 2.3
Name: fastapi-roundtable
Version: 0.1.0
Summary: Invisible bot protection for FastAPI applications using Roundtable.ai Proof-of-Human detection
License: MIT
Keywords: fastapi,bot-detection,security,roundtable,proof-of-human,spam-prevention,api-protection,session-validation
Author: Leandro Lima
Author-email: leandro@lls-software.com
Requires-Python: >=3.9
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Framework :: FastAPI
Classifier: Topic :: Internet :: WWW/HTTP
Classifier: Topic :: Security
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Dist: aiohttp (>=3.12.14)
Requires-Dist: fastapi (>=0.100.0)
Requires-Dist: pydantic (>=2.0.0)
Project-URL: Documentation, https://github.com/leandropls/fastapi-roundtable#readme
Project-URL: Homepage, https://github.com/leandropls/fastapi-roundtable
Project-URL: Issues, https://github.com/leandropls/fastapi-roundtable/issues
Project-URL: Repository, https://github.com/leandropls/fastapi-roundtable
Project-URL: Roundtable.ai, https://roundtable.ai
Description-Content-Type: text/markdown

# fastapi-roundtable

Invisible bot protection for FastAPI applications using [Roundtable.ai](https://roundtable.ai) Proof-of-Human detection.

[![PyPI version](https://badge.fury.io/py/fastapi-roundtable.svg)](https://pypi.org/project/fastapi-roundtable/)
[![Python 3.9+](https://img.shields.io/badge/python-3.9+-blue.svg)](https://www.python.org/downloads/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

## Overview

`fastapi-roundtable` is a FastAPI integration for [Roundtable.ai](https://roundtable.ai) Proof-of-Human bot detection.
It provides backend session validation for protecting your FastAPI endpoints from automated bots and
suspicious activity.

Roundtable uses behavioral biometrics and device analysis to detect bots with best-in-class accuracy
(87% vs Google's 69% and Cloudflare's 33%). Unlike CAPTCHAs, it works invisibly in the background,
providing a frictionless experience for legitimate users while blocking automated threats.

This library handles the backend validation piece, making it easy to verify session IDs generated by
Roundtable's frontend JavaScript tracker.

## How It Works

```
┌─────────────┐
│   Browser   │  1. Roundtable JS tracker monitors user behavior
│  (Frontend) │  2. Generates session ID based on behavioral analysis
└──────┬──────┘
       │ Session ID (form field, header, or body)
       ▼
┌─────────────┐
│   FastAPI   │  3. fastapi-roundtable validates session ID
│  (Backend)  │  4. Queries Roundtable API for risk score
└──────┬──────┘  5. Rejects high-risk sessions automatically
       │
       ▼
┌─────────────┐
│ Roundtable  │  Returns risk score (0-100)
│     API     │  Higher score = more suspicious
└─────────────┘
```

The result: Bots and automated attacks are blocked before they can exploit your system, while
legitimate users never see a CAPTCHA or challenge.

## Features

- **Async session validation** using aiohttp for high performance
- **Multiple session ID sources** - extract from form fields, HTTP headers, or request body
- **Configurable risk thresholds** - set your own acceptable risk level
- **Type-safe** - full type hints throughout
- **Environment variable support** - secure API key management
- **FastAPI-native** - uses dependency injection for clean integration

## Prerequisites

Before using this library, you need:

1. A [Roundtable.ai account](https://accounts.roundtable.ai) with Site Key and Secret Key
2. Roundtable's JavaScript tracker installed on your frontend pages
3. A FastAPI application

## Installation

```bash
pip install fastapi-roundtable
```

## Quick Start

### 1. Add Roundtable tracker to your frontend

```html
<!DOCTYPE html>
<html>
<head>
    <title>Contact Form</title>
</head>
<body>
    <form method="POST" action="/contact">
        <!-- Hidden field for Roundtable session ID -->
        <input type="hidden" name="rt_session_id" id="rt_session_id" value="">

        <input type="text" name="name" placeholder="Your name" required>
        <input type="email" name="email" placeholder="Your email" required>
        <textarea name="message" placeholder="Your message" required></textarea>
        <button type="submit">Send</button>
    </form>

    <!-- Load Roundtable tracker -->
    <script src="https://cdn.roundtable.ai/v1/rt.js"
            data-site-key="YOUR_SITE_KEY"></script>

    <!-- Populate hidden field with session ID from sessionStorage -->
    <script>
        const interval = setInterval(() => {
            if (sessionStorage.getItem('rtSessionId')) {
                clearInterval(interval);
                document.getElementById("rt_session_id").value = sessionStorage.getItem('rtSessionId');
            }
        }, 500);
    </script>
</body>
</html>
```

The Roundtable tracker stores the session ID in `sessionStorage.rtSessionId`. The JavaScript code
polls for this value and populates the hidden form field when available.

### 2. Protect your FastAPI endpoint

```python
from fastapi import Depends, FastAPI
from fastapi_roundtable import Roundtable

app = FastAPI()

# Initialize Roundtable validator (do this once, reuse across endpoints)
roundtable = Roundtable(
    api_key="your_secret_key",  # or set ROUNDTABLE_API_KEY env var
    status_code=404,            # HTTP status to return on validation failure
    max_risk_score=50           # Maximum acceptable risk score (0-100)
)

@app.post("/contact", dependencies=[Depends(roundtable(form_field="rt_session_id"))])
async def contact_form(name: str, email: str, message: str):
    # This code only runs if session validation passes
    # Bots and high-risk sessions are automatically rejected
    return {"message": "Thank you for your message!"}
```

That's it! Your endpoint is now protected from bots.

## Detailed Usage Examples

### Form-Based Validation

Perfect for contact forms, signup pages, and user submissions:

```python
from fastapi import Depends, FastAPI, Form
from fastapi_roundtable import Roundtable

app = FastAPI()
roundtable = Roundtable()

@app.post("/signup", dependencies=[Depends(roundtable(form_field="rt_session_id"))])
async def signup(
    username: str = Form(...),
    email: str = Form(...),
    password: str = Form(...)
):
    # Only legitimate users reach this code
    return {"status": "success"}
```

### Header-Based Validation

Ideal for API endpoints and mobile applications:

```python
@app.post("/api/submit", dependencies=[Depends(roundtable(http_header="X-Session-ID"))])
async def api_submit(data: dict):
    # Validate session from custom header
    return {"received": data}
```

Client sends request with header:
```
POST /api/submit
X-Session-ID: <roundtable_session_id>
```

### Body-Based Validation

For JSON APIs where session ID is in the request payload:

```python
@app.post("/api/create", dependencies=[Depends(roundtable(body_field="session_id"))])
async def create_resource(data: dict):
    return {"created": True}
```

Client sends JSON:
```json
{
  "session_id": "<roundtable_session_id>",
  "name": "Resource name",
  "data": {...}
}
```

### Custom Error Handling

Customize the response when validation fails:

```python
from fastapi import HTTPException, Request
from fastapi.responses import HTMLResponse

@app.exception_handler(HTTPException)
async def custom_http_exception_handler(request: Request, exc: HTTPException):
    if exc.status_code == 404:
        return HTMLResponse(
            content="<h1>Access Denied</h1><p>Suspicious activity detected.</p>",
            status_code=404
        )
    return JSONResponse(
        status_code=exc.status_code,
        content={"detail": exc.detail}
    )
```

### Reusing Across Multiple Endpoints

Initialize once, use everywhere:

```python
app = FastAPI()
roundtable = Roundtable(max_risk_score=60)

@app.post("/contact", dependencies=[Depends(roundtable(form_field="rt_session_id"))])
async def contact(): ...

@app.post("/signup", dependencies=[Depends(roundtable(form_field="rt_session_id"))])
async def signup(): ...

@app.post("/api/data", dependencies=[Depends(roundtable(http_header="X-Session-ID"))])
async def api_data(): ...
```

## Configuration

### Environment Variables

Store your API key securely:

```bash
export ROUNDTABLE_API_KEY="your_secret_key"
```

Then initialize without explicit key:

```python
roundtable = Roundtable()  # Reads from environment
```

### Parameters

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `api_key` | `str \| None` | `None` | Roundtable API secret key. If not provided, reads from `ROUNDTABLE_API_KEY` environment variable. |
| `status_code` | `int` | `404` | HTTP status code to raise when validation fails. Using 404 makes bot detection less obvious. |
| `max_risk_score` | `int` | `50` | Maximum acceptable risk score (0-100). Sessions with higher scores are rejected. |

### Risk Score Guidelines

Risk scores range from 0 (definitely human) to 100 (definitely bot):

- **0-30**: Very likely human - safe to allow
- **30-50**: Probably human - acceptable for most use cases
- **50-70**: Uncertain - higher scrutiny recommended
- **70-100**: Very likely bot - should be blocked

**Recommended thresholds:**
- **Lenient** (max_risk_score=70): Allow most traffic, block obvious bots
- **Balanced** (max_risk_score=50): Default setting, good for most applications
- **Strict** (max_risk_score=30): High security, may have false positives

Adjust based on your needs. Start with 50 and tune based on your traffic patterns.

## Use Cases

### Contact Form Spam Prevention
```python
@app.post("/contact", dependencies=[Depends(roundtable(form_field="rt_session_id"))])
```
Block automated spam submissions while keeping forms simple for real users.

### Account Signup Protection
```python
@app.post("/signup", dependencies=[Depends(roundtable(form_field="rt_session_id"))])
```
Prevent bot-driven account creation and fake registrations.

### API Rate Limit Bypass Prevention
```python
@app.post("/api/resource", dependencies=[Depends(roundtable(http_header="X-Session-ID"))])
```
Stop bots from bypassing rate limits with multiple IPs or identities.

### Comment/Review Spam Blocking
```python
@app.post("/reviews", dependencies=[Depends(roundtable(form_field="rt_session_id"))])
```
Keep your user-generated content authentic and spam-free.

### Credential Stuffing Prevention
```python
@app.post("/login", dependencies=[Depends(roundtable(form_field="rt_session_id"))])
```
Protect login endpoints from automated credential testing attacks.

## API Reference

### `Roundtable`

A reusable session validator for FastAPI applications.

```python
class Roundtable:
    def __init__(
        self,
        *,
        api_key: str | None = None,
        status_code: int = 404,
        max_risk_score: int = 50
    ) -> None:
        """Initialize a session validator with Roundtable.ai API credentials."""
```

#### `__call__(*, form_field: str | None = None, http_header: str | None = None, body_field: str | None = None)`

Creates a FastAPI dependency for session validation. Exactly one parameter must be provided.

**Returns:** An async dependency function compatible with `Depends()`

**Example:**
```python
# Validate from form field
Depends(roundtable(form_field="rt_session_id"))

# Validate from HTTP header
Depends(roundtable(http_header="X-Session-ID"))

# Validate from request body field
Depends(roundtable(body_field="sessionId"))
```

#### `async validate_session(session_id: str) -> None`

Validates a session ID against the Roundtable.ai API. Raises `HTTPException` if validation fails.

For advanced usage and full API documentation, see the [source code](https://github.com/leandropls/fastapi-roundtable).

## Requirements

- Python 3.9 or higher
- fastapi
- aiohttp
- pydantic

## Links

- **GitHub Repository**: [github.com/leandropls/fastapi-roundtable](https://github.com/leandropls/fastapi-roundtable)
- **PyPI Package**: [pypi.org/project/fastapi-roundtable](https://pypi.org/project/fastapi-roundtable)
- **Roundtable Documentation**: [docs.roundtable.ai](https://docs.roundtable.ai)
- **Issue Tracker**: [GitHub Issues](https://github.com/leandropls/fastapi-roundtable/issues)
- **Roundtable Dashboard**: [accounts.roundtable.ai](https://accounts.roundtable.ai)

## Disclaimer

This library is maintained independently and is not an official Roundtable.ai product. While the
author is employed by Roundtable.ai, this project is a community contribution and not affiliated
with or endorsed by the company.

## License

MIT License - see LICENSE file for details.

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request or open an Issue on GitHub.

