{
  "openapi": "3.0.3",
  "info": {
    "title": "isBanned API",
    "version": "1.1.0",
    "description": "Check whether a Telegram channel, group, bot or user is banned, restricted, shadowbanned or pessimized in Telegram search.\n\nThere are two ways to call it:\n1. PUBLIC, NO KEY (recommended for AI agents / quick checks): GET or POST https://isbanned.app/check — free tier, ~5 checks per day per IP, fast check only. No registration, no auth.\n2. PERSONAL KEY (for higher limits, batch and deep checks): each user gets a personal endpoint https://isbanned.app/{key}-{slug} from the Telegram bot @IsBannedBot via its /api command, and passes that URL to their own agent/integration.",
    "contact": { "name": "IsBannedBot", "url": "https://t.me/IsBannedBot", "email": "info@isbanned.app" }
  },
  "servers": [ { "url": "https://isbanned.app" } ],
  "externalDocs": { "description": "Human-readable docs", "url": "https://isbanned.app/api" },
  "paths": {
    "/check": {
      "get": {
        "operationId": "publicCheck",
        "summary": "Public fast ban check (no key required)",
        "description": "Free public endpoint. No authentication. Fast check of a single Telegram link. Rate limited to ~5 requests per day per IP. For higher limits, batch or deep checks, use a personal key (see the /{key} path).",
        "parameters": [
          { "name": "url", "in": "query", "required": false, "schema": { "type": "string" },
            "description": "Telegram link to check.", "example": "https://t.me/durov" },
          { "name": "channel", "in": "query", "required": false, "schema": { "type": "string" },
            "description": "Alternative to url: a public channel/username (with or without @). Ignored if url is set.", "example": "durov" }
        ],
        "responses": {
          "200": { "description": "Check result, or an error (e.g. rate limit exceeded).",
            "content": { "application/json": { "schema": { "oneOf": [
              { "$ref": "#/components/schemas/CheckResult" },
              { "$ref": "#/components/schemas/ErrorResponse" }
            ] } } } }
        }
      },
      "post": {
        "operationId": "publicCheckPost",
        "summary": "Public fast ban check (no key required, JSON body)",
        "description": "Same as GET /check but with a JSON body. No authentication. ~5 requests per day per IP.",
        "requestBody": { "required": true,
          "content": { "application/json": { "schema": {
            "type": "object", "required": ["url"],
            "properties": { "url": { "type": "string", "example": "https://t.me/durov" } } } } } },
        "responses": {
          "200": { "description": "Check result.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CheckResult" } } } }
        }
      }
    },
    "/{key}": {
      "post": {
        "operationId": "checkTelegram",
        "summary": "Personal API — fast batch & async deep checks (key required)",
        "description": "For registered users who need more than the public free tier. Get your personal key from @IsBannedBot (/api command). Bare `{key}` = free public daily limit; full `{key}-{slug}` = paid programmatic access from your coin balance. Fast = synchronous batch (up to 20 links). Deep = asynchronous, exactly 1 link, result POSTed to your webhook.",
        "parameters": [
          { "name": "key", "in": "path", "required": true, "schema": { "type": "string" },
            "description": "Personal key from @IsBannedBot. `{key}` for the free public API or `{key}-{slug}` for the paid full API.",
            "example": "350609712304-bFuxacZ9" }
        ],
        "requestBody": {
          "required": true,
          "content": { "application/json": { "schema": { "oneOf": [
            { "$ref": "#/components/schemas/FastRequest" },
            { "$ref": "#/components/schemas/DeepRequest" }
          ] },
          "examples": {
            "fast": { "summary": "Fast check (batch)", "value": { "url": ["https://t.me/durov", "https://t.me/telegram"] } },
            "deep": { "summary": "Deep check (async)", "value": { "url": "https://t.me/durov", "check_type": "deep", "webhook": "https://your.app/cb" } }
          } } }
        },
        "responses": {
          "200": { "description": "Fast result array, or deep ACK.",
            "content": { "application/json": { "schema": { "oneOf": [
              { "type": "array", "items": { "$ref": "#/components/schemas/CheckResult" } },
              { "$ref": "#/components/schemas/DeepAck" },
              { "$ref": "#/components/schemas/ErrorResponse" }
            ] } } } }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "FastRequest": {
        "type": "object", "required": ["url"],
        "properties": {
          "url": { "oneOf": [ { "type": "string" }, { "type": "array", "items": { "type": "string" }, "maxItems": 20 } ],
            "description": "One t.me link (string) or up to 20 links (array)." },
          "currentLang": { "type": "string", "enum": ["ru", "en", "ua"], "default": "ru" }
        }
      },
      "DeepRequest": {
        "type": "object", "required": ["url", "check_type", "webhook"],
        "properties": {
          "url": { "type": "string", "description": "Exactly one t.me link.", "example": "https://t.me/durov" },
          "check_type": { "type": "string", "enum": ["deep"] },
          "webhook": { "type": "string", "format": "uri", "description": "Public https URL; the deep result is POSTed here. Private/internal hosts are rejected." }
        }
      },
      "CheckResult": {
        "type": "object",
        "properties": {
          "link": { "type": "string" },
          "status_id": { "$ref": "#/components/schemas/StatusCode" },
          "status_key": { "type": "string", "example": "ban_porn" },
          "status_label": { "type": "string", "description": "Human-readable status.", "example": "Porn ban" },
          "title": { "type": "string" },
          "ok": { "type": "boolean", "description": "true if no restriction (status 0)." },
          "banned": { "type": "boolean", "description": "true if a real ban/restriction (not status 0 or 2)." }
        }
      },
      "DeepAck": {
        "type": "object",
        "properties": {
          "status": { "type": "string", "example": "accepted" },
          "check_type": { "type": "string", "example": "deep" },
          "link": { "type": "string" },
          "cost": { "type": "number" },
          "balance_after": { "type": "number" },
          "note": { "type": "string" }
        }
      },
      "ErrorResponse": { "type": "object", "properties": { "error": { "type": "string" } } },
      "StatusCode": {
        "type": "integer",
        "description": "0 active/clean, 1 porn-ban (real Telegram restriction for 18+/porn content, hidden in official iOS/Android apps), 2 invalid link, 3 Sensitive/18+ (soft interface age-gate, not a ban), 4 iOS-only block, 5 Android-only block, 6 SCAM/FAKE, 7 ToS-ban, 8 copyright/DMCA, 9 restricted, 10 join-request required.",
        "enum": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
      }
    }
  }
}
