{
  "openapi": "3.1.0",
  "info": {
    "title": "LeakCheck API",
    "version": "2.0.0",
    "summary": "Data breach search — check whether credentials appear in known leaks.",
    "description": "LeakCheck exposes two HTTP APIs on the same origin:\n\n- **Pro API v2** — authenticated, returns full breach records (email, username, phone, domain, hash and more).\n- **Public API** — free and unauthenticated, returns only *which* breaches an identifier appears in and *which categories* of data were exposed, never the values themselves.\n\nHuman-readable guides: https://docs.leakcheck.io",
    "termsOfService": "https://leakcheck.io/tos",
    "contact": {
      "name": "LeakCheck",
      "url": "https://leakcheck.io/contact",
      "email": "the@leakcheck.net"
    }
  },
  "externalDocs": {
    "description": "Full documentation",
    "url": "https://docs.leakcheck.io/overview"
  },
  "servers": [
    { "url": "https://leakcheck.io", "description": "Production" }
  ],
  "security": [
    { "ApiKeyHeader": [] },
    { "ApiKeyQuery": [] }
  ],
  "tags": [
    { "name": "Pro API v2", "description": "Authenticated lookup returning full breach records." },
    { "name": "Public API", "description": "Free, unauthenticated breach-source lookup." }
  ],
  "paths": {
    "/api/v2/query/{query}": {
      "get": {
        "operationId": "proLookup",
        "summary": "Pro lookup",
        "description": "Search full breach records by email, username, phone number, domain, hash and more. Requires an [API key](https://docs.leakcheck.io/authentication) passed either in the `X-API-Key` header (recommended) or as the `?key=` query parameter.",
        "tags": ["Pro API v2"],
        "security": [
          { "ApiKeyHeader": [] },
          { "ApiKeyQuery": [] }
        ],
        "parameters": [
          {
            "name": "query",
            "in": "path",
            "required": true,
            "description": "Value to search for — an email address, username, phone number, hash, domain, etc. Minimum 3 characters.",
            "schema": { "type": "string", "minLength": 3 },
            "example": "example@example.com"
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "description": "Search type. Omit to auto-detect (works for email, username, phone and hash). `domain`, `keyword`, `origin`, `password` and `phash` must be set explicitly; `origin`, `password` and `phash` are Enterprise-only.",
            "schema": {
              "type": "string",
              "enum": ["auto", "email", "domain", "keyword", "username", "phone", "hash", "phash", "origin", "password"]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum number of rows to return.",
            "schema": { "type": "integer", "default": 100, "minimum": 1, "maximum": 1000 }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Number of rows to skip, for pagination.",
            "schema": { "type": "integer", "default": 0, "minimum": 0, "maximum": 2500 }
          }
        ],
        "responses": {
          "200": {
            "description": "Search completed. `found` is 0 with an empty `result` when nothing matched.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ProLookupResponse" },
                "examples": {
                  "found": {
                    "summary": "Record found",
                    "value": {
                      "success": true,
                      "found": 1,
                      "quota": 400,
                      "result": [
                        {
                          "email": "example@example.com",
                          "source": {
                            "name": "BreachedWebsite.net",
                            "breach_date": "2019-07",
                            "unverified": 0,
                            "passwordless": 0,
                            "compilation": 0
                          },
                          "first_name": "Example",
                          "last_name": "Example",
                          "username": "leakcheck",
                          "fields": ["first_name", "last_name", "username"]
                        }
                      ]
                    }
                  },
                  "empty": {
                    "summary": "Nothing found",
                    "value": { "success": true, "found": 0, "quota": 400, "result": [] }
                  }
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "422": { "$ref": "#/components/responses/UnprocessableType" },
          "429": { "$ref": "#/components/responses/TooManyRequests" }
        }
      }
    },
    "/api/public": {
      "get": {
        "operationId": "publicLookup",
        "summary": "Public lookup",
        "description": "Free, unauthenticated lookup. Returns which breaches an identifier appears in and which data categories were exposed — never the values themselves. Use the Pro API for full records. Rate limited to 1 request per second.",
        "tags": ["Public API"],
        "security": [],
        "parameters": [
          {
            "name": "check",
            "in": "query",
            "required": true,
            "description": "An email address, a SHA-256 email hash (optionally truncated to 24 characters), or a username (min. 3 characters). The type is auto-detected.",
            "schema": { "type": "string", "minLength": 3 },
            "example": "example@example.com"
          }
        ],
        "responses": {
          "200": {
            "description": "Search completed.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/PublicLookupResponse" },
                "examples": {
                  "found": {
                    "summary": "Sources found",
                    "value": {
                      "success": true,
                      "found": 3,
                      "fields": ["username", "first_name", "address"],
                      "sources": [
                        { "name": "Evony.com", "date": "2016-07" },
                        { "name": "I-Dressup.com", "date": "2016-08" },
                        { "name": "Zynga.com", "date": "2019-09" }
                      ]
                    }
                  }
                }
              }
            }
          },
          "429": { "$ref": "#/components/responses/TooManyRequests" }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKeyHeader": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-Key",
        "description": "API key in the X-API-Key header (recommended). Keys are at least 40 characters long."
      },
      "ApiKeyQuery": {
        "type": "apiKey",
        "in": "query",
        "name": "key",
        "description": "API key as the ?key= query parameter. Prefer the header — query strings leak into logs, proxies and history."
      }
    },
    "schemas": {
      "ProLookupResponse": {
        "type": "object",
        "required": ["success", "found", "result"],
        "properties": {
          "success": { "type": "boolean" },
          "found": { "type": "integer", "description": "Number of rows found and returned." },
          "quota": { "type": "integer", "description": "Number of queries remaining on the account." },
          "result": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/ProResultRow" }
          }
        }
      },
      "ProResultRow": {
        "type": "object",
        "description": "A single breach record. The set of populated fields varies by source; the `fields` array names the data present in this row. The property list below is representative, not exhaustive.",
        "additionalProperties": true,
        "properties": {
          "source": { "$ref": "#/components/schemas/Source" },
          "fields": {
            "type": "array",
            "items": { "type": "string" },
            "description": "Names of the data fields present in this row."
          },
          "collected": {
            "type": "string",
            "description": "Info-stealer log records only: when the record was collected, derived from its ObjectId. Either an exact YYYY-MM-DD, or the upper-bound label \"April 2024 or earlier\" for older bulk-imported records. Absent for regular breaches — use source.breach_date there.",
            "examples": ["2024-11-03", "April 2024 or earlier"]
          },
          "email": { "type": "string" },
          "username": { "type": "string" },
          "password": { "type": "string" },
          "first_name": { "type": "string" },
          "last_name": { "type": "string" },
          "name": { "type": "string" },
          "dob": { "type": "string" },
          "address": { "type": "string" },
          "zip": { "type": "string" },
          "phone": { "type": "string" }
        }
      },
      "Source": {
        "type": "object",
        "description": "The breach a row came from.",
        "properties": {
          "name": { "type": "string" },
          "breach_date": { "type": "string", "description": "Month of the breach, YYYY-MM, when known.", "examples": ["2019-07"] },
          "unverified": { "type": "integer", "enum": [0, 1], "description": "1 if the origin of the leak is not fully verified." },
          "passwordless": { "type": "integer", "enum": [0, 1], "description": "1 if the records contain no passwords." },
          "compilation": { "type": "integer", "enum": [0, 1], "description": "1 if the source is a compilation of multiple leaks." }
        }
      },
      "PublicLookupResponse": {
        "type": "object",
        "required": ["success", "found"],
        "properties": {
          "success": { "type": "boolean" },
          "found": { "type": "integer", "description": "Number of breach records that match the query." },
          "fields": {
            "type": "array",
            "items": { "type": "string" },
            "description": "Categories of data exposed across the matching breaches. The values themselves are never returned."
          },
          "sources": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/PublicSource" }
          }
        }
      },
      "PublicSource": {
        "type": "object",
        "properties": {
          "name": { "type": "string" },
          "date": { "type": "string", "description": "Month of the breach, YYYY-MM.", "examples": ["2016-07"] }
        }
      },
      "Error": {
        "type": "object",
        "required": ["success"],
        "additionalProperties": true,
        "properties": {
          "success": { "type": "boolean", "const": false },
          "error": { "type": "string", "description": "Human-readable description of the failure." }
        }
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Invalid request — e.g. invalid API key, invalid `type`, invalid email/query/domain, query shorter than 3 characters, or disallowed characters.",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
      },
      "Unauthorized": {
        "description": "Missing X-API-Key header.",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
      },
      "Forbidden": {
        "description": "An active plan is required, or the plan's usage quota/limit has been reached.",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
      },
      "UnprocessableType": {
        "description": "The search type could not be determined automatically — pass an explicit `type` parameter.",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
      },
      "TooManyRequests": {
        "description": "Rate limit exceeded. Pro API v2: 3 requests/second (adjustable in settings). Public API: 1 request/second. Back off and retry.",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
      }
    }
  }
}
