{
  "openapi": "3.1.0",
  "info": {
    "title": "WhatIsMyIP.com API",
    "version": "2026-10-01",
    "description": "IP, network, DNS and router-login lookups for WhatIsMyIP.com members. JSON only.\n\n**Limits.** Each key has a rolling 24-hour limit: Starter 24, Pro 1,440, Expert 86,400 calls. The window rolls — a call made at 09:15 stops counting at 09:15 the next day; there is no midnight reset, and the allowance comes back one call at a time as old calls age out.\n\nWhat counts toward the limit (verified against the live API on 2026-10-01 by counting a key's usage before and after each request):\n\n| Request | Status | Counts |\n|---|---|---|\n| Successful call | 200 | Yes |\n| Bad input (e.g. a private address, an unknown record type) | 400 | Yes |\n| Nothing found on a valid route (e.g. an unknown router brand) | 404 | Yes |\n| Server error after the key was accepted | 5xx | Yes |\n| A path that is not an endpoint | 404 | No |\n| Missing or invalid key | 401 | No |\n| Disabled key | 403 | No |\n| Over the limit | 429 | No |\n| Browser preflight | OPTIONS | No |\n\nOver the limit you get 429. The Retry-After header is a number of seconds from now; the body's retryAfter is an absolute UTC timestamp. Both point at the moment one call frees up.\n\n**Errors** are {\"error\": \"…\"}: 400 bad input, 401 missing or invalid key, 403 disabled key, 404 nothing found, 429 limit reached.\n\n**Browsers.** Cross-origin requests are allowed from any origin, and the X-API-KEY header is permitted. Retry-After is readable from JavaScript. But a key in a public web page can be read by anyone who opens it — call the API from your own server if the key must stay private.\n\n**IPv4 and IPv6.** Routes marked x-callerAddress answer about the connection making the request. The IPv6-only host works only from a network with working IPv6; the IPv4-only host forces an IPv4 answer.",
    "contact": {
      "name": "WhatIsMyIP.com",
      "url": "https://www.whatismyip.com/contact-us/"
    },
    "x-lastReviewed": "2026-10-01",
    "x-changelog": [
      [
        "2026-10-01",
        "Success schemas for every route (location lookup, proxy check, IP-to-decimal, DNS lookup, router login), with types and which fields can be null. Proxy check documents both outcomes. The 429 response has a schema and explains its two retry values (Retry-After in seconds, retryAfter as a UTC timestamp) and that the allowance refills one call at a time. A table of which requests count toward the limit, verified against the live API. DNS lookup: the server parameter is now honored — answers come from the resolver named in the response. Before this fix, every answer came from our hosting provider's resolver whatever server was chosen. Control D is no longer offered (it does not answer queries from our servers); server=control_d returns 400. Router field tables: default_username and default_password are now described separately — the username is also filled for set-on-first-login and most per-device-label models; the password only for universal."
      ],
      [
        "2026-09-30",
        "The API key is checked before any lookup runs, so 400 and 404 answers now require a valid key and count toward the limit. Retry-After is readable from browser JavaScript. proxy_type_description now uses IP2Proxy's definitions (DCH = hosting, data center or CDN). Response field reference added. Blacklist check: four lists that could never report a listing were replaced (Spamhaus refuses queries from public resolvers; two lists no longer exist); a list that fails to answer now reads \"unavailable\" instead of \"not listed\"; SPFBL's \"not a mail server\" tag no longer counts as a listing; IPv6 addresses return 400 (these lists cover IPv4). Quick start with cURL, Python and JavaScript examples, a contents list and a troubleshooting section added to the reference."
      ],
      [
        "2026-09-29",
        "Reference generated from this OpenAPI description. Missing keys return 401 (was 400); private and reserved addresses return a clear 400; IPv6 accepted by hostname lookup; router routes return 404 when nothing matches."
      ]
    ]
  },
  "servers": [
    {
      "url": "https://wimi-api.whatismyip.com",
      "description": "Either protocol"
    },
    {
      "url": "https://wimi-api-v4.whatismyip.com",
      "description": "IPv4 only — forces caller-address routes to report IPv4"
    },
    {
      "url": "https://wimi-api-v6.whatismyip.com",
      "description": "IPv6 only — forces caller-address routes to report IPv6"
    }
  ],
  "paths": {
    "/ip": {
      "get": {
        "operationId": "ip",
        "summary": "Your public IP address",
        "description": "Returns the public IP address of the connection making the request. Called from a server, it returns the server's address. Use the IPv4 or IPv6 host to force a protocol (see [Hosts](#hosts)).",
        "x-callerAddress": true,
        "responses": {
          "200": {
            "description": "The caller's address",
            "content": {
              "application/json": {
                "example": {
                  "ip": "203.0.113.45"
                },
                "schema": {
                  "type": "object",
                  "properties": {
                    "ip": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "ip"
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/LimitReached"
          }
        },
        "security": [
          {
            "headerKey": []
          },
          {
            "queryKey": []
          }
        ],
        "x-fields": [
          [
            "ip",
            "string",
            "The public IPv4 or IPv6 address of the connection making the request."
          ]
        ]
      }
    },
    "/ip-address-lookup/{ip}": {
      "get": {
        "operationId": "ipAddressLookup",
        "summary": "Location and network details for an IP",
        "parameters": [
          {
            "name": "ip",
            "in": "path",
            "required": true,
            "description": "A public IPv4 or IPv6 address",
            "schema": {
              "type": "string",
              "examples": [
                "8.8.8.8",
                "2001:4860:4860::8888"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Location, ISP and ASN",
            "content": {
              "application/json": {
                "example": {
                  "country": "United States of America",
                  "city": "Mountain View",
                  "region": "California",
                  "postal_code": "94043",
                  "isp": "Google LLC",
                  "latitude": 37.38605,
                  "longitude": -122.08385,
                  "time_zone": "-07:00",
                  "asn": "15169",
                  "ip": "8.8.8.8"
                },
                "schema": {
                  "$ref": "#/components/schemas/IpLocation"
                }
              }
            }
          },
          "400": {
            "description": "Invalid IP address provided / Private and reserved IP addresses are not supported",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "e0": {
                    "value": {
                      "error": "Invalid IP address provided"
                    }
                  },
                  "e1": {
                    "value": {
                      "error": "Private and reserved IP addresses are not supported"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/LimitReached"
          }
        },
        "security": [
          {
            "headerKey": []
          },
          {
            "queryKey": []
          }
        ],
        "description": "Location, ISP and ASN from our IP database. Location is approximate — usually city level, and for mobile and VPN addresses it is often the network's location, not the person's. Example values are a snapshot taken when this reference was written; live answers change.",
        "x-fields": [
          [
            "ip",
            "string",
            "The address looked up."
          ],
          [
            "country",
            "string",
            "Country name."
          ],
          [
            "region",
            "string",
            "State, province or region."
          ],
          [
            "city",
            "string",
            "City."
          ],
          [
            "postal_code",
            "string",
            "Postal code; a string, since many are not numeric."
          ],
          [
            "latitude, longitude",
            "number",
            "Approximate coordinates of the city or network, not of a device."
          ],
          [
            "time_zone",
            "string",
            "UTC offset, e.g. \"-07:00\"."
          ],
          [
            "isp",
            "string",
            "The organization the address is registered to."
          ],
          [
            "asn",
            "string",
            "Autonomous system number, digits only, as a string."
          ],
          [
            "(any text field)",
            "string",
            "An unknown value is the string \"-\" — never null or empty. Example: postal_code is \"-\" in places without postal codes (Dubai, Hong Kong)."
          ]
        ]
      }
    },
    "/whois/{ip}": {
      "get": {
        "operationId": "whois",
        "summary": "Raw WHOIS record for an IP",
        "description": "Returns the registry's WHOIS text for the block, unparsed, in one field. Which registry answers depends on the address (8.8.8.8 → ARIN). Some addresses return only a referral (1.1.1.1 → IANA pointing to APNIC). Example values are a snapshot taken when this reference was written; live answers change.",
        "parameters": [
          {
            "name": "ip",
            "in": "path",
            "required": true,
            "description": "A public IPv4 or IPv6 address",
            "schema": {
              "type": "string",
              "examples": [
                "8.8.8.8",
                "2001:4860:4860::8888"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The WHOIS text",
            "content": {
              "application/json": {
                "example": {
                  "whois": "\n#\n# ARIN WHOIS data and services are subject to the Terms of Use\n# available at: https://www.arin.net/resources/registry/whois/tou/\n#\n# If you see inaccuracies in the results, please report at\n# https://www.arin.net/resources/registry/whois/inaccuracy_reporting/\n#\n# Copyright 1997-2026, American Registry for Internet Numbers, Ltd.\n#\n\n\n#\n# Query terms are ambiguous.  The query is assumed to be:\n#     \"n 8.8.8.8\"\n#\n#\n…"
                },
                "schema": {
                  "type": "object",
                  "properties": {
                    "whois": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "whois"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Invalid IP address provided / Private and reserved IP addresses are not supported",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "e0": {
                    "value": {
                      "error": "Invalid IP address provided"
                    }
                  },
                  "e1": {
                    "value": {
                      "error": "Private and reserved IP addresses are not supported"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/LimitReached"
          }
        },
        "security": [
          {
            "headerKey": []
          },
          {
            "queryKey": []
          }
        ],
        "x-fields": [
          [
            "whois",
            "string",
            "The registry's WHOIS text, unparsed. The example is shortened; the full text is returned."
          ]
        ]
      }
    },
    "/domain-blacklist/{host}": {
      "get": {
        "operationId": "domainBlacklist",
        "summary": "Check a domain or public IPv4 address against DNS blacklists",
        "description": "IPv4 only. A domain is resolved to its first IPv4 address, and that address is checked; a domain with several addresses is checked on one of them only, so check the others by IP. Each list answers \"listed\", \"not listed\", or \"unavailable\" when the list did not answer (timeout, error or a refused query) — an unavailable list has not checked the address. Every list is queried live: allow 5–10 seconds. The lists: SpamCop, PSBL, UCEPROTECT level 1, Mailspike, SPFBL, s5h, NordSpam, DroneBL, dan.me.uk Tor exits, ASCAMS and foobar.hu. SPFBL also tags ordinary web and home addresses as \"not a mail server\"; that tag is not a listing. Example values are a snapshot taken when this reference was written; live answers change.",
        "parameters": [
          {
            "name": "host",
            "in": "path",
            "required": true,
            "description": "A domain name or a public IPv4 address",
            "schema": {
              "type": "string",
              "examples": [
                "example.com",
                "8.8.8.8"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "One key per blacklist",
            "content": {
              "application/json": {
                "example": {
                  "bl.spamcop.net": "not listed",
                  "psbl.surriel.com": "not listed",
                  "dnsbl-1.uceprotect.net": "not listed",
                  "bl.mailspike.net": "not listed",
                  "dnsbl.spfbl.net": "not listed",
                  "all.s5h.net": "not listed",
                  "bl.nordspam.com": "not listed",
                  "dnsbl.dronebl.org": "not listed",
                  "tor.dan.me.uk": "not listed",
                  "dnsbl.ascams.com": "not listed",
                  "pofon.foobar.hu": "not listed"
                },
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "type": "string",
                    "enum": [
                      "listed",
                      "not listed",
                      "unavailable"
                    ]
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid host or ip provided / Blacklist checks cover IPv4 addresses only / Private or reserved IP addresses are not allowed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "e0": {
                    "value": {
                      "error": "Invalid host or ip provided"
                    }
                  },
                  "e1": {
                    "value": {
                      "error": "Blacklist checks cover IPv4 addresses only"
                    }
                  },
                  "e2": {
                    "value": {
                      "error": "Private or reserved IP addresses are not allowed"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/LimitReached"
          }
        },
        "security": [
          {
            "headerKey": []
          },
          {
            "queryKey": []
          }
        ],
        "x-fields": [
          [
            "<list name>",
            "string",
            "\"listed\", \"not listed\", or \"unavailable\" (the list did not answer, so the address was not checked by it). One key per list."
          ]
        ]
      }
    },
    "/hostname-lookup/{ip}": {
      "get": {
        "operationId": "hostnameLookup",
        "summary": "Reverse DNS (PTR) for an IP",
        "description": "IPv4 and IPv6. When the address has no PTR record, the address itself is returned as the hostname.",
        "parameters": [
          {
            "name": "ip",
            "in": "path",
            "required": true,
            "description": "A public IPv4 or IPv6 address",
            "schema": {
              "type": "string",
              "examples": [
                "8.8.8.8",
                "2001:4860:4860::8888"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The PTR hostname",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "hostname": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "hostname"
                  ]
                },
                "examples": {
                  "ipv4": {
                    "value": {
                      "hostname": "dns.google"
                    }
                  },
                  "ipv6": {
                    "value": {
                      "hostname": "dns.google"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid IP address provided / Private and reserved IP addresses are not supported",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "e0": {
                    "value": {
                      "error": "Invalid IP address provided"
                    }
                  },
                  "e1": {
                    "value": {
                      "error": "Private and reserved IP addresses are not supported"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/LimitReached"
          }
        },
        "security": [
          {
            "headerKey": []
          },
          {
            "queryKey": []
          }
        ],
        "x-fields": [
          [
            "hostname",
            "string",
            "The PTR hostname. When the address has no PTR record, the address itself is returned."
          ]
        ]
      }
    },
    "/proxy-check": {
      "get": {
        "operationId": "proxyCheckSelf",
        "summary": "Is your own connection a known proxy, VPN or data center?",
        "description": "Checks the address of the connection making the request. When the address is not in the proxy database the response is just {\"is_proxy\":\"no\"}.",
        "x-callerAddress": true,
        "responses": {
          "200": {
            "description": "Proxy classification of the caller's own address: listed (is_proxy \"yes\" with the classification) or not a known proxy (is_proxy \"no\" only)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProxyCheck"
                },
                "examples": {
                  "proxy": {
                    "value": {
                      "is_proxy": "yes",
                      "proxy_type": "DCH",
                      "proxy_type_description": "Hosting provider, data center or CDN",
                      "country_code": "US",
                      "country_name": "United States of America",
                      "proxy_range": [
                        "8.8.6.21/32",
                        "8.8.6.22/31",
                        "8.8.6.24/29",
                        "8.8.6.32/27"
                      ]
                    }
                  },
                  "notProxy": {
                    "value": {
                      "is_proxy": "no"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/LimitReached"
          }
        },
        "security": [
          {
            "headerKey": []
          },
          {
            "queryKey": []
          }
        ],
        "x-fields": [
          [
            "is_proxy",
            "string",
            "\"yes\" or \"no\". When \"no\", this is the only field."
          ],
          [
            "proxy_type",
            "string",
            "IP2Proxy code: VPN, TOR, PUB (public proxy), WEB (web proxy), DCH (hosting, data center or CDN), SES (search engine crawler), RES (residential proxy), CPN (consumer privacy network), EPN (enterprise private network)."
          ],
          [
            "proxy_type_description",
            "string",
            "The code in words."
          ],
          [
            "country_code, country_name",
            "string",
            "Where the proxy range is registered."
          ],
          [
            "proxy_range",
            "string[]",
            "The CIDR blocks of the matching range."
          ]
        ]
      }
    },
    "/proxy-check/{ip}": {
      "get": {
        "operationId": "proxyCheck",
        "summary": "Is an IP a known proxy, VPN or data center?",
        "description": "is_proxy is \"yes\" or \"no\". Coverage of consumer VPN networks is incomplete, so \"no\" means \"not in our database\", not \"certainly not a VPN\". The example's proxy_range is shortened to its first entries; the full list is returned.",
        "parameters": [
          {
            "name": "ip",
            "in": "path",
            "required": true,
            "description": "A public IPv4 or IPv6 address",
            "schema": {
              "type": "string",
              "examples": [
                "8.8.8.8",
                "2001:4860:4860::8888"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Proxy classification: listed (is_proxy \"yes\" with the classification) or not a known proxy (is_proxy \"no\" only)",
            "content": {
              "application/json": {
                "examples": {
                  "proxy": {
                    "value": {
                      "is_proxy": "yes",
                      "proxy_type": "DCH",
                      "proxy_type_description": "Hosting provider, data center or CDN",
                      "country_code": "US",
                      "country_name": "United States of America",
                      "proxy_range": [
                        "8.8.6.21/32",
                        "8.8.6.22/31",
                        "8.8.6.24/29",
                        "8.8.6.32/27"
                      ]
                    }
                  },
                  "notProxy": {
                    "value": {
                      "is_proxy": "no"
                    }
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ProxyCheck"
                }
              }
            }
          },
          "400": {
            "description": "Invalid IP address provided / Private and reserved IP addresses are not supported",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "e0": {
                    "value": {
                      "error": "Invalid IP address provided"
                    }
                  },
                  "e1": {
                    "value": {
                      "error": "Private and reserved IP addresses are not supported"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/LimitReached"
          }
        },
        "security": [
          {
            "headerKey": []
          },
          {
            "queryKey": []
          }
        ],
        "x-fields": [
          [
            "is_proxy",
            "string",
            "\"yes\" or \"no\". When \"no\", this is the only field."
          ],
          [
            "proxy_type",
            "string",
            "IP2Proxy code: VPN, TOR, PUB (public proxy), WEB (web proxy), DCH (hosting, data center or CDN), SES (search engine crawler), RES (residential proxy), CPN (consumer privacy network), EPN (enterprise private network)."
          ],
          [
            "proxy_type_description",
            "string",
            "The code in words."
          ],
          [
            "country_code, country_name",
            "string",
            "Where the proxy range is registered."
          ],
          [
            "proxy_range",
            "string[]",
            "The CIDR blocks of the matching range."
          ]
        ]
      }
    },
    "/server-headers/{server}": {
      "get": {
        "operationId": "serverHeaders",
        "summary": "HTTP response headers from a server",
        "description": "Pass a hostname or public IP — not a URL. We request http://<server>/ (plain HTTP, port 80) and return the headers of that first response. Redirects are not followed, so a site that moves visitors to HTTPS answers with its redirect (a 301 and a Location header). A server that does not answer within 10 seconds, refuses the connection, or has no HTTP service returns 400. Example values are a snapshot taken when this reference was written; live answers change.",
        "parameters": [
          {
            "name": "server",
            "in": "path",
            "required": true,
            "description": "Hostname or public IP (no scheme, no path)",
            "schema": {
              "type": "string",
              "examples": [
                "example.com"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Status line and headers",
            "content": {
              "application/json": {
                "example": {
                  "http_code": "HTTP/1.1 200 OK",
                  "Date": "Tue, 29 Sep 2026 21:13:22 GMT",
                  "Content-Type": "text/html; charset=utf-8",
                  "Transfer-Encoding": "chunked",
                  "Connection": "keep-alive",
                  "Server": "cloudflare",
                  "Last-Modified": "Mon, 28 Sep 2026 16:19:23 GMT",
                  "Allow": "GET, HEAD",
                  "Accept-Ranges": "bytes",
                  "Age": "1171",
                  "cf-cache-status": "HIT",
                  "CF-RAY": "a42dfdcbdb42efaa-IAD"
                },
                "schema": {
                  "type": "object",
                  "properties": {
                    "http_code": {
                      "type": "string"
                    }
                  },
                  "additionalProperties": {
                    "type": "string"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid host or ip provided / Could not retrieve headers from the specified server",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "e0": {
                    "value": {
                      "error": "Invalid host or ip provided"
                    }
                  },
                  "e1": {
                    "value": {
                      "error": "Could not retrieve headers from the specified server"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "e0": {
                    "value": {
                      "error": "Not found."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/LimitReached"
          }
        },
        "security": [
          {
            "headerKey": []
          },
          {
            "queryKey": []
          }
        ],
        "x-fields": [
          [
            "http_code",
            "string",
            "The status line, e.g. \"HTTP/1.1 301 Moved Permanently\"."
          ],
          [
            "<header name>",
            "string",
            "Every other key is a response header, as the server sent it."
          ]
        ]
      }
    },
    "/ipdecimal": {
      "get": {
        "operationId": "ipDecimalSelf",
        "summary": "Your IP address and its decimal form",
        "x-callerAddress": true,
        "responses": {
          "200": {
            "description": "Address and decimal",
            "content": {
              "application/json": {
                "example": {
                  "ip": "203.0.113.45",
                  "decimal": "3405803821"
                },
                "schema": {
                  "$ref": "#/components/schemas/IpDecimal"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/LimitReached"
          }
        },
        "security": [
          {
            "headerKey": []
          },
          {
            "queryKey": []
          }
        ],
        "x-fields": [
          [
            "ip",
            "string",
            "The address."
          ],
          [
            "decimal",
            "string",
            "The address as a decimal integer, as a string — IPv6 values exceed 64-bit integers."
          ]
        ]
      }
    },
    "/ipdecimal/{ip}": {
      "get": {
        "operationId": "ipDecimal",
        "summary": "An IP address as a decimal number",
        "description": "Any IPv4 or IPv6 address, private included. decimal is a string (IPv6 values exceed 64-bit integers).",
        "parameters": [
          {
            "name": "ip",
            "in": "path",
            "required": true,
            "description": "Any IPv4 or IPv6 address",
            "schema": {
              "type": "string",
              "examples": [
                "8.8.8.8",
                "2001:4860:4860::8888"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Address and decimal",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IpDecimal"
                },
                "examples": {
                  "ipv4": {
                    "value": {
                      "ip": "8.8.8.8",
                      "decimal": "134744072"
                    }
                  },
                  "ipv6": {
                    "value": {
                      "ip": "2001:4860:4860::8888",
                      "decimal": "42541956123769884636017138956568135816"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid IP address provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "e0": {
                    "value": {
                      "error": "Invalid IP address provided"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/LimitReached"
          }
        },
        "security": [
          {
            "headerKey": []
          },
          {
            "queryKey": []
          }
        ],
        "x-fields": [
          [
            "ip",
            "string",
            "The address."
          ],
          [
            "decimal",
            "string",
            "The address as a decimal integer, as a string — IPv6 values exceed 64-bit integers."
          ]
        ]
      }
    },
    "/dns-lookup/{host}": {
      "get": {
        "operationId": "dnsLookup",
        "summary": "DNS records for a domain",
        "description": "The top-level key is the resolver that answered. Without server, a resolver is picked at random. Each record type is an object whose value is a list, or the string \"no records found\". Names with underscores (such as _dmarc.example.com) are allowed; bare IP addresses are not. Example values are a snapshot taken when this reference was written; live answers change.",
        "parameters": [
          {
            "name": "host",
            "in": "path",
            "required": true,
            "description": "A domain name",
            "schema": {
              "type": "string",
              "examples": [
                "example.com",
                "_dmarc.google.com"
              ]
            }
          },
          {
            "name": "record",
            "in": "query",
            "required": false,
            "description": "One record type (case-insensitive). Omit for all six.",
            "schema": {
              "type": "string",
              "enum": [
                "ns",
                "a",
                "aaaa",
                "cname",
                "mx",
                "txt"
              ]
            }
          },
          {
            "name": "server",
            "in": "query",
            "required": false,
            "description": "Resolver to ask (case-insensitive). Omit for a random one.",
            "schema": {
              "type": "string",
              "enum": [
                "google",
                "cloudflare",
                "quad9",
                "opendns",
                "cleanbrowsing"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Records by type",
            "content": {
              "application/json": {
                "example": {
                  "cloudflare": [
                    {
                      "ns": [
                        "elliott.ns.cloudflare.com",
                        "hera.ns.cloudflare.com"
                      ]
                    },
                    {
                      "a": [
                        "172.66.147.243",
                        "104.20.23.154"
                      ]
                    },
                    {
                      "aaaa": [
                        "2606:4700:10::ac42:93f3",
                        "2606:4700:10::6814:179a"
                      ]
                    },
                    {
                      "mx": "no records found"
                    },
                    {
                      "cname": "no records found"
                    },
                    {
                      "txt": [
                        "_k2n1y4vw3qtb4skdx9e7dxt97qrmmq9",
                        "v=spf1 -all"
                      ]
                    }
                  ]
                },
                "schema": {
                  "$ref": "#/components/schemas/DnsLookup"
                }
              }
            }
          },
          "400": {
            "description": "Invalid host provided / Invalid DNS record type provided / Invalid DNS server provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "e0": {
                    "value": {
                      "error": "Invalid host provided"
                    }
                  },
                  "e1": {
                    "value": {
                      "error": "Invalid DNS record type provided"
                    }
                  },
                  "e2": {
                    "value": {
                      "error": "Invalid DNS server provided"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/LimitReached"
          }
        },
        "security": [
          {
            "headerKey": []
          },
          {
            "queryKey": []
          }
        ],
        "x-fields": [
          [
            "<resolver>",
            "object[]",
            "The single top-level key names the resolver that answered (google, cloudflare, quad9, opendns, cleanbrowsing)."
          ],
          [
            "ns, a, aaaa, cname, mx, txt",
            "string[] or string",
            "Each list item is one record type. Its value is an array of records, or the string \"no records found\" — check the type before iterating."
          ]
        ]
      }
    },
    "/router-login": {
      "get": {
        "operationId": "routerBrands",
        "summary": "Router brands with default login data",
        "description": "Start here: each brand's slug is the {brand} for the next two routes.",
        "responses": {
          "200": {
            "description": "Brands",
            "content": {
              "application/json": {
                "example": {
                  "data": [
                    {
                      "slug": "arris",
                      "name": "ARRIS SURFboard",
                      "support_url": "https://www.surfboard.com/support/resources/",
                      "default_login_url": "http://192.168.0.1",
                      "reset_pattern": "Hold the recessed Reset button on the back for about 15 seconds until the LEDs flash, then release; the gateway must be reconfigured afterwards.",
                      "profile_count": 3,
                      "model_count": 27
                    },
                    {
                      "slug": "asus",
                      "name": "ASUS",
                      "support_url": "https://www.asus.com/us/support/",
                      "default_login_url": "http://www.asusrouter.com",
                      "reset_pattern": "Hold the recessed Reset button for at least 5 seconds until the power LED starts to flash (ASUS FAQ 1005263).",
                      "profile_count": 2,
                      "model_count": 18
                    }
                  ]
                },
                "schema": {
                  "$ref": "#/components/schemas/RouterBrands"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/LimitReached"
          }
        },
        "security": [
          {
            "headerKey": []
          },
          {
            "queryKey": []
          }
        ],
        "x-fields": [
          [
            "data[]",
            "object[]",
            "One entry per brand: slug (use it as {brand}), name, support_url, default_login_url and reset_pattern (how to factory-reset)."
          ]
        ]
      }
    },
    "/router-login/{brand}": {
      "get": {
        "operationId": "routerBrand",
        "summary": "Default login profiles for one brand",
        "description": "Each profile lists the models it applies to; a model's model_slug is the {model} for /router-login/{brand}/{model}. These are the defaults a model ships with — not a reading of anyone's router, which may have been changed. A null default_password means we do not publish one (the router asks you to create it, or it is printed on the label) — it never means a blank password.",
        "parameters": [
          {
            "name": "brand",
            "in": "path",
            "required": true,
            "description": "Brand slug from /router-login",
            "schema": {
              "type": "string",
              "examples": [
                "netgear"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Profiles with their models",
            "content": {
              "application/json": {
                "example": {
                  "data": [
                    {
                      "brand": "NETGEAR",
                      "brand_slug": "netgear",
                      "profile_slug": "orbilogin-com-set-on-first-login",
                      "profile_name": "orbilogin.com · create a password on first login",
                      "gateway_ip": "192.168.1.1",
                      "login_url": "http://orbilogin.com",
                      "credential_type": "set-on-first-login",
                      "default_username": "admin",
                      "default_password": null,
                      "label_hint": null,
                      "reset_hold_seconds": null,
                      "instructions": null,
                      "source_url": "https://kb.netgear.com/980/How-do-I-log-in-to-my-NETGEAR-router",
                      "confidence": "unverified",
                      "verified_at": null,
                      "models": [
                        {
                          "model": "Orbi RBR750",
                          "model_slug": "orbi-rbr750",
                          "hardware_revision": "",
                          "sale_status": "current",
                          "release_year": 2020,
                          "discontinued_year": null,
                          "wifi_standard": "Wi-Fi 6 (802.11ax)",
                          "max_speed_mbps": 4200,
                          "band_count": 3,
                          "wan_ports": 1,
                          "lan_ports": 3,
                          "is_mesh": true,
                          "device_type": "mesh",
                          "image_url": null,
                          "product_url": "https://www.netgear.com/home/wifi/mesh/rbk752/",
                          "specs_source_url": "https://www.netgear.com/support/product/rbk752",
                          "specs_confidence": "single-source",
                          "notes": "Router of the RBK752 kit — \"Orbi WiFi 6 System AX4200: (1) Orbi Router (RBR750) + (1) Orbi Satellite (RBS750)\". Ports from the product line.",
                          "offers": [
                            {
                              "retailer": "amazon",
                              "url": "https://www.amazon.com/s?k=NETGEAR+Orbi+RBR750&tag=whatismyip-20",
                              "price_cents": null,
                              "currency": "USD",
                              "in_stock": null,
                              "checked_at": null
                            }
                          ]
                        },
                        {
                          "model": "Orbi RBR850",
                          "model_slug": "orbi-rbr850",
                          "hardware_revision": "",
                          "sale_status": "current",
                          "release_year": 2019,
                          "discontinued_year": null,
                          "wifi_standard": "Wi-Fi 6 (802.11ax)",
                          "max_speed_mbps": 6000,
                          "band_count": 3,
                          "wan_ports": 1,
                          "lan_ports": 4,
                          "is_mesh": true,
                          "device_type": "mesh",
                          "image_url": null,
                          "product_url": "https://www.netgear.com/home/wifi/mesh/rbk852/",
                          "specs_source_url": "https://www.netgear.com/home/wifi/mesh/rbk852/",
                          "specs_confidence": "single-source",
                          "notes": "Router of the RBK852 kit — \"Orbi 850 Series Tri-band WiFi 6 Mesh System, 6Gbps\"; on sale (Find a Retailer) 2026-08-28. 2.5G WAN; ports from the product line.",
                          "offers": [
                            {
                              "retailer": "amazon",
                              "url": "https://www.amazon.com/s?k=NETGEAR+Orbi+RBR850&tag=whatismyip-20",
                              "price_cents": null,
                              "currency": "USD",
                              "in_stock": null,
                              "checked_at": null
                            }
                          ]
                        }
                      ]
                    }
                  ]
                },
                "schema": {
                  "$ref": "#/components/schemas/RouterProfiles"
                }
              }
            }
          },
          "400": {
            "description": "Invalid brand provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "e0": {
                    "value": {
                      "error": "Invalid brand provided"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "No data found for the given brand",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "e0": {
                    "value": {
                      "error": "No data found for the given brand"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/LimitReached"
          }
        },
        "security": [
          {
            "headerKey": []
          },
          {
            "queryKey": []
          }
        ],
        "x-fields": [
          [
            "credential_type",
            "string",
            "universal (one default login for every unit) · set-on-first-login (no default password; you create it at setup) · per-device-label (unique, printed on the router) · isp-assigned (set by your ISP) · none-open (no login)."
          ],
          [
            "default_username",
            "string or null",
            "Filled whenever the model ships with a fixed username — always for universal, and usually for set-on-first-login and per-device-label (where only the password is created at setup or printed on the label). null means not published here."
          ],
          [
            "default_password",
            "string or null",
            "Filled only for universal. null means not published here — never an empty password."
          ],
          [
            "label_hint",
            "string or null",
            "Where to find the login on a per-device-label router."
          ],
          [
            "gateway_ip, login_url",
            "string",
            "The admin address and the page to open."
          ],
          [
            "confidence",
            "string",
            "How the login was sourced: verified (checked against the manufacturer's own documentation by us), single-source, or unverified."
          ],
          [
            "verified_at",
            "string or null",
            "Date of our check (YYYY-MM-DD) when confidence is verified; otherwise null."
          ],
          [
            "source_url",
            "string",
            "Where the login information came from."
          ],
          [
            "models[]",
            "object[]",
            "The models the profile applies to: model, model_slug, hardware_revision, release_year, wifi_standard, ports, image and product links."
          ],
          [
            "models[].specs_confidence",
            "string",
            "verified, single-source or unverified — the same scale, for the hardware specs."
          ],
          [
            "models[].offers[]",
            "object[]",
            "Where to buy. price_cents and in_stock are null until we have checked them."
          ]
        ]
      }
    },
    "/router-login/{brand}/{model}": {
      "get": {
        "operationId": "routerModel",
        "summary": "Default login for one router model",
        "parameters": [
          {
            "name": "brand",
            "in": "path",
            "required": true,
            "description": "Brand slug",
            "schema": {
              "type": "string",
              "examples": [
                "netgear"
              ]
            }
          },
          {
            "name": "model",
            "in": "path",
            "required": true,
            "description": "model_slug from /router-login/{brand}",
            "schema": {
              "type": "string",
              "examples": [
                "nighthawk-r7000"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The profile(s) for that model",
            "content": {
              "application/json": {
                "example": {
                  "data": [
                    {
                      "brand": "NETGEAR",
                      "brand_slug": "netgear",
                      "profile_slug": "routerlogin-net-universal-admin-password",
                      "profile_name": "routerlogin.net · admin / password",
                      "gateway_ip": "192.168.1.1",
                      "login_url": "http://routerlogin.net",
                      "credential_type": "universal",
                      "default_username": "admin",
                      "default_password": "password",
                      "label_hint": null,
                      "reset_hold_seconds": null,
                      "instructions": null,
                      "source_url": "https://www.netgear.com/hub/technology/router-login-page/",
                      "confidence": "unverified",
                      "verified_at": null,
                      "models": [
                        {
                          "model": "Nighthawk R7000",
                          "model_slug": "nighthawk-r7000",
                          "hardware_revision": "",
                          "sale_status": "discontinued",
                          "release_year": 2013,
                          "discontinued_year": null,
                          "wifi_standard": "Wi-Fi 5 (802.11ac)",
                          "max_speed_mbps": 1900,
                          "band_count": 2,
                          "wan_ports": 1,
                          "lan_ports": 4,
                          "is_mesh": false,
                          "device_type": "router",
                          "image_url": null,
                          "product_url": "https://www.netgear.com/support/product/r7000",
                          "specs_source_url": "https://www.netgear.com/support/product/r7000",
                          "specs_confidence": "single-source",
                          "notes": "AC1900 dual-band gigabit. NETGEAR: \"End of Service — no additional firmware updates planned\" (2026-08-28). Port counts from the product line, not the page.",
                          "offers": []
                        }
                      ]
                    }
                  ]
                },
                "schema": {
                  "$ref": "#/components/schemas/RouterProfiles"
                }
              }
            }
          },
          "400": {
            "description": "Invalid brand provided / Invalid model provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "e0": {
                    "value": {
                      "error": "Invalid brand provided"
                    }
                  },
                  "e1": {
                    "value": {
                      "error": "Invalid model provided"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "No data found for the given brand and model",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "e0": {
                    "value": {
                      "error": "No data found for the given brand and model"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/LimitReached"
          }
        },
        "security": [
          {
            "headerKey": []
          },
          {
            "queryKey": []
          }
        ],
        "description": " These are the defaults a model ships with — not a reading of anyone's router, which may have been changed. A null default_password means we do not publish one (the router asks you to create it, or it is printed on the label) — it never means a blank password.",
        "x-fields": [
          [
            "credential_type",
            "string",
            "universal (one default login for every unit) · set-on-first-login (no default password; you create it at setup) · per-device-label (unique, printed on the router) · isp-assigned (set by your ISP) · none-open (no login)."
          ],
          [
            "default_username",
            "string or null",
            "Filled whenever the model ships with a fixed username — always for universal, and usually for set-on-first-login and per-device-label (where only the password is created at setup or printed on the label). null means not published here."
          ],
          [
            "default_password",
            "string or null",
            "Filled only for universal. null means not published here — never an empty password."
          ],
          [
            "label_hint",
            "string or null",
            "Where to find the login on a per-device-label router."
          ],
          [
            "gateway_ip, login_url",
            "string",
            "The admin address and the page to open."
          ],
          [
            "confidence",
            "string",
            "How the login was sourced: verified (checked against the manufacturer's own documentation by us), single-source, or unverified."
          ],
          [
            "verified_at",
            "string or null",
            "Date of our check (YYYY-MM-DD) when confidence is verified; otherwise null."
          ],
          [
            "source_url",
            "string",
            "Where the login information came from."
          ],
          [
            "models[]",
            "object[]",
            "The models the profile applies to: model, model_slug, hardware_revision, release_year, wifi_standard, ports, image and product links."
          ],
          [
            "models[].specs_confidence",
            "string",
            "verified, single-source or unverified — the same scale, for the hardware specs."
          ],
          [
            "models[].offers[]",
            "object[]",
            "Where to buy. price_cents and in_stock are null until we have checked them."
          ]
        ]
      }
    },
    "/router-login/ip/{ip}": {
      "get": {
        "operationId": "routerLoginByIp",
        "summary": "Routers that use a given admin (gateway) IP",
        "parameters": [
          {
            "name": "ip",
            "in": "path",
            "required": true,
            "description": "A gateway IPv4 address, e.g. 192.168.1.1",
            "schema": {
              "type": "string",
              "examples": [
                "192.168.1.1"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Matching profiles",
            "content": {
              "application/json": {
                "example": {
                  "data": [
                    {
                      "brand": "ASUS",
                      "brand_slug": "asus",
                      "profile_slug": "router-asus-com-universal-admin-admin",
                      "profile_name": "router.asus.com · admin / admin",
                      "gateway_ip": "192.168.1.1",
                      "login_url": "http://router.asus.com",
                      "credential_type": "universal",
                      "default_username": "admin",
                      "default_password": "admin",
                      "label_hint": null,
                      "reset_hold_seconds": 5,
                      "instructions": null,
                      "source_url": "https://www.asus.com/us/support/faq/1005263/",
                      "confidence": "single-source",
                      "verified_at": null,
                      "models": [
                        {
                          "model": "RT-AC68U",
                          "model_slug": "rt-ac68u",
                          "hardware_revision": "",
                          "sale_status": "discontinued",
                          "release_year": 2013,
                          "discontinued_year": null,
                          "wifi_standard": "Wi-Fi 5 (802.11ac)",
                          "max_speed_mbps": 1900,
                          "band_count": 2,
                          "wan_ports": 1,
                          "lan_ports": 4,
                          "is_mesh": false,
                          "device_type": "router",
                          "image_url": null,
                          "product_url": "https://www.asus.com/networking-iot-servers/wifi-routers/asus-wifi-routers/rtac68u/techspec/",
                          "specs_source_url": "https://www.asus.com/networking-iot-servers/wifi-routers/asus-wifi-routers/rtac68u/techspec/",
                          "specs_confidence": "single-source",
                          "notes": "AC1900: 600 + 1300 Mbps, dual-band; WAN x1 + LAN x4 gigabit. ASUS support page: end of life, no further firmware. 2013 launch is the commonly documented date, not on the ASUS page. Verified 2026-08-31.",
                          "offers": []
                        }
                      ]
                    }
                  ]
                },
                "schema": {
                  "$ref": "#/components/schemas/RouterProfiles"
                }
              }
            }
          },
          "400": {
            "description": "Invalid IP address provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "e0": {
                    "value": {
                      "error": "Invalid IP address provided"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "No routers found for the given gateway IP",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "e0": {
                    "value": {
                      "error": "No routers found for the given gateway IP"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/LimitReached"
          }
        },
        "security": [
          {
            "headerKey": []
          },
          {
            "queryKey": []
          }
        ],
        "description": "Gateway addresses are shared — 192.168.1.1 is used by many brands — so expect several profiles, and pick yours by brand and model. These are the defaults a model ships with — not a reading of anyone's router, which may have been changed. A null default_password means we do not publish one (the router asks you to create it, or it is printed on the label) — it never means a blank password.",
        "x-fields": [
          [
            "credential_type",
            "string",
            "universal (one default login for every unit) · set-on-first-login (no default password; you create it at setup) · per-device-label (unique, printed on the router) · isp-assigned (set by your ISP) · none-open (no login)."
          ],
          [
            "default_username",
            "string or null",
            "Filled whenever the model ships with a fixed username — always for universal, and usually for set-on-first-login and per-device-label (where only the password is created at setup or printed on the label). null means not published here."
          ],
          [
            "default_password",
            "string or null",
            "Filled only for universal. null means not published here — never an empty password."
          ],
          [
            "label_hint",
            "string or null",
            "Where to find the login on a per-device-label router."
          ],
          [
            "gateway_ip, login_url",
            "string",
            "The admin address and the page to open."
          ],
          [
            "confidence",
            "string",
            "How the login was sourced: verified (checked against the manufacturer's own documentation by us), single-source, or unverified."
          ],
          [
            "verified_at",
            "string or null",
            "Date of our check (YYYY-MM-DD) when confidence is verified; otherwise null."
          ],
          [
            "source_url",
            "string",
            "Where the login information came from."
          ],
          [
            "models[]",
            "object[]",
            "The models the profile applies to: model, model_slug, hardware_revision, release_year, wifi_standard, ports, image and product links."
          ],
          [
            "models[].specs_confidence",
            "string",
            "verified, single-source or unverified — the same scale, for the hardware specs."
          ],
          [
            "models[].offers[]",
            "object[]",
            "Where to buy. price_cents and in_stock are null until we have checked them."
          ]
        ]
      }
    }
  },
  "components": {
    "securitySchemes": {
      "headerKey": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-KEY",
        "description": "Preferred. Allowed from browser pages (CORS)."
      },
      "queryKey": {
        "type": "apiKey",
        "in": "query",
        "name": "key",
        "description": "Works, but puts the key in URLs and logs."
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string"
          }
        },
        "required": [
          "error"
        ]
      },
      "IpLocation": {
        "type": "object",
        "description": "Location, ISP and ASN for one address. An unknown text value is the string \"-\" (never null); unknown coordinates are 0.",
        "properties": {
          "ip": {
            "type": "string"
          },
          "country": {
            "type": "string"
          },
          "region": {
            "type": "string"
          },
          "city": {
            "type": "string"
          },
          "postal_code": {
            "type": "string",
            "description": "A string: many postal codes are not numeric."
          },
          "isp": {
            "type": "string"
          },
          "latitude": {
            "type": "number"
          },
          "longitude": {
            "type": "number"
          },
          "time_zone": {
            "type": "string",
            "description": "UTC offset, e.g. \"-07:00\"."
          },
          "asn": {
            "type": "string",
            "description": "Digits only, as a string."
          }
        },
        "required": [
          "ip",
          "country",
          "region",
          "city",
          "postal_code",
          "isp",
          "latitude",
          "longitude",
          "time_zone",
          "asn"
        ]
      },
      "ProxyCheck": {
        "description": "Either the address is not a known proxy (only is_proxy, \"no\"), or it is listed (is_proxy \"yes\" plus the classification).",
        "oneOf": [
          {
            "type": "object",
            "title": "Not a known proxy",
            "properties": {
              "is_proxy": {
                "const": "no"
              }
            },
            "required": [
              "is_proxy"
            ],
            "additionalProperties": false
          },
          {
            "type": "object",
            "title": "Listed as a proxy",
            "properties": {
              "is_proxy": {
                "const": "yes"
              },
              "proxy_type": {
                "type": "string",
                "enum": [
                  "VPN",
                  "TOR",
                  "PUB",
                  "WEB",
                  "DCH",
                  "SES",
                  "RES",
                  "CPN",
                  "EPN"
                ]
              },
              "proxy_type_description": {
                "type": "string"
              },
              "country_code": {
                "type": "string"
              },
              "country_name": {
                "type": "string"
              },
              "proxy_range": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            },
            "required": [
              "is_proxy",
              "proxy_type",
              "proxy_type_description",
              "country_code",
              "country_name",
              "proxy_range"
            ]
          }
        ]
      },
      "IpDecimal": {
        "type": "object",
        "properties": {
          "ip": {
            "type": "string"
          },
          "decimal": {
            "type": "string"
          }
        },
        "required": [
          "ip",
          "decimal"
        ]
      },
      "DnsLookup": {
        "type": "object",
        "description": "One key: the resolver that answered. Its value is a list of one-key objects, one per record type; each value is an array of records or the string \"no records found\" — check the type before iterating.",
        "minProperties": 1,
        "maxProperties": 1,
        "propertyNames": {
          "enum": [
            "google",
            "cloudflare",
            "quad9",
            "opendns",
            "cleanbrowsing"
          ]
        },
        "additionalProperties": {
          "type": "array",
          "items": {
            "type": "object",
            "minProperties": 1,
            "maxProperties": 1,
            "propertyNames": {
              "enum": [
                "ns",
                "a",
                "aaaa",
                "cname",
                "mx",
                "txt"
              ]
            },
            "additionalProperties": {
              "oneOf": [
                {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                },
                {
                  "const": "no records found"
                }
              ]
            }
          }
        }
      },
      "RouterBrands": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "slug": {
                  "type": "string",
                  "description": "Use as {brand}."
                },
                "name": {
                  "type": "string"
                },
                "support_url": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "default_login_url": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "reset_pattern": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "profile_count": {
                  "type": "integer"
                },
                "model_count": {
                  "type": "integer"
                }
              },
              "required": [
                "slug",
                "name",
                "support_url",
                "default_login_url",
                "reset_pattern",
                "profile_count",
                "model_count"
              ]
            }
          }
        },
        "required": [
          "data"
        ]
      },
      "RouterProfiles": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "brand": {
                  "type": "string"
                },
                "brand_slug": {
                  "type": "string"
                },
                "profile_slug": {
                  "type": "string"
                },
                "profile_name": {
                  "type": "string"
                },
                "gateway_ip": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "login_url": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "credential_type": {
                  "type": "string",
                  "enum": [
                    "universal",
                    "set-on-first-login",
                    "per-device-label",
                    "isp-assigned",
                    "none-open"
                  ]
                },
                "default_username": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "Only for universal; null means not published here."
                },
                "default_password": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "Only for universal; null means not published here — never an empty password."
                },
                "label_hint": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "reset_hold_seconds": {
                  "type": [
                    "integer",
                    "null"
                  ]
                },
                "instructions": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "source_url": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "confidence": {
                  "type": "string",
                  "enum": [
                    "verified",
                    "single-source",
                    "unverified"
                  ]
                },
                "verified_at": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "YYYY-MM-DD when confidence is verified."
                },
                "models": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "model": {
                        "type": "string"
                      },
                      "model_slug": {
                        "type": "string"
                      },
                      "hardware_revision": {
                        "type": "string",
                        "description": "Empty string when there is only one revision."
                      },
                      "sale_status": {
                        "type": "string"
                      },
                      "release_year": {
                        "type": [
                          "integer",
                          "null"
                        ]
                      },
                      "discontinued_year": {
                        "type": [
                          "integer",
                          "null"
                        ]
                      },
                      "wifi_standard": {
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "max_speed_mbps": {
                        "type": [
                          "integer",
                          "null"
                        ]
                      },
                      "band_count": {
                        "type": [
                          "integer",
                          "null"
                        ]
                      },
                      "wan_ports": {
                        "type": [
                          "integer",
                          "null"
                        ]
                      },
                      "lan_ports": {
                        "type": [
                          "integer",
                          "null"
                        ]
                      },
                      "is_mesh": {
                        "type": [
                          "boolean",
                          "null"
                        ]
                      },
                      "device_type": {
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "image_url": {
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "product_url": {
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "specs_source_url": {
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "specs_confidence": {
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "notes": {
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "offers": {
                        "type": "array",
                        "items": {
                          "type": "object",
                          "properties": {
                            "retailer": {
                              "type": "string"
                            },
                            "url": {
                              "type": "string"
                            },
                            "price_cents": {
                              "type": [
                                "integer",
                                "null"
                              ]
                            },
                            "currency": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "in_stock": {
                              "type": [
                                "boolean",
                                "null"
                              ]
                            },
                            "checked_at": {
                              "type": [
                                "string",
                                "null"
                              ]
                            }
                          },
                          "required": [
                            "retailer",
                            "url",
                            "price_cents",
                            "currency",
                            "in_stock",
                            "checked_at"
                          ]
                        }
                      }
                    },
                    "required": [
                      "model",
                      "model_slug",
                      "hardware_revision",
                      "sale_status",
                      "release_year",
                      "discontinued_year",
                      "wifi_standard",
                      "max_speed_mbps",
                      "band_count",
                      "wan_ports",
                      "lan_ports",
                      "is_mesh",
                      "device_type",
                      "image_url",
                      "product_url",
                      "specs_source_url",
                      "specs_confidence",
                      "notes",
                      "offers"
                    ]
                  }
                }
              },
              "required": [
                "brand",
                "brand_slug",
                "profile_slug",
                "profile_name",
                "gateway_ip",
                "login_url",
                "credential_type",
                "default_username",
                "default_password",
                "label_hint",
                "reset_hold_seconds",
                "instructions",
                "source_url",
                "confidence",
                "verified_at",
                "models"
              ]
            }
          }
        },
        "required": [
          "data"
        ]
      }
    },
    "responses": {
      "Unauthorized": {
        "description": "Missing or invalid API key",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "examples": {
              "missing": {
                "value": {
                  "error": "No API key provided in the query string or header"
                }
              },
              "invalid": {
                "value": {
                  "error": "Invalid API key"
                }
              }
            }
          }
        }
      },
      "Forbidden": {
        "description": "The key is disabled",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": "API key is disabled"
            }
          }
        }
      },
      "LimitReached": {
        "description": "Daily limit reached (rolling 24 hours per key). Two retry values, in different units: the Retry-After HEADER is a number of SECONDS from now; retryAfter in the BODY is an absolute UTC timestamp — the moment your oldest counted call turns 24 hours old and one call frees up. The window refills one call at a time as old calls age out; there is no full reset.",
        "headers": {
          "Retry-After": {
            "description": "Seconds until one call frees up (integer). Readable from browser JavaScript.",
            "schema": {
              "type": "integer"
            }
          }
        },
        "content": {
          "application/json": {
            "example": {
              "allowed": false,
              "error": "API usage limit exceeded. Please try again later.",
              "dailyUsage": 1440,
              "dailyLimit": 1440,
              "retryAfter": "2026-09-30T14:02:11+00:00"
            },
            "schema": {
              "type": "object",
              "properties": {
                "allowed": {
                  "const": false
                },
                "error": {
                  "type": "string"
                },
                "dailyUsage": {
                  "type": "integer"
                },
                "dailyLimit": {
                  "type": "integer"
                },
                "retryAfter": {
                  "type": "string",
                  "format": "date-time",
                  "description": "Absolute UTC time one call frees up."
                }
              },
              "required": [
                "allowed",
                "error",
                "dailyUsage",
                "dailyLimit",
                "retryAfter"
              ]
            },
            "x-note": "Illustrative values; retryAfter is shown as an example timestamp."
          }
        }
      }
    }
  }
}
