{
  "components": {
    "schemas": {
      "ChainCert": {
        "properties": {
          "is_self_signed": {
            "type": "boolean"
          },
          "issuer": {
            "type": "string"
          },
          "key_alg": {
            "type": "string"
          },
          "key_size": {
            "type": "integer"
          },
          "sans": {
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "serial": {
            "type": "string"
          },
          "signature_alg": {
            "type": "string"
          },
          "subject": {
            "type": "string"
          },
          "valid_from": {
            "format": "date-time",
            "type": "string"
          },
          "valid_to": {
            "format": "date-time",
            "type": "string"
          }
        },
        "type": "object"
      },
      "ComplianceResult": {
        "properties": {
          "display_name": {
            "example": "PCI DSS 4.0",
            "type": "string"
          },
          "findings": {
            "items": {
              "properties": {
                "detail": {
                  "type": "string"
                },
                "requirement": {
                  "type": "string"
                },
                "status": {
                  "enum": [
                    "pass",
                    "fail",
                    "warn",
                    "info"
                  ],
                  "type": "string"
                }
              },
              "type": "object"
            },
            "type": "array"
          },
          "framework": {
            "enum": [
              "pci-dss-4",
              "nist-800-52r2",
              "hipaa"
            ],
            "example": "pci-dss-4",
            "type": "string"
          },
          "meets_requirements": {
            "type": "boolean"
          }
        },
        "type": "object"
      },
      "DANCEInfo": {
        "properties": {
          "checks": {
            "properties": {
              "dane_ee": {
                "type": "boolean"
              },
              "dane_ta": {
                "type": "boolean"
              },
              "dane_tlsa": {
                "type": "boolean"
              },
              "dnssec": {
                "type": "boolean"
              },
              "smtp_tlsa": {
                "type": "boolean"
              },
              "tls13": {
                "type": "boolean"
              }
            },
            "type": "object"
          },
          "detail": {
            "type": "string"
          },
          "status": {
            "enum": [
              "ready",
              "partial",
              "not-ready"
            ],
            "type": "string"
          },
          "tlsa_usage": {
            "items": {
              "type": "object"
            },
            "type": "array"
          }
        },
        "type": "object"
      },
      "DNSSecurityInfo": {
        "properties": {
          "caa": {
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "dane_tlsa": {
            "description": "Raw TLSA or null",
            "type": [
              "string",
              "null"
            ]
          },
          "dnssec": {
            "type": "boolean"
          },
          "parsed_tlsa": {
            "items": {
              "properties": {
                "data": {
                  "type": "string"
                },
                "matching_type": {
                  "type": "integer"
                },
                "selector": {
                  "type": "integer"
                },
                "usage": {
                  "type": "integer"
                }
              },
              "type": "object"
            },
            "type": "array"
          },
          "smtp_tlsa": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "type": "object"
      },
      "Error": {
        "properties": {
          "detail": {
            "type": "string"
          },
          "error": {
            "type": "string"
          }
        },
        "type": "object"
      },
      "HSTSInfo": {
        "properties": {
          "enabled": {
            "type": "boolean"
          },
          "include_subdomains": {
            "type": "boolean"
          },
          "max_age": {
            "type": [
              "integer",
              "null"
            ]
          },
          "on_preload_list": {
            "type": "boolean"
          },
          "preload": {
            "type": "boolean"
          }
        },
        "type": "object"
      },
      "HTTP3Info": {
        "properties": {
          "alt_svc": {
            "type": [
              "string",
              "null"
            ]
          },
          "http2": {
            "type": "boolean"
          },
          "supported": {
            "type": "boolean"
          }
        },
        "type": "object"
      },
      "ScanResult": {
        "properties": {
          "_meta": {
            "properties": {
              "cache_hit": {
                "type": "boolean"
              },
              "cache_ttl": {
                "example": 21600,
                "type": "integer"
              },
              "dns_report": {
                "format": "uri",
                "type": "string"
              },
              "docs": {
                "format": "uri",
                "type": "string"
              },
              "full_report": {
                "format": "uri",
                "type": "string"
              },
              "http_report": {
                "format": "uri",
                "type": "string"
              },
              "version": {
                "type": "string"
              }
            },
            "type": "object"
          },
          "chain_certs": {
            "items": {
              "$ref": "#/components/schemas/ChainCert"
            },
            "type": "array"
          },
          "chain_depth": {
            "type": "integer"
          },
          "chain_valid": {
            "type": "boolean"
          },
          "cipher_summary": {
            "properties": {
              "acceptable": {
                "type": "integer"
              },
              "insecure": {
                "type": "integer"
              },
              "strong": {
                "type": "integer"
              },
              "weak": {
                "type": "integer"
              }
            },
            "type": "object"
          },
          "ciphers": {
            "items": {
              "properties": {
                "id": {
                  "type": "integer"
                },
                "name": {
                  "type": "string"
                },
                "strength": {
                  "enum": [
                    "strong",
                    "acceptable",
                    "weak",
                    "insecure"
                  ],
                  "type": "string"
                }
              },
              "type": "object"
            },
            "type": "array"
          },
          "compliance": {
            "items": {
              "$ref": "#/components/schemas/ComplianceResult"
            },
            "type": "array"
          },
          "crl_endpoints": {
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "dance": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/DANCEInfo"
              },
              {
                "type": "null"
              }
            ]
          },
          "days_remaining": {
            "example": 72,
            "type": "integer"
          },
          "dns_security": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/DNSSecurityInfo"
              },
              {
                "type": "null"
              }
            ]
          },
          "ext_key_usage": {
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "fingerprint": {
            "type": "string"
          },
          "forward_secrecy": {
            "type": "boolean"
          },
          "grade": {
            "description": "A+ to F, like SSL Labs",
            "example": "A+",
            "type": "string"
          },
          "has_scts": {
            "type": "boolean"
          },
          "hsts": {
            "$ref": "#/components/schemas/HSTSInfo"
          },
          "http3": {
            "$ref": "#/components/schemas/HTTP3Info"
          },
          "ip_addresses": {
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "is_ca": {
            "type": "boolean"
          },
          "is_ip": {
            "type": "boolean"
          },
          "issuer": {
            "type": "string"
          },
          "issuing_cert_url": {
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "key_alg": {
            "example": "ECDSA",
            "type": "string"
          },
          "key_exchange": {
            "type": "string"
          },
          "key_size": {
            "example": 256,
            "type": "integer"
          },
          "key_usage": {
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "ocsp_must_staple": {
            "type": "boolean"
          },
          "ocsp_servers": {
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "ocsp_stapling": {
            "type": "boolean"
          },
          "policy_oids": {
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "probe_ms": {
            "example": 142,
            "type": "integer"
          },
          "protocols": {
            "example": [
              "TLS 1.3",
              "TLS 1.2"
            ],
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "sans": {
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "scanned_at": {
            "format": "date-time",
            "type": "string"
          },
          "sct_count": {
            "type": "integer"
          },
          "serial": {
            "type": "string"
          },
          "signature_alg": {
            "type": "string"
          },
          "starttls": {
            "type": "boolean"
          },
          "starttls_proto": {
            "enum": [
              "",
              "smtp",
              "imap",
              "pop3"
            ],
            "type": "string"
          },
          "subject": {
            "type": "string"
          },
          "target": {
            "example": "stripe.com",
            "type": "string"
          },
          "valid_from": {
            "format": "date-time",
            "type": "string"
          },
          "valid_to": {
            "format": "date-time",
            "type": "string"
          }
        },
        "required": [
          "grade",
          "target",
          "issuer",
          "protocols",
          "chain_valid"
        ],
        "type": "object"
      }
    }
  },
  "externalDocs": {
    "description": "CLI and human docs",
    "url": "https://certs.lol/api/docs"
  },
  "info": {
    "contact": {
      "email": "hello@yoke.lol",
      "name": "certs.lol",
      "url": "https://certs.lol"
    },
    "description": "Fast, API-first TLS certificate checker — grade, issuer, chain, protocols, ciphers, HSTS, CT, DNSSEC, DANE, DANCE, compliance (PCI/NIST/HIPAA). Free, no auth, 60 req/hr, 6h cache. Content-negotiated: curl/Accept: application/json → JSON, browsers → HTML report. CLI: brew install yokedotlol/tap/certs. Part of .lol family (yoke.lol, ns.lol, xhttp.lol, vrfy.lol).",
    "license": {
      "name": "MIT",
      "url": "https://github.com/yokedotlol/certs-lol/blob/main/LICENSE"
    },
    "title": "certs.lol",
    "version": "2.0.0"
  },
  "openapi": "3.1.0",
  "paths": {
    "/": {
      "get": {
        "description": "GET / with JSON Accept returns service info. Browser Accept returns HTML homepage. Same pattern as /{domain} content negotiation.",
        "operationId": "getRoot",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "docs": {
                      "format": "uri",
                      "type": "string"
                    },
                    "family": {
                      "type": "object"
                    },
                    "name": {
                      "example": "certs.lol",
                      "type": "string"
                    },
                    "tagline": {
                      "type": "string"
                    },
                    "usage": {
                      "example": "curl -s https://certs.lol/stripe.com | jq",
                      "type": "string"
                    },
                    "version": {
                      "type": "string"
                    }
                  },
                  "type": "object"
                }
              },
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "description": "Service info (JSON) or HTML homepage"
          }
        },
        "summary": "Service info",
        "tags": [
          "meta"
        ]
      }
    },
    "/.well-known/ai-catalog.json": {
      "get": {
        "description": "ARD 1.0 catalog pointing to OpenAPI. Used by ora.ai, agent discovery.",
        "operationId": "getAiCatalog",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "entries": {
                      "items": {
                        "type": "object"
                      },
                      "type": "array"
                    },
                    "host": {
                      "type": "object"
                    },
                    "specVersion": {
                      "type": "string"
                    }
                  },
                  "type": "object"
                }
              }
            },
            "description": "ARD catalog"
          }
        },
        "summary": "Agentic Resource Discovery catalog",
        "tags": [
          "docs"
        ]
      }
    },
    "/api/docs": {
      "get": {
        "operationId": "getApiDocs",
        "responses": {
          "200": {
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "description": "HTML docs"
          }
        },
        "summary": "Human-readable API docs",
        "tags": [
          "docs"
        ]
      }
    },
    "/api/openapi.json": {
      "get": {
        "operationId": "getOpenApiAlias",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            },
            "description": "OpenAPI document"
          }
        },
        "summary": "OpenAPI 3.1 spec (alias)",
        "tags": [
          "docs"
        ]
      }
    },
    "/health": {
      "get": {
        "operationId": "health",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "service": {
                      "example": "certs.lol",
                      "type": "string"
                    },
                    "status": {
                      "example": "ok",
                      "type": "string"
                    }
                  },
                  "type": "object"
                }
              }
            },
            "description": "OK"
          }
        },
        "summary": "Health check",
        "tags": [
          "meta"
        ]
      }
    },
    "/openapi.json": {
      "get": {
        "description": "This spec. Also served at /api/openapi.json for compatibility.",
        "operationId": "getOpenApi",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              },
              "application/openapi+json": {
                "schema": {
                  "type": "object"
                }
              }
            },
            "description": "OpenAPI document"
          }
        },
        "summary": "OpenAPI 3.1 spec",
        "tags": [
          "docs"
        ]
      }
    },
    "/status": {
      "get": {
        "operationId": "getStatus",
        "responses": {
          "200": {
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "description": "HTML status"
          }
        },
        "summary": "Service status page",
        "tags": [
          "meta"
        ]
      }
    },
    "/usage": {
      "get": {
        "description": "HTML usage stats (KV-backed). Not part of public JSON API.",
        "operationId": "getUsage",
        "responses": {
          "200": {
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "description": "HTML dashboard"
          }
        },
        "summary": "Usage dashboard",
        "tags": [
          "meta"
        ]
      }
    },
    "/{domain}": {
      "get": {
        "description": "Full TLS scan — cert, chain, protocols, ciphers, HSTS, HTTP/3, DNSSEC/CAA/DANE, DANCE readiness, compliance. Cached 6h, 60/hr per IP. Cache hits don't count. Add ?force=1 to bypass cache (still rate-limited). Content-negotiated: Accept: application/json or curl UA → JSON, browser → HTML.",
        "operationId": "scanDomain",
        "parameters": [
          {
            "description": "Domain (e.g., stripe.com, example.com) or IPv4/IPv6 (e.g., 1.1.1.1, [2001:db8::1]). No slashes.",
            "example": "stripe.com",
            "in": "path",
            "name": "domain",
            "required": true,
            "schema": {
              "pattern": "^[^/]+$",
              "type": "string"
            }
          },
          {
            "description": "Bypass cache if present (?force=1). Value ignored, presence triggers.",
            "example": "1",
            "in": "query",
            "name": "force",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScanResult"
                }
              },
              "text/html": {
                "schema": {
                  "description": "HTML report for browsers",
                  "type": "string"
                }
              }
            },
            "description": "Scan result",
            "headers": {
              "Access-Control-Allow-Origin": {
                "schema": {
                  "type": "string"
                }
              },
              "Cache-Control": {
                "schema": {
                  "type": "string"
                }
              },
              "X-Cache": {
                "description": "HIT or MISS",
                "schema": {
                  "enum": [
                    "HIT",
                    "MISS"
                  ],
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Invalid domain or file-extension filtered"
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "error": {
                      "example": "Rate limit exceeded",
                      "type": "string"
                    },
                    "retry_after": {
                      "type": "integer"
                    }
                  },
                  "type": "object"
                }
              }
            },
            "description": "Rate limited",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "example": "0",
                  "type": "string"
                }
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "502": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "detail": {
                      "type": "string"
                    },
                    "error": {
                      "type": "string"
                    },
                    "status": {
                      "type": "integer"
                    }
                  },
                  "type": "object"
                }
              }
            },
            "description": "Probe error or scan failed"
          },
          "504": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "detail": {
                      "type": "string"
                    },
                    "error": {
                      "example": "Scan timed out",
                      "type": "string"
                    }
                  },
                  "type": "object"
                }
              }
            },
            "description": "Timeout (15s probe)"
          }
        },
        "summary": "Scan a domain or IP for TLS",
        "tags": [
          "scan"
        ]
      }
    }
  },
  "security": [],
  "servers": [
    {
      "description": "Production",
      "url": "https://certs.lol"
    }
  ],
  "tags": [
    {
      "description": "TLS scanning",
      "name": "scan"
    },
    {
      "description": "Documentation and discovery",
      "name": "docs"
    },
    {
      "description": "Static assets and metadata",
      "name": "meta"
    }
  ]
}
