{
  "openapi": "3.1.0",
  "jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
  "info": {
    "title": "whatsmyip.fyi API",
    "version": "1.0.0",
    "summary": "Public IP, geolocation, DNS, RDAP and reputation, without a key.",
    "description": "A keyless JSON API for the address of the caller and for lookups against other targets.\n\nNothing here needs a key, an account or a contract. Rate limits are published rather than discovered, every response carries the quota that is left, and CORS is open on every endpoint so a browser can call it directly.\n\n**The v1 promise.** Fields may be added. An existing field will never be removed, and its type and meaning will never change. Parse defensively and ignore what you do not recognise. Anything genuinely incompatible becomes /api/v2 and v1 keeps serving.\n\nGeolocation is always approximate. It reflects the route the address takes, not a street address, and it is labelled that way in every response through the geo_accuracy field.",
    "termsOfService": "https://whatsmyip.fyi/terms",
    "contact": {
      "name": "whatsmyip.fyi",
      "email": "hello@whatsmyip.fyi",
      "url": "https://whatsmyip.fyi/contact"
    },
    "license": {
      "name": "CC BY 4.0",
      "identifier": "CC-BY-4.0"
    }
  },
  "externalDocs": {
    "description": "Human documentation",
    "url": "https://whatsmyip.fyi/api"
  },
  "servers": [
    {
      "url": "https://whatsmyip.fyi",
      "description": "Production, dual-stack"
    },
    {
      "url": "https://v4.whatsmyip.fyi",
      "description": "IPv4 only, A record with no AAAA"
    },
    {
      "url": "https://v6.whatsmyip.fyi",
      "description": "IPv6 only, AAAA record with no A"
    }
  ],
  "security": [],
  "tags": [
    {
      "name": "requester",
      "description": "Facts about the connection that made the call."
    },
    {
      "name": "lookup",
      "description": "Facts about a target the caller names."
    },
    {
      "name": "registry",
      "description": "Registration data from the RIRs and domain registries."
    },
    {
      "name": "reputation",
      "description": "Attributed public blocklists."
    },
    {
      "name": "meta",
      "description": "The service describing itself."
    }
  ],
  "paths": {
    "/ip": {
      "get": {
        "tags": [
          "requester"
        ],
        "operationId": "getIpText",
        "summary": "The caller address as plain text",
        "description": "The address and a trailing newline. Nothing else. This is the endpoint to paste into a shell script, because the body needs no parsing and cannot grow a field later.",
        "deprecated": false,
        "x-status": "stable",
        "x-rate-limit-class": "public-ip",
        "x-cache-control": "private, no-store",
        "parameters": [],
        "responses": {
          "200": {
            "description": "The caller address as plain text",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "The limit of the window that is closest to being exhausted.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in that window. Omitted when the reported window is a per-minute window, because the limiter that enforces it does not report a count.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "When that window ends, in Unix seconds.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Policy": {
                "description": "The policy that counted this request, or \"unavailable\" when the counter store could not be reached.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "text/plain; charset=utf-8": {
                "schema": {
                  "type": "string"
                },
                "example": "203.0.113.45\n"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/json": {
      "get": {
        "tags": [
          "requester"
        ],
        "operationId": "getIpJson",
        "summary": "The caller report as JSON",
        "description": "The full record for the calling address. Served from the edge with no external call unless full=1 is set. This is the short URL; /api/v1/ip is the same response behind the version guarantee.",
        "deprecated": false,
        "x-status": "stable",
        "x-rate-limit-class": "public-ip",
        "x-cache-control": "private, no-store",
        "parameters": [
          {
            "name": "full",
            "in": "query",
            "required": false,
            "description": "Set to 1 to resolve the reverse DNS name and the privacy flags. Both cost a provider call and are metered separately at 20 per day.",
            "schema": {
              "type": "string",
              "enum": [
                "1"
              ]
            },
            "example": "1"
          }
        ],
        "responses": {
          "200": {
            "description": "The caller report as JSON",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "The limit of the window that is closest to being exhausted.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in that window. Omitted when the reported window is a per-minute window, because the limiter that enforces it does not report a count.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "When that window ends, in Unix seconds.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Policy": {
                "description": "The policy that counted this request, or \"unavailable\" when the counter store could not be reached.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json; charset=utf-8": {
                "schema": {
                  "$ref": "#/components/schemas/IpReport"
                },
                "example": {
                  "ip": "203.0.113.45",
                  "version": 4,
                  "hostname": null,
                  "city": "Tallinn",
                  "region": "Harjumaa",
                  "region_code": "37",
                  "country": "EE",
                  "country_name": "Estonia",
                  "continent": "EU",
                  "postal": "10111",
                  "loc": "59.4370,24.7536",
                  "timezone": "Europe/Tallinn",
                  "local_time": "2026-09-05T14:02:11+03:00",
                  "isp": "Telia Eesti",
                  "asn": 3249,
                  "as_name": "Telia Eesti AS",
                  "as_domain": "telia.ee",
                  "rir": "RIPE",
                  "connection_type": "residential",
                  "privacy": null,
                  "network": {
                    "protocol": "HTTP/2",
                    "tls": "TLSv1.3",
                    "rtt_ms": 21,
                    "edge": "TLL"
                  },
                  "user_agent": "curl/8.7.1",
                  "accepts_language": null,
                  "geo_accuracy": "approximate",
                  "checked_at": "2026-09-05T14:02:11Z",
                  "source": "whatsmyip.fyi"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/ip.md": {
      "get": {
        "tags": [
          "requester"
        ],
        "operationId": "getIpMarkdown",
        "summary": "The caller report as Markdown",
        "description": "A five-line Markdown document carrying its own source URL. Written for agents and language models that handle prose better than JSON, and small enough to paste into a prompt.",
        "deprecated": false,
        "x-status": "stable",
        "x-rate-limit-class": "public-ip",
        "x-cache-control": "private, no-store",
        "parameters": [],
        "responses": {
          "200": {
            "description": "The caller report as Markdown",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "The limit of the window that is closest to being exhausted.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in that window. Omitted when the reported window is a per-minute window, because the limiter that enforces it does not report a count.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "When that window ends, in Unix seconds.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Policy": {
                "description": "The policy that counted this request, or \"unavailable\" when the counter store could not be reached.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "text/markdown; charset=utf-8": {
                "schema": {
                  "type": "string"
                },
                "example": "# Your public IP\nIP: 203.0.113.45 (IPv4)\nLocation: Tallinn, Harjumaa, EE (approximate)\nISP: Telia Eesti (AS3249)\nSource: https://whatsmyip.fyi/ip.md\n"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/v1/ip": {
      "get": {
        "tags": [
          "requester"
        ],
        "operationId": "getV1Ip",
        "summary": "The caller report, versioned",
        "description": "Byte-for-byte the same response as /json. Use this path in anything you will not revisit for a year, because the compatibility promise is attached to the version segment rather than to the short URL.",
        "deprecated": false,
        "x-status": "stable",
        "x-rate-limit-class": "public-ip",
        "x-cache-control": "private, no-store",
        "parameters": [
          {
            "name": "full",
            "in": "query",
            "required": false,
            "description": "Set to 1 to resolve the reverse DNS name and the privacy flags. Both cost a provider call and are metered separately at 20 per day.",
            "schema": {
              "type": "string",
              "enum": [
                "1"
              ]
            },
            "example": "1"
          }
        ],
        "responses": {
          "200": {
            "description": "The caller report, versioned",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "The limit of the window that is closest to being exhausted.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in that window. Omitted when the reported window is a per-minute window, because the limiter that enforces it does not report a count.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "When that window ends, in Unix seconds.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Policy": {
                "description": "The policy that counted this request, or \"unavailable\" when the counter store could not be reached.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json; charset=utf-8": {
                "schema": {
                  "$ref": "#/components/schemas/IpReport"
                },
                "example": {
                  "ip": "203.0.113.45",
                  "version": 4,
                  "hostname": null,
                  "city": "Tallinn",
                  "region": "Harjumaa",
                  "region_code": "37",
                  "country": "EE",
                  "country_name": "Estonia",
                  "continent": "EU",
                  "postal": "10111",
                  "loc": "59.4370,24.7536",
                  "timezone": "Europe/Tallinn",
                  "local_time": "2026-09-05T14:02:11+03:00",
                  "isp": "Telia Eesti",
                  "asn": 3249,
                  "as_name": "Telia Eesti AS",
                  "as_domain": "telia.ee",
                  "rir": "RIPE",
                  "connection_type": "residential",
                  "privacy": null,
                  "network": {
                    "protocol": "HTTP/2",
                    "tls": "TLSv1.3",
                    "rtt_ms": 21,
                    "edge": "TLL"
                  },
                  "user_agent": "curl/8.7.1",
                  "accepts_language": null,
                  "geo_accuracy": "approximate",
                  "checked_at": "2026-09-05T14:02:11Z",
                  "source": "whatsmyip.fyi"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/v1/lookup/{target}": {
      "get": {
        "tags": [
          "lookup"
        ],
        "operationId": "getV1Lookup",
        "summary": "Look up any address or hostname",
        "description": "The IpReport shape for a target other than the caller, plus the RFC classification of the address. A hostname is resolved first and the resolved address is reported. Private, reserved and documentation ranges return the classification and an explanation rather than a geolocation guess.",
        "deprecated": false,
        "x-status": "stable",
        "x-rate-limit-class": "lookup",
        "x-cache-control": "public, max-age=300",
        "parameters": [
          {
            "name": "target",
            "in": "path",
            "required": true,
            "description": "An IPv4 address, an IPv6 address or a hostname.",
            "schema": {
              "type": "string"
            },
            "example": "8.8.8.8"
          },
          {
            "name": "privacy",
            "in": "query",
            "required": false,
            "description": "Set to 1 to add the VPN, proxy, Tor, hosting and relay flags. Metered at 20 per day.",
            "schema": {
              "type": "string",
              "enum": [
                "1"
              ]
            },
            "example": "1"
          }
        ],
        "responses": {
          "200": {
            "description": "Look up any address or hostname",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "The limit of the window that is closest to being exhausted.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in that window. Omitted when the reported window is a per-minute window, because the limiter that enforces it does not report a count.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "When that window ends, in Unix seconds.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Policy": {
                "description": "The policy that counted this request, or \"unavailable\" when the counter store could not be reached.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json; charset=utf-8": {
                "schema": {
                  "$ref": "#/components/schemas/LookupResponse"
                },
                "example": {
                  "ip": "8.8.8.8",
                  "version": 4,
                  "hostname": "dns.google",
                  "city": null,
                  "country": "US",
                  "country_name": "United States",
                  "isp": "Google LLC",
                  "asn": 15169,
                  "as_name": "GOOGLE",
                  "as_domain": "google.com",
                  "rir": "ARIN",
                  "connection_type": "hosting",
                  "privacy": null,
                  "geo_accuracy": "country-only",
                  "classification": {
                    "kind": "public",
                    "rfc": null,
                    "description": "Globally routable unicast address.",
                    "routable": true
                  },
                  "checked_at": "2026-09-05T14:02:11Z",
                  "source": "whatsmyip.fyi"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/v1/dns": {
      "get": {
        "tags": [
          "lookup"
        ],
        "operationId": "getV1Dns",
        "summary": "DNS over two resolvers at once",
        "description": "Queries more than one public resolver over DoH in parallel and returns each answer separately with its TTL and the DNSSEC AD flag. Answers are not reconciled. Which resolver said what is usually the information you came for.",
        "deprecated": false,
        "x-status": "stable",
        "x-rate-limit-class": "lookup",
        "x-cache-control": "public, max-age=60",
        "parameters": [
          {
            "name": "name",
            "in": "query",
            "required": true,
            "description": "The name to query. Internationalised names are converted to A-label form and both are returned.",
            "schema": {
              "type": "string"
            },
            "example": "example.com"
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "description": "A, AAAA, MX, TXT, NS, SOA, CAA, SRV, PTR, DNSKEY or DS. Defaults to A.",
            "schema": {
              "type": "string",
              "default": "A"
            },
            "example": "MX"
          }
        ],
        "responses": {
          "200": {
            "description": "DNS over two resolvers at once",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "The limit of the window that is closest to being exhausted.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in that window. Omitted when the reported window is a per-minute window, because the limiter that enforces it does not report a count.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "When that window ends, in Unix seconds.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Policy": {
                "description": "The policy that counted this request, or \"unavailable\" when the counter store could not be reached.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json; charset=utf-8": {
                "schema": {
                  "$ref": "#/components/schemas/DnsResponse"
                },
                "example": {
                  "name": "example.com",
                  "ascii_name": "example.com",
                  "type": "A",
                  "answers": [
                    {
                      "resolver": "cloudflare",
                      "status": 0,
                      "ad": true,
                      "records": [
                        {
                          "name": "example.com",
                          "type": "A",
                          "ttl": 300,
                          "data": "93.184.215.14"
                        }
                      ],
                      "error": null
                    },
                    {
                      "resolver": "google",
                      "status": 0,
                      "ad": true,
                      "records": [
                        {
                          "name": "example.com",
                          "type": "A",
                          "ttl": 288,
                          "data": "93.184.215.14"
                        }
                      ],
                      "error": null
                    }
                  ],
                  "agree": true,
                  "dnssec": true,
                  "checked_at": "2026-09-05T14:02:11Z",
                  "source": "whatsmyip.fyi"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/v1/rdap": {
      "get": {
        "tags": [
          "registry"
        ],
        "operationId": "getV1Rdap",
        "summary": "Normalised registration data",
        "description": "RDAP for an address, a domain or an AS number, flattened into one stable shape with the raw registry response kept alongside. Where a registry publishes no RDAP service the query falls back to port 43 WHOIS, and the summary says which path answered.",
        "deprecated": false,
        "x-status": "stable",
        "x-rate-limit-class": "lookup",
        "x-cache-control": "public, max-age=3600",
        "parameters": [
          {
            "name": "query",
            "in": "query",
            "required": true,
            "description": "An IP address, a CIDR block, a domain name or an AS number.",
            "schema": {
              "type": "string"
            },
            "example": "1.1.1.1"
          }
        ],
        "responses": {
          "200": {
            "description": "Normalised registration data",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "The limit of the window that is closest to being exhausted.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in that window. Omitted when the reported window is a per-minute window, because the limiter that enforces it does not report a count.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "When that window ends, in Unix seconds.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Policy": {
                "description": "The policy that counted this request, or \"unavailable\" when the counter store could not be reached.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json; charset=utf-8": {
                "schema": {
                  "$ref": "#/components/schemas/RdapResponse"
                },
                "example": {
                  "query": "1.1.1.1",
                  "kind": "ip",
                  "summary": {
                    "handle": "1.1.1.0 - 1.1.1.255",
                    "name": "APNIC-LABS",
                    "type": "ASSIGNED PORTABLE",
                    "country": "AU",
                    "start_address": "1.1.1.0",
                    "end_address": "1.1.1.255",
                    "cidr": [
                      "1.1.1.0/24"
                    ],
                    "registry": "APNIC",
                    "registered": "2011-08-10T23:12:35Z",
                    "updated": "2024-03-06T02:46:16Z",
                    "status": [
                      "active"
                    ],
                    "abuse_email": "helpdesk@apnic.net",
                    "entities": [
                      {
                        "handle": "AA1412-AP",
                        "role": "administrative",
                        "name": "APNIC RDNS",
                        "email": null
                      }
                    ],
                    "source": "rdap"
                  },
                  "raw": {},
                  "cached": false,
                  "checked_at": "2026-09-05T14:02:11Z",
                  "source": "whatsmyip.fyi"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/v1/reverse/{ip}": {
      "get": {
        "tags": [
          "lookup"
        ],
        "operationId": "getV1Reverse",
        "summary": "PTR with a forward-confirmed check",
        "description": "The PTR names for an address, plus the forward lookup of each name back to an address. A PTR record alone proves nothing, because the owner of the address writes it. forward_confirmed is the field that carries weight.",
        "deprecated": false,
        "x-status": "stable",
        "x-rate-limit-class": "lookup",
        "x-cache-control": "public, max-age=300",
        "parameters": [
          {
            "name": "ip",
            "in": "path",
            "required": true,
            "description": "An IPv4 or IPv6 address.",
            "schema": {
              "type": "string"
            },
            "example": "8.8.8.8"
          }
        ],
        "responses": {
          "200": {
            "description": "PTR with a forward-confirmed check",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "The limit of the window that is closest to being exhausted.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in that window. Omitted when the reported window is a per-minute window, because the limiter that enforces it does not report a count.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "When that window ends, in Unix seconds.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Policy": {
                "description": "The policy that counted this request, or \"unavailable\" when the counter store could not be reached.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json; charset=utf-8": {
                "schema": {
                  "$ref": "#/components/schemas/ReverseDnsResponse"
                },
                "example": {
                  "ip": "8.8.8.8",
                  "version": 4,
                  "arpa": "8.8.8.8.in-addr.arpa",
                  "hostnames": [
                    "dns.google"
                  ],
                  "forward_confirmed": true,
                  "forward_addresses": [
                    "8.8.8.8",
                    "8.8.4.4"
                  ],
                  "checked_at": "2026-09-05T14:02:11Z",
                  "source": "whatsmyip.fyi"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/v1/blacklist/{ip}": {
      "get": {
        "tags": [
          "reputation"
        ],
        "operationId": "getV1Blacklist",
        "summary": "DNSBL status across attributed lists",
        "description": "One row per curated public blocklist, with the return code the list gave and the meaning that list documents for it. Results are cached for an hour. Every list is named, because an unattributed reputation score is not a check anyone can act on.",
        "deprecated": false,
        "x-status": "stable",
        "x-rate-limit-class": "lookup",
        "x-cache-control": "public, max-age=3600",
        "parameters": [
          {
            "name": "ip",
            "in": "path",
            "required": true,
            "description": "An IPv4 or IPv6 address.",
            "schema": {
              "type": "string"
            },
            "example": "203.0.113.45"
          }
        ],
        "responses": {
          "200": {
            "description": "DNSBL status across attributed lists",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "The limit of the window that is closest to being exhausted.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in that window. Omitted when the reported window is a per-minute window, because the limiter that enforces it does not report a count.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "When that window ends, in Unix seconds.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Policy": {
                "description": "The policy that counted this request, or \"unavailable\" when the counter store could not be reached.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json; charset=utf-8": {
                "schema": {
                  "$ref": "#/components/schemas/BlacklistResponse"
                },
                "example": {
                  "ip": "203.0.113.45",
                  "version": 4,
                  "listed_count": 0,
                  "total_count": 6,
                  "results": [
                    {
                      "list": "Spamhaus ZEN",
                      "zone": "zen.spamhaus.org",
                      "listed": false,
                      "codes": [],
                      "reason": null,
                      "lookup_url": "https://check.spamhaus.org/results/?query=203.0.113.45",
                      "error": null
                    }
                  ],
                  "checked_at": "2026-09-05T14:02:11Z",
                  "source": "whatsmyip.fyi"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/v1/mx": {
      "get": {
        "tags": [
          "lookup"
        ],
        "operationId": "getV1Mx",
        "summary": "Mail records with SPF and DMARC parsing",
        "description": "MX hosts in preference order with their addresses, the SPF record with its DNS-lookup count checked against the limit of ten in RFC 7208, and the DMARC record parsed into its tags.",
        "deprecated": false,
        "x-status": "stable",
        "x-rate-limit-class": "lookup",
        "x-cache-control": "public, max-age=300",
        "parameters": [
          {
            "name": "domain",
            "in": "query",
            "required": true,
            "description": "The domain to inspect. Not a mail address.",
            "schema": {
              "type": "string"
            },
            "example": "example.com"
          }
        ],
        "responses": {
          "200": {
            "description": "Mail records with SPF and DMARC parsing",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "The limit of the window that is closest to being exhausted.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in that window. Omitted when the reported window is a per-minute window, because the limiter that enforces it does not report a count.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "When that window ends, in Unix seconds.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Policy": {
                "description": "The policy that counted this request, or \"unavailable\" when the counter store could not be reached.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json; charset=utf-8": {
                "schema": {
                  "$ref": "#/components/schemas/MxResponse"
                },
                "example": {
                  "domain": "example.com",
                  "ascii_domain": "example.com",
                  "records": [
                    {
                      "host": "mx1.example.com",
                      "preference": 10,
                      "addresses": [
                        "203.0.113.10"
                      ],
                      "resolves": true
                    }
                  ],
                  "spf": {
                    "raw": "v=spf1 include:_spf.example.net -all",
                    "valid": true,
                    "version": "spf1",
                    "terms": [
                      {
                        "qualifier": "+",
                        "mechanism": "include",
                        "value": "_spf.example.net",
                        "countsTowardLimit": true
                      },
                      {
                        "qualifier": "-",
                        "mechanism": "all",
                        "value": null,
                        "countsTowardLimit": false
                      }
                    ],
                    "modifiers": [],
                    "lookupCount": 1,
                    "exceedsLookupLimit": false,
                    "all": {
                      "qualifier": "-",
                      "mechanism": "all",
                      "value": null,
                      "countsTowardLimit": false
                    },
                    "errors": []
                  },
                  "dmarc": {
                    "raw": "v=DMARC1; p=reject; rua=mailto:dmarc@example.com",
                    "valid": true,
                    "version": "DMARC1",
                    "policy": "reject",
                    "subdomainPolicy": null,
                    "percent": null,
                    "aggregateReports": [
                      "mailto:dmarc@example.com"
                    ],
                    "forensicReports": [],
                    "adkim": null,
                    "aspf": null,
                    "failureOptions": null,
                    "reportInterval": null,
                    "tags": {
                      "v": "DMARC1",
                      "p": "reject",
                      "rua": "mailto:dmarc@example.com"
                    },
                    "errors": []
                  },
                  "checked_at": "2026-09-05T14:02:11Z",
                  "source": "whatsmyip.fyi"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/v1/ssl": {
      "get": {
        "tags": [
          "lookup"
        ],
        "operationId": "getV1Ssl",
        "summary": "Decode the TLS certificate a host presents",
        "description": "Opens port 443, reads the certificate chain out of a TLS 1.2 handshake, and returns the subject, every subject alternative name, the issuer chain, the validity window with days remaining, the key type and size, the signature algorithm and the SHA-256 fingerprint. A plain HTTPS request runs alongside it for the status code, HSTS and Alt-Svc. A server that refuses TLS 1.2 returns a null certificate and the HTTPS reading alone, because a TLS 1.3 handshake encrypts the certificate.",
        "deprecated": false,
        "x-status": "stable",
        "x-rate-limit-class": "lookup",
        "x-cache-control": "public, max-age=300",
        "parameters": [
          {
            "name": "host",
            "in": "query",
            "required": true,
            "description": "The hostname to inspect. Port 443 only, public addresses only, no address literals.",
            "schema": {
              "type": "string"
            },
            "example": "example.com"
          }
        ],
        "responses": {
          "200": {
            "description": "Decode the TLS certificate a host presents",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "The limit of the window that is closest to being exhausted.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in that window. Omitted when the reported window is a per-minute window, because the limiter that enforces it does not report a count.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "When that window ends, in Unix seconds.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Policy": {
                "description": "The policy that counted this request, or \"unavailable\" when the counter store could not be reached.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json; charset=utf-8": {
                "schema": {
                  "$ref": "#/components/schemas/SslResponse"
                },
                "example": {
                  "host": "example.com",
                  "ascii_host": "example.com",
                  "port": 443,
                  "addresses": [
                    {
                      "address": "203.0.113.10",
                      "family": "IPv4"
                    }
                  ],
                  "connected_address": "203.0.113.10:443",
                  "certificate": {
                    "subject": "CN=example.com",
                    "subject_common_name": "example.com",
                    "issuer": "C=US, O=Example CA, CN=Example TLS ECC CA 3",
                    "issuer_common_name": "Example TLS ECC CA 3",
                    "issuer_organization": "Example CA",
                    "serial": "0624D0AB311558780B7D5213B9631831",
                    "version": 3,
                    "not_before": "2026-07-29T22:10:08Z",
                    "not_after": "2026-10-27T22:17:21Z",
                    "days_remaining": 52,
                    "expiry_band": "ok",
                    "lifetime_days": 90,
                    "sans": [
                      "example.com",
                      "*.example.com"
                    ],
                    "san_ips": [],
                    "key": {
                      "algorithm": "EC",
                      "bits": 256,
                      "curve": "P-256"
                    },
                    "signature_algorithm": "ecdsa-with-SHA256",
                    "is_certificate_authority": false,
                    "self_issued": false,
                    "extended_key_usage": [
                      "serverAuth"
                    ],
                    "ocsp_responders": [
                      "http://ocsp.example-ca.net"
                    ],
                    "ca_issuers": [
                      "http://i.example-ca.net/issuer.cer"
                    ],
                    "fingerprint_sha256": "61:53:A9:6F:D1:A6:AB:7F:4D:43:8F:C3:49:32:48:42:99:D0:72:9D:91:40:B3:A1:26:BB:2F:9C:07:B0:22:00"
                  },
                  "chain_length": 3,
                  "hostname_match": {
                    "matched": true,
                    "matched_name": "example.com",
                    "checked_names": [
                      "example.com",
                      "*.example.com"
                    ],
                    "used_common_name": false
                  },
                  "https": {
                    "reachable": true,
                    "method": "HEAD",
                    "status": 200,
                    "location": null,
                    "strict_transport_security": "max-age=31536000",
                    "alt_svc": null,
                    "server": "example",
                    "error": null
                  },
                  "probe": {
                    "certificate_read": true,
                    "method": "tls12-clienthello",
                    "negotiated_version": "TLS 1.2",
                    "cipher_suite": "ECDHE-ECDSA-AES128-GCM-SHA256",
                    "alert": null,
                    "error": null,
                    "elapsed_ms": 101
                  },
                  "checked_at": "2026-09-05T14:02:11Z",
                  "source": "whatsmyip.fyi"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/v1/headers": {
      "get": {
        "tags": [
          "requester"
        ],
        "operationId": "getV1Headers",
        "summary": "Echo of the request headers",
        "description": "The headers the edge received, in the order received, each with a one-line explanation. Cookie and Authorization are replaced with a redaction marker so that a shared debugging transcript cannot leak a credential. Edge only, no external call.",
        "deprecated": false,
        "x-status": "stable",
        "x-rate-limit-class": "public-ip",
        "x-cache-control": "private, no-store",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Echo of the request headers",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "The limit of the window that is closest to being exhausted.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in that window. Omitted when the reported window is a per-minute window, because the limiter that enforces it does not report a count.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "When that window ends, in Unix seconds.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Policy": {
                "description": "The policy that counted this request, or \"unavailable\" when the counter store could not be reached.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json; charset=utf-8": {
                "schema": {
                  "$ref": "#/components/schemas/HeadersResponse"
                },
                "example": {
                  "headers": [
                    {
                      "name": "user-agent",
                      "value": "curl/8.7.1",
                      "redacted": false,
                      "explanation": "The client software identifying itself."
                    },
                    {
                      "name": "authorization",
                      "value": "[redacted]",
                      "redacted": true,
                      "explanation": "Credentials. Never echoed back."
                    }
                  ],
                  "method": "GET",
                  "protocol": "HTTP/2",
                  "tls": "TLSv1.3",
                  "checked_at": "2026-09-05T14:02:11Z",
                  "source": "whatsmyip.fyi"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/v1/ua": {
      "get": {
        "tags": [
          "requester"
        ],
        "operationId": "getV1Ua",
        "summary": "Parse a user agent string",
        "description": "Browser, engine, operating system and device class. Parses the caller own header, or the string given in the ua parameter. Edge only, no external call, so it is cheap enough for high-frequency debugging.",
        "deprecated": false,
        "x-status": "stable",
        "x-rate-limit-class": "public-ip",
        "x-cache-control": "private, no-store",
        "parameters": [
          {
            "name": "ua",
            "in": "query",
            "required": false,
            "description": "A user agent string to parse instead of the caller own.",
            "schema": {
              "type": "string"
            },
            "example": "curl/8.7.1"
          }
        ],
        "responses": {
          "200": {
            "description": "Parse a user agent string",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "The limit of the window that is closest to being exhausted.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in that window. Omitted when the reported window is a per-minute window, because the limiter that enforces it does not report a count.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "When that window ends, in Unix seconds.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Policy": {
                "description": "The policy that counted this request, or \"unavailable\" when the counter store could not be reached.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json; charset=utf-8": {
                "schema": {
                  "$ref": "#/components/schemas/UaResponse"
                },
                "example": {
                  "user_agent": "curl/8.7.1",
                  "browser": {
                    "name": "curl",
                    "version": "8.7.1"
                  },
                  "engine": {
                    "name": null,
                    "version": null
                  },
                  "os": {
                    "name": null,
                    "version": null
                  },
                  "device": "cli",
                  "bot": false,
                  "cli": true,
                  "checked_at": "2026-09-05T14:02:11Z",
                  "source": "whatsmyip.fyi"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/v1/status": {
      "get": {
        "tags": [
          "meta"
        ],
        "operationId": "getV1Status",
        "summary": "Measured uptime and latency",
        "description": "The same figures the status page renders: uptime and p50 and p95 latency per target and region over the last 24 hours and the last 30 days. Poll this rather than the badge image; the badge is a picture.",
        "deprecated": false,
        "x-status": "stable",
        "x-rate-limit-class": "none",
        "x-cache-control": "public, max-age=300",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Measured uptime and latency",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "The limit of the window that is closest to being exhausted.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in that window. Omitted when the reported window is a per-minute window, because the limiter that enforces it does not report a count.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "When that window ends, in Unix seconds.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Policy": {
                "description": "The policy that counted this request, or \"unavailable\" when the counter store could not be reached.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json; charset=utf-8": {
                "schema": {
                  "$ref": "#/components/schemas/StatusResponse"
                },
                "example": {
                  "generated_at": "2026-09-05T14:02:11Z",
                  "available": true,
                  "window": {
                    "short_hours": 24,
                    "long_days": 30
                  },
                  "overall": {
                    "uptime_24h": 99.98,
                    "uptime_30d": 99.94,
                    "p50_ms": 34,
                    "p95_ms": 71,
                    "checks_24h": 864
                  },
                  "targets": [
                    {
                      "target": "https://whatsmyip.fyi/json",
                      "label": "/json",
                      "kind": "edge",
                      "regions": [
                        {
                          "region": "TLL",
                          "uptime_24h": 99.98,
                          "uptime_30d": 99.94,
                          "p50_ms": 34,
                          "p95_ms": 71,
                          "checks_24h": 288,
                          "checks_30d": 8640,
                          "last_checked_at": "2026-09-05T14:00:00Z",
                          "last_ok": true
                        }
                      ]
                    }
                  ],
                  "source": "whatsmyip.fyi"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/v1/dnsleak/{session}": {
      "get": {
        "tags": [
          "meta"
        ],
        "operationId": "getV1DnsLeak",
        "summary": "DNS leak session results",
        "description": "The resolvers that queried the authoritative server for one session token. Planned, not shipped. The route answers 404 until the authoritative responder is live, and it appears here so that the shape is settled before anything depends on it.",
        "deprecated": false,
        "x-status": "planned",
        "x-rate-limit-class": "lookup",
        "x-cache-control": "private, no-store",
        "parameters": [
          {
            "name": "session",
            "in": "path",
            "required": true,
            "description": "The session token handed out when the test started. Sessions are discarded after ten minutes.",
            "schema": {
              "type": "string"
            },
            "example": "a1b2c3d4"
          }
        ],
        "responses": {
          "200": {
            "description": "DNS leak session results",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "The limit of the window that is closest to being exhausted.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in that window. Omitted when the reported window is a per-minute window, because the limiter that enforces it does not report a count.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "When that window ends, in Unix seconds.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Policy": {
                "description": "The policy that counted this request, or \"unavailable\" when the counter store could not be reached.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json; charset=utf-8": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error": "not_implemented",
                  "message": "The DNS leak session API is not live yet. See https://whatsmyip.fyi/dns-leak-test.",
                  "status": 404
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "IpReport": {
        "description": "The report for one address. Identical for /json, /api/v1/ip and the lookup base. hostname and privacy are null unless enrichment was requested and available.",
        "type": "object",
        "properties": {
          "ip": {
            "type": "string"
          },
          "version": {
            "anyOf": [
              {
                "type": "number",
                "const": 4
              },
              {
                "type": "number",
                "const": 6
              }
            ]
          },
          "hostname": {
            "type": [
              "string",
              "null"
            ]
          },
          "city": {
            "type": [
              "string",
              "null"
            ]
          },
          "region": {
            "type": [
              "string",
              "null"
            ]
          },
          "region_code": {
            "type": [
              "string",
              "null"
            ]
          },
          "country": {
            "type": [
              "string",
              "null"
            ]
          },
          "country_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "continent": {
            "type": [
              "string",
              "null"
            ]
          },
          "postal": {
            "type": [
              "string",
              "null"
            ]
          },
          "loc": {
            "type": [
              "string",
              "null"
            ]
          },
          "timezone": {
            "type": [
              "string",
              "null"
            ]
          },
          "local_time": {
            "type": [
              "string",
              "null"
            ]
          },
          "isp": {
            "type": [
              "string",
              "null"
            ]
          },
          "asn": {
            "type": [
              "number",
              "null"
            ]
          },
          "as_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "as_domain": {
            "type": [
              "string",
              "null"
            ]
          },
          "rir": {
            "type": "string",
            "enum": [
              "ARIN",
              "RIPE",
              "APNIC",
              "LACNIC",
              "AFRINIC",
              "IANA",
              "UNKNOWN"
            ]
          },
          "connection_type": {
            "type": "string",
            "enum": [
              "residential",
              "mobile",
              "business",
              "hosting",
              "education",
              "government",
              "unknown"
            ]
          },
          "privacy": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "vpn": {
                    "type": "boolean"
                  },
                  "proxy": {
                    "type": "boolean"
                  },
                  "tor": {
                    "type": "boolean"
                  },
                  "hosting": {
                    "type": "boolean"
                  },
                  "relay": {
                    "type": "boolean"
                  },
                  "source": {
                    "type": "string"
                  },
                  "checked_at": {
                    "type": "string"
                  }
                },
                "required": [
                  "vpn",
                  "proxy",
                  "tor",
                  "hosting",
                  "relay",
                  "source",
                  "checked_at"
                ],
                "additionalProperties": false
              },
              {
                "type": "null"
              }
            ]
          },
          "network": {
            "type": "object",
            "properties": {
              "protocol": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "tls": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "rtt_ms": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "edge": {
                "type": [
                  "string",
                  "null"
                ]
              }
            },
            "required": [
              "protocol",
              "tls",
              "rtt_ms",
              "edge"
            ],
            "additionalProperties": false
          },
          "user_agent": {
            "type": [
              "string",
              "null"
            ]
          },
          "accepts_language": {
            "type": [
              "string",
              "null"
            ]
          },
          "geo_accuracy": {
            "type": "string",
            "enum": [
              "approximate",
              "country-only"
            ]
          },
          "checked_at": {
            "type": "string"
          },
          "source": {
            "type": "string",
            "const": "whatsmyip.fyi"
          }
        },
        "required": [
          "ip",
          "version",
          "hostname",
          "city",
          "region",
          "region_code",
          "country",
          "country_name",
          "continent",
          "postal",
          "loc",
          "timezone",
          "local_time",
          "isp",
          "asn",
          "as_name",
          "as_domain",
          "rir",
          "connection_type",
          "privacy",
          "network",
          "user_agent",
          "accepts_language",
          "geo_accuracy",
          "checked_at",
          "source"
        ],
        "additionalProperties": false
      },
      "LookupResponse": {
        "description": "An IpReport for a target other than the caller, plus the RFC classification and an optional RDAP summary.",
        "type": "object",
        "properties": {
          "ip": {
            "type": "string"
          },
          "version": {
            "anyOf": [
              {
                "type": "number",
                "const": 4
              },
              {
                "type": "number",
                "const": 6
              }
            ]
          },
          "hostname": {
            "type": [
              "string",
              "null"
            ]
          },
          "city": {
            "type": [
              "string",
              "null"
            ]
          },
          "region": {
            "type": [
              "string",
              "null"
            ]
          },
          "region_code": {
            "type": [
              "string",
              "null"
            ]
          },
          "country": {
            "type": [
              "string",
              "null"
            ]
          },
          "country_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "continent": {
            "type": [
              "string",
              "null"
            ]
          },
          "postal": {
            "type": [
              "string",
              "null"
            ]
          },
          "loc": {
            "type": [
              "string",
              "null"
            ]
          },
          "timezone": {
            "type": [
              "string",
              "null"
            ]
          },
          "local_time": {
            "type": [
              "string",
              "null"
            ]
          },
          "isp": {
            "type": [
              "string",
              "null"
            ]
          },
          "asn": {
            "type": [
              "number",
              "null"
            ]
          },
          "as_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "as_domain": {
            "type": [
              "string",
              "null"
            ]
          },
          "rir": {
            "type": "string",
            "enum": [
              "ARIN",
              "RIPE",
              "APNIC",
              "LACNIC",
              "AFRINIC",
              "IANA",
              "UNKNOWN"
            ]
          },
          "connection_type": {
            "type": "string",
            "enum": [
              "residential",
              "mobile",
              "business",
              "hosting",
              "education",
              "government",
              "unknown"
            ]
          },
          "privacy": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "vpn": {
                    "type": "boolean"
                  },
                  "proxy": {
                    "type": "boolean"
                  },
                  "tor": {
                    "type": "boolean"
                  },
                  "hosting": {
                    "type": "boolean"
                  },
                  "relay": {
                    "type": "boolean"
                  },
                  "source": {
                    "type": "string"
                  },
                  "checked_at": {
                    "type": "string"
                  }
                },
                "required": [
                  "vpn",
                  "proxy",
                  "tor",
                  "hosting",
                  "relay",
                  "source",
                  "checked_at"
                ],
                "additionalProperties": false
              },
              {
                "type": "null"
              }
            ]
          },
          "network": {
            "type": "object",
            "properties": {
              "protocol": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "tls": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "rtt_ms": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "edge": {
                "type": [
                  "string",
                  "null"
                ]
              }
            },
            "required": [
              "protocol",
              "tls",
              "rtt_ms",
              "edge"
            ],
            "additionalProperties": false
          },
          "user_agent": {
            "type": [
              "string",
              "null"
            ]
          },
          "accepts_language": {
            "type": [
              "string",
              "null"
            ]
          },
          "geo_accuracy": {
            "type": "string",
            "enum": [
              "approximate",
              "country-only"
            ]
          },
          "checked_at": {
            "type": "string"
          },
          "source": {
            "type": "string",
            "const": "whatsmyip.fyi"
          },
          "classification": {
            "type": "object",
            "properties": {
              "kind": {
                "type": "string",
                "enum": [
                  "public",
                  "private",
                  "loopback",
                  "link-local",
                  "cgnat",
                  "multicast",
                  "broadcast",
                  "unspecified",
                  "documentation",
                  "benchmarking",
                  "reserved",
                  "6to4",
                  "teredo",
                  "unique-local",
                  "ipv4-mapped",
                  "ipv4-translated",
                  "discard",
                  "ietf-protocol"
                ]
              },
              "rfc": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "description": {
                "type": "string"
              },
              "routable": {
                "type": "boolean"
              }
            },
            "required": [
              "kind",
              "rfc",
              "description",
              "routable"
            ],
            "additionalProperties": false
          },
          "rdap": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "handle": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "name": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "type": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "country": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "start_address": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "end_address": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "cidr": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "registry": {
                    "type": "string",
                    "enum": [
                      "ARIN",
                      "RIPE",
                      "APNIC",
                      "LACNIC",
                      "AFRINIC",
                      "IANA",
                      "UNKNOWN"
                    ]
                  },
                  "registered": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "updated": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "status": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "abuse_email": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "entities": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "handle": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "role": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "name": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "email": {
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "handle",
                        "role",
                        "name",
                        "email"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "source": {
                    "type": "string"
                  }
                },
                "required": [
                  "handle",
                  "name",
                  "type",
                  "country",
                  "start_address",
                  "end_address",
                  "cidr",
                  "registry",
                  "registered",
                  "updated",
                  "status",
                  "abuse_email",
                  "entities",
                  "source"
                ],
                "additionalProperties": false
              },
              {
                "type": "null"
              }
            ]
          },
          "reverse": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "hostnames": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "forward_confirmed": {
                    "type": [
                      "boolean",
                      "null"
                    ]
                  }
                },
                "required": [
                  "hostnames",
                  "forward_confirmed"
                ],
                "additionalProperties": false
              },
              {
                "type": "null"
              }
            ]
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "field": {
                  "type": "string"
                },
                "provider": {
                  "type": "string"
                },
                "attribution": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              },
              "required": [
                "field",
                "provider",
                "attribution"
              ],
              "additionalProperties": false
            }
          }
        },
        "required": [
          "ip",
          "version",
          "hostname",
          "city",
          "region",
          "region_code",
          "country",
          "country_name",
          "continent",
          "postal",
          "loc",
          "timezone",
          "local_time",
          "isp",
          "asn",
          "as_name",
          "as_domain",
          "rir",
          "connection_type",
          "privacy",
          "network",
          "user_agent",
          "accepts_language",
          "geo_accuracy",
          "checked_at",
          "source",
          "classification"
        ],
        "additionalProperties": false
      },
      "DnsResponse": {
        "description": "One answer per resolver. Disagreements are returned rather than reconciled.",
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "ascii_name": {
            "type": "string"
          },
          "type": {
            "type": "string"
          },
          "answers": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "resolver": {
                  "type": "string"
                },
                "status": {
                  "type": "number"
                },
                "ad": {
                  "type": "boolean"
                },
                "records": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "name": {
                        "type": "string"
                      },
                      "type": {
                        "type": "string"
                      },
                      "ttl": {
                        "type": "number"
                      },
                      "data": {
                        "type": "string"
                      }
                    },
                    "required": [
                      "name",
                      "type",
                      "ttl",
                      "data"
                    ],
                    "additionalProperties": false
                  }
                },
                "error": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              },
              "required": [
                "resolver",
                "status",
                "ad",
                "records",
                "error"
              ],
              "additionalProperties": false
            }
          },
          "agree": {
            "type": "boolean"
          },
          "dnssec": {
            "type": "boolean"
          },
          "checked_at": {
            "type": "string"
          },
          "source": {
            "type": "string",
            "const": "whatsmyip.fyi"
          }
        },
        "required": [
          "name",
          "ascii_name",
          "type",
          "answers",
          "agree",
          "dnssec",
          "checked_at",
          "source"
        ],
        "additionalProperties": false
      },
      "RdapResponse": {
        "description": "A normalised RDAP record with the raw registry payload.",
        "type": "object",
        "properties": {
          "query": {
            "type": "string"
          },
          "kind": {
            "type": "string",
            "enum": [
              "ip",
              "domain",
              "asn"
            ]
          },
          "summary": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "handle": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "name": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "type": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "country": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "start_address": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "end_address": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "cidr": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "registry": {
                    "type": "string",
                    "enum": [
                      "ARIN",
                      "RIPE",
                      "APNIC",
                      "LACNIC",
                      "AFRINIC",
                      "IANA",
                      "UNKNOWN"
                    ]
                  },
                  "registered": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "updated": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "status": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "abuse_email": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "entities": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "handle": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "role": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "name": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "email": {
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "handle",
                        "role",
                        "name",
                        "email"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "source": {
                    "type": "string"
                  }
                },
                "required": [
                  "handle",
                  "name",
                  "type",
                  "country",
                  "start_address",
                  "end_address",
                  "cidr",
                  "registry",
                  "registered",
                  "updated",
                  "status",
                  "abuse_email",
                  "entities",
                  "source"
                ],
                "additionalProperties": false
              },
              {
                "type": "null"
              }
            ]
          },
          "raw": {
            "anyOf": [
              {},
              {
                "type": "null"
              }
            ]
          },
          "cached": {
            "type": "boolean"
          },
          "checked_at": {
            "type": "string"
          },
          "source": {
            "type": "string",
            "const": "whatsmyip.fyi"
          }
        },
        "required": [
          "query",
          "kind",
          "summary",
          "raw",
          "cached",
          "checked_at",
          "source"
        ],
        "additionalProperties": false
      },
      "ReverseDnsResponse": {
        "description": "PTR names with a forward-confirmed check.",
        "type": "object",
        "properties": {
          "ip": {
            "type": "string"
          },
          "version": {
            "anyOf": [
              {
                "type": "number",
                "const": 4
              },
              {
                "type": "number",
                "const": 6
              }
            ]
          },
          "arpa": {
            "type": "string"
          },
          "hostnames": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "forward_confirmed": {
            "type": "boolean"
          },
          "forward_addresses": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "checked_at": {
            "type": "string"
          },
          "source": {
            "type": "string",
            "const": "whatsmyip.fyi"
          }
        },
        "required": [
          "ip",
          "version",
          "arpa",
          "hostnames",
          "forward_confirmed",
          "forward_addresses",
          "checked_at",
          "source"
        ],
        "additionalProperties": false
      },
      "BlacklistResponse": {
        "description": "One row per attributed public blocklist.",
        "type": "object",
        "properties": {
          "ip": {
            "type": "string"
          },
          "version": {
            "anyOf": [
              {
                "type": "number",
                "const": 4
              },
              {
                "type": "number",
                "const": 6
              }
            ]
          },
          "listed_count": {
            "type": "number"
          },
          "total_count": {
            "type": "number"
          },
          "results": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "list": {
                  "type": "string"
                },
                "zone": {
                  "type": "string"
                },
                "listed": {
                  "type": "boolean"
                },
                "codes": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                },
                "reason": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "lookup_url": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "error": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              },
              "required": [
                "list",
                "zone",
                "listed",
                "codes",
                "reason",
                "lookup_url",
                "error"
              ],
              "additionalProperties": false
            }
          },
          "checked_at": {
            "type": "string"
          },
          "source": {
            "type": "string",
            "const": "whatsmyip.fyi"
          }
        },
        "required": [
          "ip",
          "version",
          "listed_count",
          "total_count",
          "results",
          "checked_at",
          "source"
        ],
        "additionalProperties": false
      },
      "MxResponse": {
        "description": "Mail records with SPF lookup counting and DMARC policy parsing.",
        "type": "object",
        "properties": {
          "domain": {
            "type": "string"
          },
          "ascii_domain": {
            "type": "string"
          },
          "mx": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "host": {
                  "type": "string"
                },
                "preference": {
                  "type": "number"
                },
                "ttl": {
                  "type": "number"
                }
              },
              "required": [
                "host",
                "preference",
                "ttl"
              ],
              "additionalProperties": false
            }
          },
          "spf": {
            "type": "object",
            "properties": {
              "found": {
                "type": "boolean"
              },
              "record": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "mechanisms": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "qualifier": {
                      "type": "string"
                    },
                    "mechanism": {
                      "type": "string"
                    },
                    "value": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "counts_toward_limit": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "qualifier",
                    "mechanism",
                    "value",
                    "counts_toward_limit"
                  ],
                  "additionalProperties": false
                }
              },
              "lookup_count": {
                "type": "number"
              },
              "lookup_limit": {
                "type": "number"
              },
              "exceeds_limit": {
                "type": "boolean"
              },
              "all": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "errors": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            },
            "required": [
              "found",
              "record",
              "mechanisms",
              "lookup_count",
              "lookup_limit",
              "exceeds_limit",
              "all",
              "errors"
            ],
            "additionalProperties": false
          },
          "dmarc": {
            "type": "object",
            "properties": {
              "found": {
                "type": "boolean"
              },
              "record": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "policy": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "subdomain_policy": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "percent": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "rua": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "ruf": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "errors": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            },
            "required": [
              "found",
              "record",
              "policy",
              "subdomain_policy",
              "percent",
              "rua",
              "ruf",
              "errors"
            ],
            "additionalProperties": false
          },
          "dkim": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "selector": {
                    "type": "string"
                  },
                  "name": {
                    "type": "string"
                  },
                  "found": {
                    "type": "boolean"
                  },
                  "record": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "key_type": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "flags": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "revoked": {
                    "type": "boolean"
                  },
                  "valid": {
                    "type": "boolean"
                  },
                  "errors": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                },
                "required": [
                  "selector",
                  "name",
                  "found",
                  "record",
                  "key_type",
                  "flags",
                  "revoked",
                  "valid",
                  "errors"
                ],
                "additionalProperties": false
              },
              {
                "type": "null"
              }
            ]
          },
          "verdicts": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "area": {
                  "type": "string"
                },
                "level": {
                  "type": "string",
                  "enum": [
                    "ok",
                    "warn",
                    "bad",
                    "info"
                  ]
                },
                "headline": {
                  "type": "string"
                },
                "meaning": {
                  "type": "string"
                }
              },
              "required": [
                "area",
                "level",
                "headline",
                "meaning"
              ],
              "additionalProperties": false
            }
          },
          "checked_at": {
            "type": "string"
          },
          "source": {
            "type": "string",
            "const": "whatsmyip.fyi"
          }
        },
        "required": [
          "domain",
          "ascii_domain",
          "mx",
          "spf",
          "dmarc",
          "dkim",
          "verdicts",
          "checked_at",
          "source"
        ],
        "additionalProperties": false
      },
      "SslResponse": {
        "description": "The certificate chain a host presents on port 443, decoded, with the hostname match, the expiry band and the plain HTTPS reading taken alongside it.",
        "type": "object",
        "properties": {
          "host": {
            "type": "string"
          },
          "ascii_host": {
            "type": "string"
          },
          "port": {
            "type": "number",
            "const": 443
          },
          "addresses": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "address": {
                  "type": "string"
                },
                "family": {
                  "type": "string",
                  "enum": [
                    "IPv4",
                    "IPv6"
                  ]
                }
              },
              "required": [
                "address",
                "family"
              ],
              "additionalProperties": false
            }
          },
          "connected_address": {
            "type": [
              "string",
              "null"
            ]
          },
          "certificate": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "subject": {
                    "type": "string"
                  },
                  "subject_common_name": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "issuer": {
                    "type": "string"
                  },
                  "issuer_common_name": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "issuer_organization": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "serial": {
                    "type": "string"
                  },
                  "version": {
                    "type": "number"
                  },
                  "not_before": {
                    "type": "string"
                  },
                  "not_after": {
                    "type": "string"
                  },
                  "days_remaining": {
                    "type": "number"
                  },
                  "expiry_band": {
                    "type": "string",
                    "enum": [
                      "expired",
                      "critical",
                      "soon",
                      "ok"
                    ]
                  },
                  "lifetime_days": {
                    "type": "number"
                  },
                  "sans": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "san_ips": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "key": {
                    "type": "object",
                    "properties": {
                      "algorithm": {
                        "type": "string"
                      },
                      "bits": {
                        "type": [
                          "number",
                          "null"
                        ]
                      },
                      "curve": {
                        "type": [
                          "string",
                          "null"
                        ]
                      }
                    },
                    "required": [
                      "algorithm",
                      "bits",
                      "curve"
                    ],
                    "additionalProperties": false
                  },
                  "signature_algorithm": {
                    "type": "string"
                  },
                  "is_certificate_authority": {
                    "type": "boolean"
                  },
                  "self_issued": {
                    "type": "boolean"
                  },
                  "extended_key_usage": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "ocsp_responders": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "ca_issuers": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "fingerprint_sha256": {
                    "type": "string"
                  }
                },
                "required": [
                  "subject",
                  "subject_common_name",
                  "issuer",
                  "issuer_common_name",
                  "issuer_organization",
                  "serial",
                  "version",
                  "not_before",
                  "not_after",
                  "days_remaining",
                  "expiry_band",
                  "lifetime_days",
                  "sans",
                  "san_ips",
                  "key",
                  "signature_algorithm",
                  "is_certificate_authority",
                  "self_issued",
                  "extended_key_usage",
                  "ocsp_responders",
                  "ca_issuers",
                  "fingerprint_sha256"
                ],
                "additionalProperties": false
              },
              {
                "type": "null"
              }
            ]
          },
          "chain": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "position": {
                  "type": "number"
                },
                "subject_common_name": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "issuer_common_name": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "is_certificate_authority": {
                  "type": "boolean"
                },
                "not_after": {
                  "type": "string"
                },
                "days_remaining": {
                  "type": "number"
                },
                "key": {
                  "type": "object",
                  "properties": {
                    "algorithm": {
                      "type": "string"
                    },
                    "bits": {
                      "type": [
                        "number",
                        "null"
                      ]
                    },
                    "curve": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "algorithm",
                    "bits",
                    "curve"
                  ],
                  "additionalProperties": false
                },
                "signature_algorithm": {
                  "type": "string"
                },
                "fingerprint_sha256": {
                  "type": "string"
                }
              },
              "required": [
                "position",
                "subject_common_name",
                "issuer_common_name",
                "is_certificate_authority",
                "not_after",
                "days_remaining",
                "key",
                "signature_algorithm",
                "fingerprint_sha256"
              ],
              "additionalProperties": false
            }
          },
          "chain_length": {
            "type": "number"
          },
          "hostname_match": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "matched": {
                    "type": "boolean"
                  },
                  "matched_name": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "checked_names": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "used_common_name": {
                    "type": "boolean"
                  }
                },
                "required": [
                  "matched",
                  "matched_name",
                  "checked_names",
                  "used_common_name"
                ],
                "additionalProperties": false
              },
              {
                "type": "null"
              }
            ]
          },
          "https": {
            "type": "object",
            "properties": {
              "reachable": {
                "type": "boolean"
              },
              "method": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "status": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "location": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "strict_transport_security": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "alt_svc": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "server": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "error": {
                "type": [
                  "string",
                  "null"
                ]
              }
            },
            "required": [
              "reachable",
              "method",
              "status",
              "location",
              "strict_transport_security",
              "alt_svc",
              "server",
              "error"
            ],
            "additionalProperties": false
          },
          "probe": {
            "type": "object",
            "properties": {
              "certificate_read": {
                "type": "boolean"
              },
              "method": {
                "type": "string",
                "enum": [
                  "tls12-clienthello",
                  "none"
                ]
              },
              "negotiated_version": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "cipher_suite": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "alert": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "error": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "elapsed_ms": {
                "type": "number"
              },
              "note": {
                "type": "string"
              }
            },
            "required": [
              "certificate_read",
              "method",
              "negotiated_version",
              "cipher_suite",
              "alert",
              "error",
              "elapsed_ms",
              "note"
            ],
            "additionalProperties": false
          },
          "verdicts": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "area": {
                  "type": "string"
                },
                "level": {
                  "type": "string",
                  "enum": [
                    "ok",
                    "warn",
                    "bad",
                    "info"
                  ]
                },
                "headline": {
                  "type": "string"
                },
                "meaning": {
                  "type": "string"
                }
              },
              "required": [
                "area",
                "level",
                "headline",
                "meaning"
              ],
              "additionalProperties": false
            }
          },
          "checked_at": {
            "type": "string"
          },
          "source": {
            "type": "string",
            "const": "whatsmyip.fyi"
          }
        },
        "required": [
          "host",
          "ascii_host",
          "port",
          "addresses",
          "connected_address",
          "certificate",
          "chain",
          "chain_length",
          "hostname_match",
          "https",
          "probe",
          "verdicts",
          "checked_at",
          "source"
        ],
        "additionalProperties": false
      },
      "HeadersResponse": {
        "description": "The request headers as received, with credentials redacted.",
        "type": "object",
        "properties": {
          "headers": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "name": {
                  "type": "string"
                },
                "value": {
                  "type": "string"
                },
                "redacted": {
                  "type": "boolean"
                },
                "explanation": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              },
              "required": [
                "name",
                "value",
                "redacted",
                "explanation"
              ],
              "additionalProperties": false
            }
          },
          "method": {
            "type": "string"
          },
          "protocol": {
            "type": [
              "string",
              "null"
            ]
          },
          "tls": {
            "type": [
              "string",
              "null"
            ]
          },
          "checked_at": {
            "type": "string"
          },
          "source": {
            "type": "string",
            "const": "whatsmyip.fyi"
          }
        },
        "required": [
          "headers",
          "method",
          "protocol",
          "tls",
          "checked_at",
          "source"
        ],
        "additionalProperties": false
      },
      "UaResponse": {
        "description": "A parsed user agent string.",
        "type": "object",
        "properties": {
          "user_agent": {
            "type": "string"
          },
          "browser": {
            "type": "object",
            "properties": {
              "name": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "version": {
                "type": [
                  "string",
                  "null"
                ]
              }
            },
            "required": [
              "name",
              "version"
            ],
            "additionalProperties": false
          },
          "engine": {
            "type": "object",
            "properties": {
              "name": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "version": {
                "type": [
                  "string",
                  "null"
                ]
              }
            },
            "required": [
              "name",
              "version"
            ],
            "additionalProperties": false
          },
          "os": {
            "type": "object",
            "properties": {
              "name": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "version": {
                "type": [
                  "string",
                  "null"
                ]
              }
            },
            "required": [
              "name",
              "version"
            ],
            "additionalProperties": false
          },
          "device": {
            "type": "string",
            "enum": [
              "desktop",
              "mobile",
              "tablet",
              "bot",
              "cli",
              "unknown"
            ]
          },
          "bot": {
            "type": "boolean"
          },
          "cli": {
            "type": "boolean"
          },
          "checked_at": {
            "type": "string"
          },
          "source": {
            "type": "string",
            "const": "whatsmyip.fyi"
          }
        },
        "required": [
          "user_agent",
          "browser",
          "engine",
          "os",
          "device",
          "bot",
          "cli",
          "checked_at",
          "source"
        ],
        "additionalProperties": false
      },
      "StatusResponse": {
        "description": "Measured uptime and latency per target and region.",
        "type": "object",
        "properties": {
          "generated_at": {
            "type": "string"
          },
          "available": {
            "type": "boolean"
          },
          "window": {
            "type": "object",
            "properties": {
              "short_hours": {
                "type": "number"
              },
              "long_days": {
                "type": "number"
              }
            },
            "required": [
              "short_hours",
              "long_days"
            ],
            "additionalProperties": false
          },
          "overall": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "uptime_24h": {
                    "type": [
                      "number",
                      "null"
                    ]
                  },
                  "uptime_30d": {
                    "type": [
                      "number",
                      "null"
                    ]
                  },
                  "p50_ms": {
                    "type": [
                      "number",
                      "null"
                    ]
                  },
                  "p95_ms": {
                    "type": [
                      "number",
                      "null"
                    ]
                  },
                  "checks_24h": {
                    "type": "number"
                  }
                },
                "required": [
                  "uptime_24h",
                  "uptime_30d",
                  "p50_ms",
                  "p95_ms",
                  "checks_24h"
                ],
                "additionalProperties": false
              },
              {
                "type": "null"
              }
            ]
          },
          "targets": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "target": {
                  "type": "string"
                },
                "label": {
                  "type": "string"
                },
                "kind": {
                  "type": "string",
                  "enum": [
                    "edge",
                    "enrichment"
                  ]
                },
                "regions": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "region": {
                        "type": "string"
                      },
                      "uptime_24h": {
                        "type": [
                          "number",
                          "null"
                        ]
                      },
                      "uptime_30d": {
                        "type": [
                          "number",
                          "null"
                        ]
                      },
                      "p50_ms": {
                        "type": [
                          "number",
                          "null"
                        ]
                      },
                      "p95_ms": {
                        "type": [
                          "number",
                          "null"
                        ]
                      },
                      "checks_24h": {
                        "type": "number"
                      },
                      "checks_30d": {
                        "type": "number"
                      },
                      "last_checked_at": {
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "last_ok": {
                        "type": [
                          "boolean",
                          "null"
                        ]
                      }
                    },
                    "required": [
                      "region",
                      "uptime_24h",
                      "uptime_30d",
                      "p50_ms",
                      "p95_ms",
                      "checks_24h",
                      "checks_30d",
                      "last_checked_at",
                      "last_ok"
                    ],
                    "additionalProperties": false
                  }
                }
              },
              "required": [
                "target",
                "label",
                "kind",
                "regions"
              ],
              "additionalProperties": false
            }
          },
          "source": {
            "type": "string",
            "const": "whatsmyip.fyi"
          }
        },
        "required": [
          "generated_at",
          "available",
          "window",
          "overall",
          "targets",
          "source"
        ],
        "additionalProperties": false
      },
      "ErrorResponse": {
        "description": "Every error body on every endpoint uses this shape.",
        "type": "object",
        "properties": {
          "error": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "status": {
            "type": "number"
          }
        },
        "required": [
          "error",
          "message",
          "status"
        ],
        "additionalProperties": false
      }
    },
    "responses": {
      "BadRequest": {
        "description": "The request was malformed. The message names the parameter at fault.",
        "content": {
          "application/json; charset=utf-8": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "NotFound": {
        "description": "No such route, or no such record for the target given.",
        "content": {
          "application/json; charset=utf-8": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "RateLimited": {
        "description": "Over the published limit. Retry-After holds the wait in seconds and it is not advisory.",
        "headers": {
          "X-RateLimit-Limit": {
            "description": "The limit of the window that is closest to being exhausted.",
            "schema": {
              "type": "integer"
            }
          },
          "X-RateLimit-Remaining": {
            "description": "Requests left in that window. Omitted when the reported window is a per-minute window, because the limiter that enforces it does not report a count.",
            "schema": {
              "type": "integer"
            }
          },
          "X-RateLimit-Reset": {
            "description": "When that window ends, in Unix seconds.",
            "schema": {
              "type": "integer"
            }
          },
          "X-RateLimit-Policy": {
            "description": "The policy that counted this request, or \"unavailable\" when the counter store could not be reached.",
            "schema": {
              "type": "string"
            }
          },
          "Retry-After": {
            "description": "Seconds to wait before retrying.",
            "schema": {
              "type": "integer"
            }
          }
        },
        "content": {
          "application/json; charset=utf-8": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      }
    }
  },
  "x-cors": {
    "Access-Control-Allow-Origin": "*",
    "Access-Control-Allow-Methods": "GET, HEAD, OPTIONS",
    "Access-Control-Allow-Headers": "Accept, Content-Type",
    "note": "A browser call reports the address of the visitor, not of your server, and spends quota per visitor."
  },
  "x-rate-limits": [
    {
      "surface": "/ip, /json, /ip.md, /api/v1/ip",
      "per_minute": "60",
      "per_day": "none",
      "escalation": "429 with Retry-After"
    },
    {
      "surface": "/api/v1/lookup, /api/v1/dns, /api/v1/rdap, /api/v1/reverse, /api/v1/blacklist, /api/v1/mx",
      "per_minute": "20",
      "per_day": "200",
      "escalation": "429, Turnstile after 50 per day"
    },
    {
      "surface": "Privacy enrichment (?full=1, ?privacy=1)",
      "per_minute": "none",
      "per_day": "20",
      "escalation": "Field returns null with a reason"
    },
    {
      "surface": "/api/v1/status, /status/badge.svg",
      "per_minute": "none",
      "per_day": "none",
      "escalation": "Cached for 5 minutes at the edge"
    }
  ],
  "x-changelog": [
    {
      "version": "1.0.0",
      "date": "2026-09-05",
      "changes": [
        "First published version of /api/v1. The requester endpoints /ip, /json and /ip.md are unchanged and are now described here.",
        "Added /api/v1/ip, /api/v1/lookup/{target}, /api/v1/dns, /api/v1/rdap, /api/v1/reverse/{ip}, /api/v1/blacklist/{ip}, /api/v1/mx, /api/v1/headers, /api/v1/ua and /api/v1/status.",
        "Published the OpenAPI 3.1 document at /api/openapi.json and the uptime badge at /status/badge.svg.",
        "/api/v1/dnsleak/{session} is reserved and documented as planned. It answers 404 until the authoritative responder ships."
      ]
    }
  ]
}
