# ban.wtf APIs — Full Reference & Machine-Readable Context > Comprehensive, un-truncated API documentation and schemas for LLMs, autonomous agents, and developers. - Base URL: https://apis.ban.wtf - Current Text Moderation Cost: 0.5 credit(s) per message - Current Image Moderation Cost: 1 credit(s) per image - Authentication: Bearer token or `x-api-key` header with prefix `bw_live_` - OpenAPI Specification: https://apis.ban.wtf/openapi.json - Short LLM Summary: https://apis.ban.wtf/llms.txt --- ## 1. Authentication & Security Every request to moderation endpoints must include a valid secret API key. Keys are generated in the ban.wtf Developer Dashboard and always begin with `bw_live_`. ### Supported Headers: 1. Standard Bearer Authorization: `Authorization: Bearer bw_live_0123456789abcdef...` 2. Custom Header: `x-api-key: bw_live_0123456789abcdef...` 3. Fallback Header: `api-key: bw_live_0123456789abcdef...` --- ## 2. Credit System & Billing - **Charge-and-Use**: Accounts hold a balance of credits deducted on successful moderation. - **Failed Requests**: If an upstream error occurs (HTTP 500), credits are **not** deducted. - **Insufficient Credits**: If balance < required cost, HTTP 402 is returned with code `INSUFFICIENT_CREDITS`. --- ## 3. Endpoints Reference ### 3.1 Text Moderation (`POST /api/v1/moderate/text`) Evaluates a single message for zero-day raids, phishing, scam links, toxicity, and action candidate probabilities. #### Request Headers: - `Authorization: Bearer bw_live_...` - `Content-Type: application/json` #### Request Body (JSON): | Field | Type | Required | Default | Description | |---|---|---|---|---| | `content` | string | Yes | — | The message text to analyze. | | `author` | string | No | `"user#0001"` | Username, discriminator, or Discord snowflake ID. | | `channel` | string | No | `"#general"` | Channel name or Discord snowflake ID. | | `account_age_days` | integer | No | `30` | Author account age in days (used for raid detection). | | `mentions_count` | integer | No | `0` | Count of mentions in message (mass ping detection). | | `has_attachments` | boolean | No | `false` | Whether message has attached files/media. | | `mode` | string | No | `"hybrid"` | `"hybrid"` (AI guardrails + diffusion) or `"native"`. | #### Sample Request: ```bash curl -X POST "https://apis.ban.wtf/api/v1/moderate/text" \ -H "Authorization: Bearer bw_live_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "content": "FREE DISCORD NITRO: Claim 3 months at https://discrod-nitro.ru/claim @everyone", "author": "spambot#1337", "channel": "#general", "account_age_days": 1, "mentions_count": 1, "has_attachments": false, "mode": "hybrid" }' ``` #### Sample Response (HTTP 200 OK): ```json { "id": "mod_7f2b90d1ec4a3901", "action": "ban", "threat_score": 2.4512, "is_phishing_or_scam": 0.9821, "requires_mod_review": 0.9145, "action_probabilities": { "ban": 0.9612, "timeout": 0.0245, "warn": 0.0101, "none": 0.0042 }, "routing_model": "diffusion_router", "latency_ms": 14.82, "mode": "hybrid", "credits_deducted": 1.0, "remaining_credits": 149.0 } ``` --- ### 3.2 Batch Text Moderation (`POST /api/v1/moderate/text/batch`) Evaluates up to 50 messages in parallel. Deducts `0.5 * count` credits atomically. #### Request Body (JSON): ```json { "messages": [ { "content": "Hello world! Have a great day.", "author": "friendly_coder#0001" }, { "content": "Claim gift cards at https://scam-site.ru", "author": "bad_actor#9999" } ], "mode": "hybrid" } ``` #### Sample Response (HTTP 200 OK): ```json { "batch_size": 2, "total_latency_ms": 38.45, "results": [ { "content": "Hello world! Have a great day.", "action": "none", "threat_score": 0.0812, "is_phishing_or_scam": 0.0120, "requires_mod_review": 0.0054, "action_probabilities": { "ban": 0.0011, "timeout": 0.0022, "warn": 0.0085, "none": 0.9882 } }, { "content": "Claim gift cards at https://scam-site.ru", "action": "ban", "threat_score": 2.6105, "is_phishing_or_scam": 0.9789, "requires_mod_review": 0.9412, "action_probabilities": { "ban": 0.9810, "timeout": 0.0125, "warn": 0.0041, "none": 0.0024 } } ], "credits_deducted": 2.0, "remaining_credits": 147.0 } ``` --- ### 3.3 Image Moderation (`POST /api/v1/moderate/image`) Classifies images for explicit nudity, anime/drawn nudity, and estimates facial age. #### Input Options: 1. **JSON with Image URL**: `{"image_url": "https://example.com/photo.jpg"}` 2. **JSON with Base64**: `{"image_base64": "data:image/jpeg;base64,..."}` 3. **Multipart Form Upload**: `image=@photo.jpg` (Content-Type: multipart/form-data) #### Sample Response (HTTP 200 OK): ```json { "status": "success", "request_id": "req_img_1726918293", "credits_deducted": 5.0, "remaining_credits": 140.0, "data": { "is_flagged": false, "summary": "Image passed safety filters.", "categories": { "nudity": { "score": 0.0051, "flagged": false, "labels": ["safe_neutral"] }, "drawn_nudity": { "score": 0.0019, "flagged": false, "labels": ["none"] }, "age_estimation": { "estimated_age": 34, "age_range": "29 to 39", "is_minor": false, "confidence": 0.75, "face_detected": true } }, "classifications": [ { "className": "Neutral", "probability": 0.9844 }, { "className": "Drawing", "probability": 0.0086 }, { "className": "Porn", "probability": 0.0040 }, { "className": "Hentai", "probability": 0.0019 }, { "className": "Sexy", "probability": 0.0011 } ], "meta": { "source": "photo.jpg", "latency_ms": 112, "processed_at": "2026-09-21T15:00:00.000Z", "model_backend": "tensorflow_nsfwjs_age_v1" } } } ``` --- ### 3.4 Public Pricing (`GET /api/pricing`) Returns active per-request credit rates. No authentication required. #### Sample Response (HTTP 200 OK): ```json { "success": true, "pricing": { "imageCreditCost": 1, "textCreditCost": 0.5 } } ``` --- ### 3.5 System Health (`GET /api/v1/moderate/health`) Returns gateway status and upstream microservice connectivity. No authentication required. #### Sample Response (HTTP 200 OK): ```json { "gateway_status": "healthy", "service": "banwtf-gateway-v1", "timestamp": "2026-09-22T13:00:00.000Z", "services": { "text_moderation": { "healthy": true }, "image_moderation": { "healthy": true } } } ``` --- ## 4. HTTP Status Codes & Error Handling - **200 OK**: Request authenticated, processed, and credits deducted. - **400 Bad Request**: Malformed JSON or unparseable payload. - **401 Unauthorized**: Missing or invalid API key. Ensure `Authorization: Bearer bw_live_...` is set. - **402 Payment Required**: Insufficient credit balance. Top up credits in billing. - **422 Unprocessable Entity**: Missing required fields (`content` or `messages`), or batch exceeds 50 items. - **500 Internal Server Error**: Router processing or upstream failure. Credits are **not** deducted. --- ## 5. Client Code Examples ### Python (requests) ```python import requests API_KEY = "bw_live_YOUR_KEY" BASE_URL = "https://apis.ban.wtf" response = requests.post( f"{BASE_URL}/api/v1/moderate/text", headers={ "Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json", }, json={ "content": "Join our server for free nitro: https://discord-nitro.ru @everyone", "author": "spammer#0001", } ) data = response.json() print("Action:", data.get("action")) print("Threat score:", data.get("threat_score")) ``` ### TypeScript / Node.js (fetch) ```typescript const response = await fetch("https://apis.ban.wtf/api/v1/moderate/text", { method: "POST", headers: { "Authorization": "Bearer bw_live_YOUR_KEY", "Content-Type": "application/json", }, body: JSON.stringify({ content: "Suspicious message link: https://scam-site.ru", author: "user#1234", }), }); const result = await response.json(); console.log("Moderation decision:", result.action); ```