{
  "openapi": "3.0.3",
  "info": {
    "title": "MyIPScan API",
    "version": "1.0.0",
    "description": "Free public lookups for IP, ASN, DNS, TLS and the HTTP surface of a site. No key and no account; every route is rate limited per client (8-120 requests/minute depending on the route, 120/minute across all routes together). The API is served from https://myipscan.net only and answers 421 on any other hostname. Human documentation: https://myipscan.net/api-docs/",
    "contact": {
      "name": "MyIPScan",
      "url": "https://myipscan.net/contact"
    },
    "license": {
      "name": "Fair use, no key",
      "url": "https://myipscan.net/api-docs/"
    }
  },
  "externalDocs": {
    "description": "Human-readable reference",
    "url": "https://myipscan.net/api-docs/"
  },
  "servers": [
    {
      "url": "https://myipscan.net"
    }
  ],
  "paths": {
    "/api/ip": {
      "get": {
        "operationId": "getIp",
        "summary": "Your own address as seen by the edge: IP, country, city, region, coordinates, timezone, ASN, organisation, ISP",
        "responses": {
          "200": {
            "description": "The lookup result as a JSON object.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Every route carries a per-minute budget and the response names when to retry.",
            "headers": {
              "retry-after": {
                "schema": {
                  "type": "string"
                },
                "description": "Seconds until the window resets."
              },
              "x-ratelimit-limit": {
                "schema": {
                  "type": "string"
                }
              },
              "x-ratelimit-remaining": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/ip-geolocation-lookup": {
      "get": {
        "operationId": "getIpGeolocationLookup",
        "summary": "Country, region, city, coordinates and network for any public IP",
        "responses": {
          "200": {
            "description": "The lookup result as a JSON object.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Every route carries a per-minute budget and the response names when to retry.",
            "headers": {
              "retry-after": {
                "schema": {
                  "type": "string"
                },
                "description": "Seconds until the window resets."
              },
              "x-ratelimit-limit": {
                "schema": {
                  "type": "string"
                }
              },
              "x-ratelimit-remaining": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "400": {
            "description": "Missing or invalid parameter (error code invalid_input).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "ip",
            "in": "query",
            "required": true,
            "description": "A public IPv4 or IPv6 address.",
            "schema": {
              "type": "string"
            },
            "example": "8.8.8.8"
          }
        ]
      }
    },
    "/api/asn-lookup": {
      "get": {
        "operationId": "getAsnLookup",
        "summary": "Autonomous system details. Accepts an ASN number or a public IP",
        "responses": {
          "200": {
            "description": "The lookup result as a JSON object.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Every route carries a per-minute budget and the response names when to retry.",
            "headers": {
              "retry-after": {
                "schema": {
                  "type": "string"
                },
                "description": "Seconds until the window resets."
              },
              "x-ratelimit-limit": {
                "schema": {
                  "type": "string"
                }
              },
              "x-ratelimit-remaining": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "400": {
            "description": "Missing or invalid parameter (error code invalid_input).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "query",
            "in": "query",
            "required": true,
            "description": "An ASN (with or without the AS prefix) or a public IP address.",
            "schema": {
              "type": "string"
            },
            "example": "AS13335"
          }
        ]
      }
    },
    "/api/rdap": {
      "get": {
        "operationId": "getRdap",
        "summary": "Raw RDAP registry record for an IP or ASN, straight from the responsible RIR",
        "responses": {
          "200": {
            "description": "The lookup result as a JSON object.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Every route carries a per-minute budget and the response names when to retry.",
            "headers": {
              "retry-after": {
                "schema": {
                  "type": "string"
                },
                "description": "Seconds until the window resets."
              },
              "x-ratelimit-limit": {
                "schema": {
                  "type": "string"
                }
              },
              "x-ratelimit-remaining": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "400": {
            "description": "Missing or invalid parameter (error code invalid_input).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "query",
            "in": "query",
            "required": true,
            "description": "An ASN (with or without the AS prefix) or a public IP address.",
            "schema": {
              "type": "string"
            },
            "example": "AS13335"
          }
        ]
      }
    },
    "/api/reverse-dns": {
      "get": {
        "operationId": "getReverseDns",
        "summary": "PTR record for a public IP",
        "responses": {
          "200": {
            "description": "The lookup result as a JSON object.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Every route carries a per-minute budget and the response names when to retry.",
            "headers": {
              "retry-after": {
                "schema": {
                  "type": "string"
                },
                "description": "Seconds until the window resets."
              },
              "x-ratelimit-limit": {
                "schema": {
                  "type": "string"
                }
              },
              "x-ratelimit-remaining": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "400": {
            "description": "Missing or invalid parameter (error code invalid_input).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "ip",
            "in": "query",
            "required": true,
            "description": "A public IPv4 or IPv6 address.",
            "schema": {
              "type": "string"
            },
            "example": "8.8.8.8"
          }
        ]
      }
    },
    "/api/tor-exit": {
      "get": {
        "operationId": "getTorExit",
        "summary": "Whether the address appears on the public Tor exit-node list",
        "responses": {
          "200": {
            "description": "The lookup result as a JSON object.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Every route carries a per-minute budget and the response names when to retry.",
            "headers": {
              "retry-after": {
                "schema": {
                  "type": "string"
                },
                "description": "Seconds until the window resets."
              },
              "x-ratelimit-limit": {
                "schema": {
                  "type": "string"
                }
              },
              "x-ratelimit-remaining": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "ip",
            "in": "query",
            "required": false,
            "description": "A public IPv4 or IPv6 address.",
            "schema": {
              "type": "string"
            },
            "example": "8.8.8.8"
          }
        ]
      }
    },
    "/api/ip-blacklist-checker": {
      "get": {
        "operationId": "getIpBlacklistChecker",
        "summary": "Presence of the address on public DNS blocklists",
        "responses": {
          "200": {
            "description": "The lookup result as a JSON object.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Every route carries a per-minute budget and the response names when to retry.",
            "headers": {
              "retry-after": {
                "schema": {
                  "type": "string"
                },
                "description": "Seconds until the window resets."
              },
              "x-ratelimit-limit": {
                "schema": {
                  "type": "string"
                }
              },
              "x-ratelimit-remaining": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "400": {
            "description": "Missing or invalid parameter (error code invalid_input).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "ip",
            "in": "query",
            "required": true,
            "description": "A public IPv4 or IPv6 address.",
            "schema": {
              "type": "string"
            },
            "example": "8.8.8.8"
          }
        ]
      }
    },
    "/api/dns-lookup": {
      "get": {
        "operationId": "getDnsLookup",
        "summary": "DNS records over DoH. Type accepts A, AAAA, MX, NS, TXT, CNAME, SOA",
        "responses": {
          "200": {
            "description": "The lookup result as a JSON object.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Every route carries a per-minute budget and the response names when to retry.",
            "headers": {
              "retry-after": {
                "schema": {
                  "type": "string"
                },
                "description": "Seconds until the window resets."
              },
              "x-ratelimit-limit": {
                "schema": {
                  "type": "string"
                }
              },
              "x-ratelimit-remaining": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "400": {
            "description": "Missing or invalid parameter (error code invalid_dns_name).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "name",
            "in": "query",
            "required": true,
            "description": "A DNS name.",
            "schema": {
              "type": "string"
            },
            "example": "example.com"
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "description": "Record type. Defaults to A.",
            "schema": {
              "type": "string",
              "enum": [
                "A",
                "AAAA",
                "MX",
                "NS",
                "TXT",
                "CNAME",
                "SOA"
              ]
            }
          }
        ]
      }
    },
    "/api/ssl-certificate": {
      "get": {
        "operationId": "getSslCertificate",
        "summary": "TLS certificate summary: issuer, validity window, subject names",
        "responses": {
          "200": {
            "description": "The lookup result as a JSON object.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Every route carries a per-minute budget and the response names when to retry.",
            "headers": {
              "retry-after": {
                "schema": {
                  "type": "string"
                },
                "description": "Seconds until the window resets."
              },
              "x-ratelimit-limit": {
                "schema": {
                  "type": "string"
                }
              },
              "x-ratelimit-remaining": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "400": {
            "description": "Missing or invalid parameter (error code invalid_hostname).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "host",
            "in": "query",
            "required": true,
            "description": "A hostname to read the served certificate from.",
            "schema": {
              "type": "string"
            },
            "example": "example.com"
          }
        ]
      }
    },
    "/api/http-headers": {
      "get": {
        "operationId": "getHttpHeaders",
        "summary": "Response headers plus a read of the common security headers",
        "responses": {
          "200": {
            "description": "The lookup result as a JSON object.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Every route carries a per-minute budget and the response names when to retry.",
            "headers": {
              "retry-after": {
                "schema": {
                  "type": "string"
                },
                "description": "Seconds until the window resets."
              },
              "x-ratelimit-limit": {
                "schema": {
                  "type": "string"
                }
              },
              "x-ratelimit-remaining": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "400": {
            "description": "Missing or invalid parameter (error code invalid_url).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "url",
            "in": "query",
            "required": true,
            "description": "A public http(s) URL.",
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "example": "https://example.com/"
          }
        ]
      }
    },
    "/api/http-latency": {
      "get": {
        "operationId": "getHttpLatency",
        "summary": "Response timing for a single HEAD request",
        "responses": {
          "200": {
            "description": "The lookup result as a JSON object.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Every route carries a per-minute budget and the response names when to retry.",
            "headers": {
              "retry-after": {
                "schema": {
                  "type": "string"
                },
                "description": "Seconds until the window resets."
              },
              "x-ratelimit-limit": {
                "schema": {
                  "type": "string"
                }
              },
              "x-ratelimit-remaining": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "400": {
            "description": "Missing or invalid parameter (error code invalid_url).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "url",
            "in": "query",
            "required": true,
            "description": "A public http(s) URL.",
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "example": "https://example.com/"
          }
        ]
      }
    },
    "/api/redirect-checker": {
      "get": {
        "operationId": "getRedirectChecker",
        "summary": "Full redirect chain with status codes and timing per hop",
        "responses": {
          "200": {
            "description": "The lookup result as a JSON object.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Every route carries a per-minute budget and the response names when to retry.",
            "headers": {
              "retry-after": {
                "schema": {
                  "type": "string"
                },
                "description": "Seconds until the window resets."
              },
              "x-ratelimit-limit": {
                "schema": {
                  "type": "string"
                }
              },
              "x-ratelimit-remaining": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "400": {
            "description": "Missing or invalid parameter (error code invalid_url).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "url",
            "in": "query",
            "required": true,
            "description": "A public http(s) URL.",
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "example": "https://example.com/"
          }
        ]
      }
    },
    "/api/robots-txt": {
      "get": {
        "operationId": "getRobotsTxt",
        "summary": "robots.txt as served, with parsed directives",
        "responses": {
          "200": {
            "description": "The lookup result as a JSON object.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Every route carries a per-minute budget and the response names when to retry.",
            "headers": {
              "retry-after": {
                "schema": {
                  "type": "string"
                },
                "description": "Seconds until the window resets."
              },
              "x-ratelimit-limit": {
                "schema": {
                  "type": "string"
                }
              },
              "x-ratelimit-remaining": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "400": {
            "description": "Missing or invalid parameter (error code invalid_url).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "url",
            "in": "query",
            "required": true,
            "description": "A public http(s) URL.",
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "example": "https://example.com/"
          }
        ]
      }
    },
    "/api/sitemap-checker": {
      "get": {
        "operationId": "getSitemapChecker",
        "summary": "Sitemap discovery and basic validity",
        "responses": {
          "200": {
            "description": "The lookup result as a JSON object.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Every route carries a per-minute budget and the response names when to retry.",
            "headers": {
              "retry-after": {
                "schema": {
                  "type": "string"
                },
                "description": "Seconds until the window resets."
              },
              "x-ratelimit-limit": {
                "schema": {
                  "type": "string"
                }
              },
              "x-ratelimit-remaining": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "400": {
            "description": "Missing or invalid parameter (error code invalid_url).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "url",
            "in": "query",
            "required": true,
            "description": "A public http(s) URL.",
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "example": "https://example.com/"
          }
        ]
      }
    },
    "/api/canonical-noindex": {
      "get": {
        "operationId": "getCanonicalNoindex",
        "summary": "Canonical URL and indexing directives from headers and markup",
        "responses": {
          "200": {
            "description": "The lookup result as a JSON object.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Every route carries a per-minute budget and the response names when to retry.",
            "headers": {
              "retry-after": {
                "schema": {
                  "type": "string"
                },
                "description": "Seconds until the window resets."
              },
              "x-ratelimit-limit": {
                "schema": {
                  "type": "string"
                }
              },
              "x-ratelimit-remaining": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "400": {
            "description": "Missing or invalid parameter (error code invalid_url).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "url",
            "in": "query",
            "required": true,
            "description": "A public http(s) URL.",
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "example": "https://example.com/"
          }
        ]
      }
    },
    "/api/meta-title-description": {
      "get": {
        "operationId": "getMetaTitleDescription",
        "summary": "Title and meta description with lengths",
        "responses": {
          "200": {
            "description": "The lookup result as a JSON object.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Every route carries a per-minute budget and the response names when to retry.",
            "headers": {
              "retry-after": {
                "schema": {
                  "type": "string"
                },
                "description": "Seconds until the window resets."
              },
              "x-ratelimit-limit": {
                "schema": {
                  "type": "string"
                }
              },
              "x-ratelimit-remaining": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "400": {
            "description": "Missing or invalid parameter (error code invalid_url).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "url",
            "in": "query",
            "required": true,
            "description": "A public http(s) URL.",
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "example": "https://example.com/"
          }
        ]
      }
    },
    "/api/open-graph-social": {
      "get": {
        "operationId": "getOpenGraphSocial",
        "summary": "Open Graph and Twitter card fields",
        "responses": {
          "200": {
            "description": "The lookup result as a JSON object.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Every route carries a per-minute budget and the response names when to retry.",
            "headers": {
              "retry-after": {
                "schema": {
                  "type": "string"
                },
                "description": "Seconds until the window resets."
              },
              "x-ratelimit-limit": {
                "schema": {
                  "type": "string"
                }
              },
              "x-ratelimit-remaining": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "400": {
            "description": "Missing or invalid parameter (error code invalid_url).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "url",
            "in": "query",
            "required": true,
            "description": "A public http(s) URL.",
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "example": "https://example.com/"
          }
        ]
      }
    },
    "/api/structured-data": {
      "get": {
        "operationId": "getStructuredData",
        "summary": "JSON-LD blocks found on the page, parsed",
        "responses": {
          "200": {
            "description": "The lookup result as a JSON object.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Every route carries a per-minute budget and the response names when to retry.",
            "headers": {
              "retry-after": {
                "schema": {
                  "type": "string"
                },
                "description": "Seconds until the window resets."
              },
              "x-ratelimit-limit": {
                "schema": {
                  "type": "string"
                }
              },
              "x-ratelimit-remaining": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "400": {
            "description": "Missing or invalid parameter (error code invalid_url).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "url",
            "in": "query",
            "required": true,
            "description": "A public http(s) URL.",
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "example": "https://example.com/"
          }
        ]
      }
    },
    "/api/html-heading-content-structure": {
      "get": {
        "operationId": "getHtmlHeadingContentStructure",
        "summary": "Heading outline and content structure",
        "responses": {
          "200": {
            "description": "The lookup result as a JSON object.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Every route carries a per-minute budget and the response names when to retry.",
            "headers": {
              "retry-after": {
                "schema": {
                  "type": "string"
                },
                "description": "Seconds until the window resets."
              },
              "x-ratelimit-limit": {
                "schema": {
                  "type": "string"
                }
              },
              "x-ratelimit-remaining": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "400": {
            "description": "Missing or invalid parameter (error code invalid_url).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "url",
            "in": "query",
            "required": true,
            "description": "A public http(s) URL.",
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "example": "https://example.com/"
          }
        ]
      }
    },
    "/api/website-exposure": {
      "post": {
        "operationId": "postWebsiteExposure",
        "summary": "Combined public-surface report for a hostname",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "target"
                ],
                "properties": {
                  "target": {
                    "type": "string",
                    "example": "example.com",
                    "description": "A public hostname or domain."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The report as a JSON object.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "Missing or invalid target (error code invalid_target).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Every route carries a per-minute budget and the response names when to retry.",
            "headers": {
              "retry-after": {
                "schema": {
                  "type": "string"
                },
                "description": "Seconds until the window resets."
              },
              "x-ratelimit-limit": {
                "schema": {
                  "type": "string"
                }
              },
              "x-ratelimit-remaining": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/domain-intelligence": {
      "post": {
        "operationId": "postDomainIntelligence",
        "summary": "Domain overview: registry, DNS, hosting and mail signals",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "target"
                ],
                "properties": {
                  "target": {
                    "type": "string",
                    "example": "example.com",
                    "description": "A public hostname or domain."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The report as a JSON object.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "Missing or invalid target (error code invalid_target).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Every route carries a per-minute budget and the response names when to retry.",
            "headers": {
              "retry-after": {
                "schema": {
                  "type": "string"
                },
                "description": "Seconds until the window resets."
              },
              "x-ratelimit-limit": {
                "schema": {
                  "type": "string"
                }
              },
              "x-ratelimit-remaining": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/email-exposure": {
      "post": {
        "operationId": "postEmailExposure",
        "summary": "Mail-related exposure for a domain: SPF, DMARC, MX posture",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "target"
                ],
                "properties": {
                  "target": {
                    "type": "string",
                    "example": "example.com",
                    "description": "A public hostname or domain."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The report as a JSON object.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "Missing or invalid target (error code invalid_target).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Every route carries a per-minute budget and the response names when to retry.",
            "headers": {
              "retry-after": {
                "schema": {
                  "type": "string"
                },
                "description": "Seconds until the window resets."
              },
              "x-ratelimit-limit": {
                "schema": {
                  "type": "string"
                }
              },
              "x-ratelimit-remaining": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/ai-search-visibility": {
      "post": {
        "operationId": "postAiSearchVisibility",
        "summary": "Whether AI crawlers are permitted, from robots.txt and headers",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "target"
                ],
                "properties": {
                  "target": {
                    "type": "string",
                    "example": "example.com",
                    "description": "A public hostname or domain."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The report as a JSON object.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "Missing or invalid target (error code invalid_target).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Every route carries a per-minute budget and the response names when to retry.",
            "headers": {
              "retry-after": {
                "schema": {
                  "type": "string"
                },
                "description": "Seconds until the window resets."
              },
              "x-ratelimit-limit": {
                "schema": {
                  "type": "string"
                }
              },
              "x-ratelimit-remaining": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "ok",
          "error"
        ],
        "properties": {
          "ok": {
            "type": "boolean",
            "enum": [
              false
            ]
          },
          "error": {
            "type": "object",
            "required": [
              "code",
              "message"
            ],
            "properties": {
              "code": {
                "type": "string"
              },
              "message": {
                "type": "string"
              }
            }
          }
        }
      }
    }
  }
}
