{
  "components": {
    "schemas": {
      "BatchRequest": {
        "properties": {
          "emails": {
            "example": [
              "user@example.com",
              "admin@test.org"
            ],
            "items": {
              "format": "email",
              "type": "string"
            },
            "maxItems": 20,
            "minItems": 1,
            "type": "array"
          },
          "force": {
            "default": false,
            "type": "boolean",
            "description": "Bypass the domain-level cache"
          },
          "mode": {
            "default": "full",
            "enum": [
              "quick",
              "full"
            ],
            "type": "string"
          },
          "pow": {
            "$ref": "#/components/schemas/PowSolution"
          },
          "quick": {
            "default": false,
            "type": "boolean"
          }
        },
        "required": [
          "emails"
        ],
        "type": "object"
      },
      "BatchResponse": {
        "properties": {
          "batch_ms": {
            "type": "integer"
          },
          "domains_queried": {
            "type": "integer"
          },
          "results": {
            "items": {
              "$ref": "#/components/schemas/VrfyResponse"
            },
            "type": "array"
          }
        },
        "type": "object"
      },
      "ErrorResponse": {
        "properties": {
          "challenge": {
            "type": "object"
          },
          "docs": {
            "type": "string"
          },
          "error": {
            "type": "string"
          },
          "message": {
            "type": "string"
          }
        },
        "type": "object"
      },
      "HeuristicResult": {
        "properties": {
          "domain_entropy": {
            "type": "number"
          },
          "entropy_suspicious": {
            "type": "boolean"
          },
          "is_subdomain": {
            "type": "boolean"
          },
          "mx_provider_class": {
            "enum": [
              "enterprise",
              "consumer",
              "self-hosted",
              "forwarding",
              "unknown"
            ],
            "type": "string"
          },
          "mx_security_gateway": {
            "type": [
              "string",
              "null"
            ]
          },
          "ns_provider": {
            "type": [
              "string",
              "null"
            ]
          },
          "parent_domain": {
            "type": [
              "string",
              "null"
            ]
          },
          "risky_tld": {
            "type": "boolean"
          },
          "spam_trap": {
            "type": "boolean"
          },
          "spam_trap_pattern": {
            "type": [
              "string",
              "null"
            ]
          },
          "subdomain_depth": {
            "type": "integer"
          },
          "tld": {
            "type": "string"
          }
        },
        "type": "object"
      },
      "MetaResult": {
        "properties": {
          "identity_breadth": {
            "type": "integer"
          },
          "links": {
            "properties": {
              "dns_details": {
                "type": "string"
              },
              "full_report": {
                "type": "string"
              },
              "tls_details": {
                "type": "string"
              }
            },
            "type": "object"
          },
          "pki_depth": {
            "type": "integer"
          },
          "query_ms": {
            "type": "integer"
          },
          "signals": {
            "type": "integer"
          },
          "signals_positive": {
            "type": "integer"
          },
          "version": {
            "type": "string"
          }
        },
        "type": "object"
      },
      "PowSolution": {
        "type": "object",
        "required": [
          "challenge",
          "nonce"
        ],
        "properties": {
          "challenge": {
            "type": "string",
            "pattern": "^[0-9a-f]{64}$",
            "description": "HMAC-SHA256(IP:bucket), hex, IP-bound, 5-min window"
          },
          "nonce": {
            "type": "string",
            "description": "Decimal string solving SHA-256(challenge:nonce) >= difficulty bits"
          }
        }
      },
      "ProviderInfo": {
        "properties": {
          "catch_all_default": {
            "type": "boolean"
          },
          "is_free": {
            "type": "boolean"
          },
          "name": {
            "type": "string"
          },
          "note": {
            "type": "string"
          },
          "smtp_verification": {
            "enum": [
              "reliable",
              "unreliable",
              "blocked",
              "unknown"
            ],
            "type": "string"
          }
        },
        "type": "object"
      },
      "SecurityResult": {
        "properties": {
          "bimi": {
            "type": "boolean"
          },
          "dane_tlsa": {
            "type": "boolean"
          },
          "dkim": {
            "type": "boolean"
          },
          "dkim_selectors": {
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "dmarc": {
            "properties": {
              "found": {
                "type": "boolean"
              },
              "policy": {
                "type": [
                  "string",
                  "null"
                ]
              }
            },
            "type": "object"
          },
          "dnssec": {
            "type": "boolean"
          },
          "domain_maturity": {
            "enum": [
              "mature",
              "basic",
              "minimal",
              "none"
            ],
            "type": "string"
          },
          "grade": {
            "type": "string"
          },
          "mta_sts": {
            "type": "boolean"
          },
          "spf": {
            "type": "boolean"
          },
          "tls_rpt": {
            "type": "boolean"
          }
        },
        "type": "object"
      },
      "ValidateRequest": {
        "properties": {
          "email": {
            "description": "Email address to validate",
            "example": "user@example.com",
            "format": "email",
            "type": "string"
          },
          "force": {
            "default": false,
            "description": "Bypass the domain-level cache",
            "type": "boolean"
          },
          "mode": {
            "default": "full",
            "description": "Alias for quick flag",
            "enum": [
              "quick",
              "full"
            ],
            "type": "string"
          },
          "pow": {
            "$ref": "#/components/schemas/PowSolution"
          },
          "quick": {
            "default": false,
            "description": "Tier 1 only — skip enrichment/security",
            "type": "boolean"
          },
          "stream": {
            "default": false,
            "description": "Stream progress via SSE",
            "type": "boolean"
          }
        },
        "required": [
          "email"
        ],
        "type": "object"
      },
      "ValidationResult": {
        "properties": {
          "catch_all_likely": {
            "type": "boolean"
          },
          "catch_all_reason": {
            "type": [
              "string",
              "null"
            ]
          },
          "disposable": {
            "type": "boolean"
          },
          "domain_type": {
            "enum": [
              "domain",
              "ip_literal",
              null
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "free_provider": {
            "type": "boolean"
          },
          "has_typo": {
            "type": "boolean"
          },
          "is_internationalized": {
            "type": "boolean"
          },
          "is_ip_literal": {
            "type": "boolean"
          },
          "is_punycode": {
            "type": "boolean"
          },
          "local_part_pattern": {
            "type": [
              "string",
              "null"
            ]
          },
          "local_part_random": {
            "type": "boolean"
          },
          "mx_found": {
            "type": "boolean"
          },
          "null_mx": {
            "type": "boolean"
          },
          "privacy_relay": {
            "type": "boolean"
          },
          "privacy_relay_service": {
            "type": [
              "string",
              "null"
            ]
          },
          "provider": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ProviderInfo"
              },
              {
                "type": "null"
              }
            ]
          },
          "role_account": {
            "type": "boolean"
          },
          "subaddress_base": {
            "type": [
              "string",
              "null"
            ]
          },
          "subaddress_tag": {
            "type": [
              "string",
              "null"
            ]
          },
          "subaddressed": {
            "type": "boolean"
          },
          "syntax_valid": {
            "type": "boolean"
          },
          "typo_suggestion": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "type": "object"
      },
      "VrfyResponse": {
        "properties": {
          "_meta": {
            "$ref": "#/components/schemas/MetaResult"
          },
          "action": {
            "description": "allow = safe to accept, verify = send confirmation, block = reject",
            "enum": [
              "allow",
              "verify",
              "block"
            ],
            "type": "string"
          },
          "confidence": {
            "enum": [
              "valid",
              "likely_valid",
              "risky",
              "invalid",
              "unknown"
            ],
            "type": "string"
          },
          "email": {
            "type": "string"
          },
          "heuristics": {
            "$ref": "#/components/schemas/HeuristicResult"
          },
          "security": {
            "$ref": "#/components/schemas/SecurityResult"
          },
          "validation": {
            "$ref": "#/components/schemas/ValidationResult"
          }
        },
        "required": [
          "email",
          "action",
          "confidence",
          "validation",
          "_meta"
        ],
        "type": "object"
      }
    },
    "securitySchemes": {
      "basicAuth": {
        "scheme": "basic",
        "type": "http"
      }
    }
  },
  "info": {
    "contact": {
      "email": "hello@yoke.lol",
      "name": "yoke.lol",
      "url": "https://yoke.lol"
    },
    "description": "Free email verification API — syntax, DNS/MX, disposable detection, provider identification, typo correction, security posture, heuristics. No SMTP probes. POST-only, no emails in URLs. Proof-of-work instead of API keys. Open source: https://github.com/yokedotlol/vrfy-lol",
    "license": {
      "name": "MIT",
      "url": "https://opensource.org/licenses/MIT"
    },
    "title": "vrfy.lol",
    "version": "1.0.0"
  },
  "openapi": "3.1.0",
  "paths": {
    "/": {
      "get": {
        "description": "GET / returns JSON metadata for API clients (curl without Accept: text/html) or HTML SPA landing page when Accept: text/html is present.",
        "operationId": "getRoot",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "description": {
                      "type": "string"
                    },
                    "endpoints": {
                      "type": "object"
                    },
                    "name": {
                      "type": "string"
                    },
                    "rate_limit": {
                      "type": "object"
                    },
                    "version": {
                      "type": "string"
                    }
                  },
                  "type": "object"
                }
              },
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "description": "JSON metadata or HTML page"
          }
        },
        "summary": "API root / landing page",
        "tags": [
          "docs"
        ]
      },
      "post": {
        "description": "POST-only email validation. No emails in URLs, server logs, or CDN analytics. Returns action (allow/verify/block) + confidence + detailed signals.",
        "operationId": "validateEmail",
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "force": {
                  "summary": "Bypass the domain-level cache",
                  "value": {
                    "email": "user@example.com",
                    "force": true
                  }
                },
                "pow": {
                  "summary": "With proof-of-work",
                  "value": {
                    "email": "user@example.com",
                    "pow": {
                      "challenge": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
                      "nonce": "12345"
                    }
                  }
                },
                "quick": {
                  "summary": "Quick mode (Tier 1 only)",
                  "value": {
                    "email": "user@example.com",
                    "quick": true
                  }
                },
                "simple": {
                  "summary": "Simple validation",
                  "value": {
                    "email": "user@example.com"
                  }
                }
              },
              "schema": {
                "$ref": "#/components/schemas/ValidateRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VrfyResponse"
                }
              }
            },
            "description": "Validation result",
            "headers": {
              "X-RateLimit-Remaining-Daily": {
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Remaining-Hourly": {
                "schema": {
                  "type": "string"
                }
              },
              "X-Vrfy-Version": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Missing or invalid email"
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Rate limited — PoW challenge issued"
          }
        },
        "summary": "Validate a single email",
        "tags": [
          "validate"
        ]
      }
    },
    "/.well-known/ai-catalog.json": {
      "get": {
        "description": "Ora.ai / AI Ready discovery catalog. Points to OpenAPI spec.",
        "operationId": "getAiCatalog",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "entries": {
                      "type": "array"
                    },
                    "host": {
                      "type": "object"
                    },
                    "specVersion": {
                      "type": "string"
                    }
                  },
                  "type": "object"
                }
              }
            },
            "description": "AI catalog JSON"
          }
        },
        "summary": "AI catalog (AI Ready)",
        "tags": [
          "well-known"
        ]
      }
    },
    "/.well-known/security.txt": {
      "get": {
        "operationId": "getSecurityTxt",
        "responses": {
          "200": {
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "description": "security.txt"
          }
        },
        "summary": "security.txt",
        "tags": [
          "well-known"
        ]
      }
    },
    "/about": {
      "get": {
        "operationId": "getAbout",
        "responses": {
          "200": {
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "description": "HTML page"
          }
        },
        "summary": "About page",
        "tags": [
          "docs"
        ]
      }
    },
    "/api/docs": {
      "get": {
        "operationId": "getApiDocs",
        "responses": {
          "200": {
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "description": "HTML docs page"
          }
        },
        "summary": "API documentation",
        "tags": [
          "docs"
        ]
      }
    },
    "/api/openapi.json": {
      "get": {
        "description": "Alias for /openapi.json",
        "operationId": "getOpenApiAlias",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            },
            "description": "OpenAPI spec"
          }
        },
        "summary": "OpenAPI specification (alias)",
        "tags": [
          "docs"
        ]
      }
    },
    "/api/usage": {
      "get": {
        "description": "Requires HTTP Basic Auth (admin:ADMIN_KEY). Returns XON signal counters and rate limit state.",
        "operationId": "getUsageApi",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            },
            "description": "Usage stats"
          },
          "401": {
            "description": "Unauthorized"
          }
        },
        "security": [
          {
            "basicAuth": []
          }
        ],
        "summary": "Admin usage stats",
        "tags": [
          "system"
        ]
      }
    },
    "/batch": {
      "post": {
        "operationId": "validateBatch",
        "requestBody": {
          "content": {
            "application/json": {
              "examples": {
                "batch": {
                  "value": {
                    "emails": [
                      "user@example.com",
                      "admin@test.org"
                    ]
                  }
                }
              },
              "schema": {
                "$ref": "#/components/schemas/BatchRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BatchResponse"
                }
              }
            },
            "description": "Batch results"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Invalid batch"
          }
        },
        "summary": "Batch validate up to 20 emails",
        "tags": [
          "validate"
        ]
      }
    },
    "/cli": {
      "get": {
        "operationId": "getCli",
        "responses": {
          "200": {
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "description": "HTML page"
          }
        },
        "summary": "CLI documentation",
        "tags": [
          "docs"
        ]
      }
    },
    "/favicon.svg": {
      "get": {
        "responses": {
          "200": {
            "content": {
              "image/svg+xml": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "description": "SVG"
          }
        },
        "summary": "Favicon SVG",
        "tags": [
          "docs"
        ]
      }
    },
    "/health": {
      "get": {
        "operationId": "health",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "service": {
                      "example": "vrfy.lol",
                      "type": "string"
                    },
                    "status": {
                      "example": "ok",
                      "type": "string"
                    },
                    "version": {
                      "example": "1.0.0",
                      "type": "string"
                    }
                  },
                  "type": "object"
                }
              }
            },
            "description": "Service healthy"
          }
        },
        "summary": "Health check",
        "tags": [
          "system"
        ]
      }
    },
    "/manifest.json": {
      "get": {
        "responses": {
          "200": {
            "description": "manifest.json"
          }
        },
        "summary": "PWA manifest",
        "tags": [
          "docs"
        ]
      }
    },
    "/openapi.json": {
      "get": {
        "description": "Returns the OpenAPI 3.1 spec for this API. CORS enabled, cached 1h.",
        "operationId": "getOpenApi",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            },
            "description": "OpenAPI spec"
          }
        },
        "summary": "OpenAPI specification",
        "tags": [
          "docs"
        ]
      }
    },
    "/pow": {
      "get": {
        "operationId": "getPow",
        "responses": {
          "200": {
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "description": "HTML page"
          }
        },
        "summary": "Proof-of-work protocol",
        "tags": [
          "docs"
        ]
      }
    },
    "/privacy": {
      "get": {
        "operationId": "getPrivacy",
        "responses": {
          "200": {
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "description": "HTML page"
          }
        },
        "summary": "Privacy policy",
        "tags": [
          "docs"
        ]
      }
    },
    "/robots.txt": {
      "get": {
        "operationId": "getRobots",
        "responses": {
          "200": {
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "description": "robots.txt"
          }
        },
        "summary": "robots.txt",
        "tags": [
          "docs"
        ]
      }
    },
    "/sitemap.xml": {
      "get": {
        "operationId": "getSitemap",
        "responses": {
          "200": {
            "content": {
              "application/xml": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "description": "sitemap.xml"
          }
        },
        "summary": "sitemap.xml",
        "tags": [
          "docs"
        ]
      }
    },
    "/status": {
      "get": {
        "operationId": "getStatus",
        "responses": {
          "200": {
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "description": "HTML status page"
          }
        },
        "summary": "Service status",
        "tags": [
          "system"
        ]
      }
    },
    "/terms": {
      "get": {
        "operationId": "getTerms",
        "responses": {
          "200": {
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "description": "HTML page"
          }
        },
        "summary": "Terms of Use",
        "tags": [
          "docs"
        ]
      }
    },
    "/usage": {
      "get": {
        "description": "Requires Basic Auth when ADMIN_KEY is set.",
        "operationId": "getUsage",
        "responses": {
          "200": {
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "description": "HTML page"
          },
          "401": {
            "description": "Unauthorized"
          }
        },
        "summary": "Usage dashboard (admin SPA)",
        "tags": [
          "docs"
        ]
      }
    }
  },
  "servers": [
    {
      "description": "Production",
      "url": "https://vrfy.lol"
    }
  ],
  "tags": [
    {
      "description": "Email validation",
      "name": "validate"
    },
    {
      "description": "System & health",
      "name": "system"
    },
    {
      "description": "Documentation & static",
      "name": "docs"
    },
    {
      "description": ".well-known discovery",
      "name": "well-known"
    }
  ]
}