{"openapi":"3.1.0","jsonSchemaDialect":"https://json-schema.org/draft/2020-12/schema","info":{"title":"LookupOwl API","version":"1.0.0","summary":"Free network, DNS and WHOIS tools over REST. No API key, no account.","description":"LookupOwl exposes every tool it has three ways: this REST API, an MCP server at https://lookupowl.com/mcp, and web pages.\n\nThere are no API keys and no accounts. Results are cached; cached calls are cheap.\n\nEach network gets about 300 cost units per 10 minutes (burst 60); a cached result costs 1 unit, a live lookup 1 to a few, and a calculator 1. The RateLimit and RateLimit-Policy response headers show your remaining budget.\n\nErrors are `application/problem+json`. A 429 or 503 carries `Retry-After`. Every response carries `X-Request-Id`.\n\nAgent-readable docs: https://lookupowl.com/llms.txt","contact":{"name":"LookupOwl","url":"https://lookupowl.com","email":"talk@lookupowl.com"},"license":{"name":"LookupOwl terms of use","url":"https://lookupowl.com/terms"}},"security":[],"servers":[{"url":"https://lookupowl.com"}],"tags":[{"name":"catalog","description":"Discover tools and their schemas."},{"name":"domain","description":"Domain registration data: WHOIS/RDAP, availability, EPP status codes, IDN conversion."},{"name":"dns","description":"DNS lookups, propagation checks and reverse DNS."},{"name":"email","description":"Email authentication: SPF and DMARC checkers and generators."},{"name":"ip","description":"IP addresses, networks and ASNs: lookups and calculators."},{"name":"web","description":"HTTP-level checks: response headers and redirect chains."},{"name":"security","description":"TLS certificates and security helpers."}],"paths":{"/api/v1/tools":{"get":{"operationId":"list_tools","summary":"List tools","description":"Catalog of every tool available over REST, with links to run it and to its JSON Schemas.","tags":["catalog"],"responses":{"200":{"description":"The catalog.","content":{"application/json":{"schema":{"type":"object","required":["apiVersion","tools"],"properties":{"apiVersion":{"const":1},"tools":{"type":"array","items":{"$ref":"#/components/schemas/ToolDescriptor"}}}}}}}}}},"/api/v1/tools/{id}/schema":{"get":{"operationId":"get_tool_schema","summary":"JSON Schemas of a tool","tags":["catalog"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","enum":["asn-lookup","blacklist-checker","dkim-checker","dmarc-checker","dmarc-generator","dns-lookup","dns-propagation","domain-availability","domain-report","epp-status","http-headers","ip-convert","ip-location","ip-range-convert","ip-whois","ipv6-format","mac-lookup","password-generator","punycode-converter","reverse-dns","security-headers","spf-checker","spf-generator","ssl-checker","subnet-calculator","website-hosting","what-is-my-ip","whois-lookup"]}}],"responses":{"200":{"description":"Input and output JSON Schema (draft 2020-12).","content":{"application/json":{"schema":{"type":"object","properties":{"input":{"type":"object"},"output":{"type":"object"}}}}}},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/v1/tools/asn-lookup":{"get":{"operationId":"asn_lookup","summary":"ASN Lookup","description":"Look up an Autonomous System (AS) number through RDAP, from the Regional Internet Registry that allocated it (ARIN, RIPE NCC, APNIC, LACNIC or AFRINIC). Accepts AS13335, as13335, 13335 or asdot such as 1.10. Returns the AS name and handle, the number range it belongs to, type, country, status, registration and last-changed dates, contacts and the abuse mailbox. Private-use, documentation and reserved AS numbers return status \"special_purpose\" without any lookup. This is registration data; it does not list prefixes, peers or routes.\n\nNot for: Routing data such as announced prefixes, peers or BGP paths, IP addresses (use ip_whois) or domain names (use whois_lookup).","tags":["ip"],"x-mcp-tool":"asn_lookup","x-cost":{"lane":"rdap","miss":1,"hit":1},"x-cache-ttl":"dynamic","x-cache-scope":"public","parameters":[{"name":"q","in":"query","required":true,"description":"AS number, e.g. AS13335, 13335 or asdot notation such as 1.10. A leading \"AS\" is optional.","schema":{"type":"string","minLength":1,"maxLength":512},"examples":{"cloudflare":{"summary":"AS13335 (Cloudflare)","value":"AS13335"},"google":{"summary":"AS15169 (Google), without the prefix","value":"15169"},"private-asn":{"summary":"A private-use AS number has no owner to look up","value":"AS64512"}},"style":"form","explode":true},{"name":"includeRaw","in":"query","required":false,"description":"Include the raw RDAP JSON from the Regional Internet Registry in the result. Large; off by default.","schema":{"default":false,"type":"boolean"},"examples":{"cloudflare":{"summary":"AS13335 (Cloudflare)","value":false},"google":{"summary":"AS15169 (Google), without the prefix","value":false},"private-asn":{"summary":"A private-use AS number has no owner to look up","value":false}},"style":"form","explode":true},{"name":"fresh","in":"query","required":false,"description":"Bypass the cache (costs 3x, limited to 10 per hour per network).","schema":{"type":"boolean","default":false}},{"name":"format","in":"query","required":false,"description":"`text` returns the plain-text summary instead of JSON.","schema":{"enum":["json","text"],"default":"json"}}],"responses":{"200":{"description":"The result.","headers":{"RateLimit":{"description":"Remaining tool-cost units: `\"cost\";r=<remaining>;t=<seconds until full>`.","schema":{"type":"string"}},"RateLimit-Policy":{"description":"Quota: `\"cost\";q=<units>;w=<seconds>`.","schema":{"type":"string"}},"X-Request-Id":{"description":"Request id, also in the body.","schema":{"type":"string"}},"ETag":{"description":"Weak validator for conditional requests.","schema":{"type":"string"}},"Link":{"description":"Permalink to the web page (rel=alternate).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AsnLookupResult"}}}},"304":{"description":"Not modified (If-None-Match matched)."},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}},"post":{"operationId":"asn_lookup_post","summary":"ASN Lookup (JSON body)","description":"Same as GET, with the input as a JSON body. Never cached. Add `?fresh=1` to bypass the cache where supported.","tags":["ip"],"x-mcp-tool":"asn_lookup","x-cost":{"lane":"rdap","miss":1,"hit":1},"x-cache-ttl":"dynamic","x-cache-scope":"public","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AsnLookupInput"},"examples":{"cloudflare":{"summary":"AS13335 (Cloudflare)","value":{"q":"AS13335","includeRaw":false}},"google":{"summary":"AS15169 (Google), without the prefix","value":{"q":"15169","includeRaw":false}},"private-asn":{"summary":"A private-use AS number has no owner to look up","value":{"q":"AS64512","includeRaw":false}}}}}},"responses":{"200":{"description":"The result.","headers":{"RateLimit":{"description":"Remaining tool-cost units: `\"cost\";r=<remaining>;t=<seconds until full>`.","schema":{"type":"string"}},"RateLimit-Policy":{"description":"Quota: `\"cost\";q=<units>;w=<seconds>`.","schema":{"type":"string"}},"X-Request-Id":{"description":"Request id, also in the body.","schema":{"type":"string"}},"ETag":{"description":"Weak validator for conditional requests.","schema":{"type":"string"}},"Link":{"description":"Permalink to the web page (rel=alternate).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AsnLookupResult"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/api/v1/tools/blacklist-checker":{"get":{"operationId":"blacklist_check","summary":"IP and Domain Blacklist Checker","description":"Check an IPv4/IPv6 address, a domain's mail-server IPs (scope mx, a or both) or a domain name (scope domain) against a curated registry of live DNS blocklists: Spamhaus ZEN and DBL, SpamCop, Barracuda, UCEPROTECT 1-3, PSBL, Mailspike, DroneBL, URIBL and others (dead lists such as SORBS are excluded). Returns per list listed, clean, error or refused, the decoded return code, the TXT reason and the delisting link, plus a weighted summary. A refusal (for example Spamhaus 127.255.255.254 for public resolvers) means the list did not answer and is never counted as listed or clean. At most 3 IPs per domain.\n\nNot for: Monitoring over time, or mailbox-provider reputation (Gmail, Outlook), which no public list shows.","tags":["email"],"x-mcp-tool":"blacklist_check","x-cost":{"lane":"dns","miss":"variable","hit":1},"x-cache-ttl":"dynamic","x-cache-scope":"public","parameters":[{"name":"target","in":"query","required":true,"description":"A public IPv4 or IPv6 address, or a domain. A URL or e-mail address is reduced to its host. Private and reserved addresses are refused.","schema":{"type":"string","maxLength":253},"examples":{"ip-clean":{"summary":"A well-known mail server IP","value":"8.8.8.8"},"mail-servers":{"summary":"The mail servers of a domain","value":"github.com"},"domain-lists":{"summary":"A domain against domain blocklists","value":"example.com"}},"style":"form","explode":true},{"name":"scope","in":"query","required":false,"description":"For a domain: mx = check its mail servers' IPs (default), a = the IP of the domain itself, both = both, domain = check the domain name against domain blocklists (Spamhaus DBL, URIBL, ...). Ignored for an IP address.","schema":{"default":"mx","type":"string","enum":["mx","a","both","domain"]},"examples":{"ip-clean":{"summary":"A well-known mail server IP","value":"mx"},"mail-servers":{"summary":"The mail servers of a domain","value":"mx"},"domain-lists":{"summary":"A domain against domain blocklists","value":"domain"}},"style":"form","explode":true},{"name":"fresh","in":"query","required":false,"description":"Bypass the cache (costs 3x, limited to 10 per hour per network).","schema":{"type":"boolean","default":false}},{"name":"format","in":"query","required":false,"description":"`text` returns the plain-text summary instead of JSON.","schema":{"enum":["json","text"],"default":"json"}}],"responses":{"200":{"description":"The result.","headers":{"RateLimit":{"description":"Remaining tool-cost units: `\"cost\";r=<remaining>;t=<seconds until full>`.","schema":{"type":"string"}},"RateLimit-Policy":{"description":"Quota: `\"cost\";q=<units>;w=<seconds>`.","schema":{"type":"string"}},"X-Request-Id":{"description":"Request id, also in the body.","schema":{"type":"string"}},"ETag":{"description":"Weak validator for conditional requests.","schema":{"type":"string"}},"Link":{"description":"Permalink to the web page (rel=alternate).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BlacklistCheckResult"}}}},"304":{"description":"Not modified (If-None-Match matched)."},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}},"post":{"operationId":"blacklist_check_post","summary":"IP and Domain Blacklist Checker (JSON body)","description":"Same as GET, with the input as a JSON body. Never cached. Add `?fresh=1` to bypass the cache where supported.","tags":["email"],"x-mcp-tool":"blacklist_check","x-cost":{"lane":"dns","miss":"variable","hit":1},"x-cache-ttl":"dynamic","x-cache-scope":"public","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BlacklistCheckInput"},"examples":{"ip-clean":{"summary":"A well-known mail server IP","value":{"target":"8.8.8.8","scope":"mx"}},"mail-servers":{"summary":"The mail servers of a domain","value":{"target":"github.com","scope":"mx"}},"domain-lists":{"summary":"A domain against domain blocklists","value":{"target":"example.com","scope":"domain"}}}}}},"responses":{"200":{"description":"The result.","headers":{"RateLimit":{"description":"Remaining tool-cost units: `\"cost\";r=<remaining>;t=<seconds until full>`.","schema":{"type":"string"}},"RateLimit-Policy":{"description":"Quota: `\"cost\";q=<units>;w=<seconds>`.","schema":{"type":"string"}},"X-Request-Id":{"description":"Request id, also in the body.","schema":{"type":"string"}},"ETag":{"description":"Weak validator for conditional requests.","schema":{"type":"string"}},"Link":{"description":"Permalink to the web page (rel=alternate).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BlacklistCheckResult"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/api/v1/tools/dkim-checker":{"get":{"operationId":"dkim_check","summary":"DKIM Record Checker","description":"Look up DKIM keys at <selector>._domainkey.<domain> (RFC 6376). With a selector it reads that one record; without one it tries up to 24 documented common selectors (google, selector1, selector2, k1, s1, default, ...), ordered by the provider seen in the MX records. Parses every tag (v, k, p, h, s, t, n), follows CNAME delegation to providers, decodes the key (RSA length in bits, Ed25519) and flags RSA under 1024 bits (error), 1024 bits (warning, RFC 8301), sha1-only, t=y testing mode, revoked (empty p=) and syntax errors. Selectors cannot be enumerated, so none found is not proof of no DKIM; the result says what was tried.\n\nNot for: Verifying a signature on a real message (use email_header_analyze) or generating a key (use dkim_record_format).","tags":["email"],"x-mcp-tool":"dkim_check","x-cost":{"lane":"dns","miss":"variable","hit":1},"x-cache-ttl":"dynamic","x-cache-scope":"public","parameters":[{"name":"domain","in":"query","required":true,"description":"Domain that sends the mail, e.g. example.com. A URL, an e-mail address or a full key name such as google._domainkey.example.com is reduced to the domain (and the selector, when it is in the name).","schema":{"type":"string","maxLength":253},"examples":{"discover-github":{"summary":"Find the selectors of github.com","value":"github.com"},"microsoft-365":{"summary":"A Microsoft 365 selector (CNAME delegation)","value":"microsoft.com"},"revoked-key":{"summary":"A revoked key (empty p=)","value":"google.com"}},"style":"form","explode":true},{"name":"selector","in":"query","required":false,"description":"DKIM selector, the \"s=\" value of a DKIM-Signature header, e.g. google or selector1. Leave it out to try a short list of common selectors.","schema":{"type":"string","maxLength":100},"examples":{"microsoft-365":{"summary":"A Microsoft 365 selector (CNAME delegation)","value":"selector2"},"revoked-key":{"summary":"A revoked key (empty p=)","value":"20230601"}},"style":"form","explode":true},{"name":"discover","in":"query","required":false,"description":"When no selector is given, try the documented list of common selectors (at most 24). DKIM selectors cannot be listed, so finding none is not proof that the domain has no DKIM.","schema":{"default":true,"type":"boolean"},"examples":{"discover-github":{"summary":"Find the selectors of github.com","value":true},"microsoft-365":{"summary":"A Microsoft 365 selector (CNAME delegation)","value":true},"revoked-key":{"summary":"A revoked key (empty p=)","value":true}},"style":"form","explode":true},{"name":"fresh","in":"query","required":false,"description":"Bypass the cache (costs 3x, limited to 10 per hour per network).","schema":{"type":"boolean","default":false}},{"name":"format","in":"query","required":false,"description":"`text` returns the plain-text summary instead of JSON.","schema":{"enum":["json","text"],"default":"json"}}],"responses":{"200":{"description":"The result.","headers":{"RateLimit":{"description":"Remaining tool-cost units: `\"cost\";r=<remaining>;t=<seconds until full>`.","schema":{"type":"string"}},"RateLimit-Policy":{"description":"Quota: `\"cost\";q=<units>;w=<seconds>`.","schema":{"type":"string"}},"X-Request-Id":{"description":"Request id, also in the body.","schema":{"type":"string"}},"ETag":{"description":"Weak validator for conditional requests.","schema":{"type":"string"}},"Link":{"description":"Permalink to the web page (rel=alternate).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DkimCheckResult"}}}},"304":{"description":"Not modified (If-None-Match matched)."},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}},"post":{"operationId":"dkim_check_post","summary":"DKIM Record Checker (JSON body)","description":"Same as GET, with the input as a JSON body. Never cached. Add `?fresh=1` to bypass the cache where supported.","tags":["email"],"x-mcp-tool":"dkim_check","x-cost":{"lane":"dns","miss":"variable","hit":1},"x-cache-ttl":"dynamic","x-cache-scope":"public","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DkimCheckInput"},"examples":{"discover-github":{"summary":"Find the selectors of github.com","value":{"domain":"github.com","discover":true}},"microsoft-365":{"summary":"A Microsoft 365 selector (CNAME delegation)","value":{"domain":"microsoft.com","selector":"selector2","discover":true}},"revoked-key":{"summary":"A revoked key (empty p=)","value":{"domain":"google.com","selector":"20230601","discover":true}}}}}},"responses":{"200":{"description":"The result.","headers":{"RateLimit":{"description":"Remaining tool-cost units: `\"cost\";r=<remaining>;t=<seconds until full>`.","schema":{"type":"string"}},"RateLimit-Policy":{"description":"Quota: `\"cost\";q=<units>;w=<seconds>`.","schema":{"type":"string"}},"X-Request-Id":{"description":"Request id, also in the body.","schema":{"type":"string"}},"ETag":{"description":"Weak validator for conditional requests.","schema":{"type":"string"}},"Link":{"description":"Permalink to the web page (rel=alternate).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DkimCheckResult"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/api/v1/tools/dmarc-checker":{"get":{"operationId":"dmarc_check","summary":"DMARC Record Checker","description":"Fetch and validate the DMARC (RFC 7489, DMARCbis tags np/t/psd) record at _dmarc.<domain>. When a subdomain has no record, falls back to the organizational domain (Public Suffix List), as receivers do. Parses every tag (p, sp, np, pct, adkim, aspf, rua, ruf, fo, ri), reports the effective policy and its strength (monitoring, partial, enforcing), flags errors and weak settings, and verifies that report mailboxes in other domains are authorized by a <domain>._report._dmarc.<reporter> TXT record. A missing record is a normal result.\n\nNot for: Generating a record (use dmarc_generate) or checking SPF (use spf_check).","tags":["email"],"x-mcp-tool":"dmarc_check","x-cost":{"lane":"dns","miss":3,"hit":1},"x-cache-ttl":"dynamic","x-cache-scope":"public","parameters":[{"name":"domain","in":"query","required":true,"description":"Domain to check, e.g. example.com (not _dmarc.example.com, though that is accepted). A URL or e-mail address is reduced to its domain; Unicode names are converted to Punycode. For a subdomain without its own record the organizational domain's record is used, as receivers do.","schema":{"type":"string","maxLength":253},"examples":{"google-com":{"summary":"DMARC of google.com","value":"google.com"},"github-com":{"summary":"DMARC of github.com","value":"github.com"},"subdomain-fallback":{"summary":"A subdomain that inherits its parent's policy","value":"mail.google.com"}},"style":"form","explode":true},{"name":"fresh","in":"query","required":false,"description":"Bypass the cache (costs 3x, limited to 10 per hour per network).","schema":{"type":"boolean","default":false}},{"name":"format","in":"query","required":false,"description":"`text` returns the plain-text summary instead of JSON.","schema":{"enum":["json","text"],"default":"json"}}],"responses":{"200":{"description":"The result.","headers":{"RateLimit":{"description":"Remaining tool-cost units: `\"cost\";r=<remaining>;t=<seconds until full>`.","schema":{"type":"string"}},"RateLimit-Policy":{"description":"Quota: `\"cost\";q=<units>;w=<seconds>`.","schema":{"type":"string"}},"X-Request-Id":{"description":"Request id, also in the body.","schema":{"type":"string"}},"ETag":{"description":"Weak validator for conditional requests.","schema":{"type":"string"}},"Link":{"description":"Permalink to the web page (rel=alternate).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DmarcCheckResult"}}}},"304":{"description":"Not modified (If-None-Match matched)."},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}},"post":{"operationId":"dmarc_check_post","summary":"DMARC Record Checker (JSON body)","description":"Same as GET, with the input as a JSON body. Never cached. Add `?fresh=1` to bypass the cache where supported.","tags":["email"],"x-mcp-tool":"dmarc_check","x-cost":{"lane":"dns","miss":3,"hit":1},"x-cache-ttl":"dynamic","x-cache-scope":"public","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DmarcCheckInput"},"examples":{"google-com":{"summary":"DMARC of google.com","value":{"domain":"google.com"}},"github-com":{"summary":"DMARC of github.com","value":{"domain":"github.com"}},"subdomain-fallback":{"summary":"A subdomain that inherits its parent's policy","value":{"domain":"mail.google.com"}}}}}},"responses":{"200":{"description":"The result.","headers":{"RateLimit":{"description":"Remaining tool-cost units: `\"cost\";r=<remaining>;t=<seconds until full>`.","schema":{"type":"string"}},"RateLimit-Policy":{"description":"Quota: `\"cost\";q=<units>;w=<seconds>`.","schema":{"type":"string"}},"X-Request-Id":{"description":"Request id, also in the body.","schema":{"type":"string"}},"ETag":{"description":"Weak validator for conditional requests.","schema":{"type":"string"}},"Link":{"description":"Permalink to the web page (rel=alternate).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DmarcCheckResult"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/api/v1/tools/dmarc-generator":{"get":{"operationId":"dmarc_generate","summary":"DMARC Record Generator","description":"Generate a DMARC TXT record for _dmarc.<domain> from structured choices: policy (none, quarantine, reject), subdomain policy sp, non-existent subdomain policy np, rua/ruf report addresses (mailto URIs with optional size limits), adkim/aspf alignment, failure options fo, and the legacy pct and ri tags. Validates every value, lists the external report-authorization TXT records needed when reports go to another domain, and returns a four-step rollout from p=none to p=reject. Pure calculation, no DNS queries.\n\nNot for: Checking a published DMARC record (use dmarc_check).","tags":["email"],"x-mcp-tool":"dmarc_generate","x-cost":{"lane":"cpu","miss":1,"hit":1},"x-cache-ttl":86400,"x-cache-scope":"public","parameters":[{"name":"domain","in":"query","required":true,"description":"The domain to protect, e.g. example.com (the record is published at _dmarc.<domain>). URLs, e-mail addresses and Unicode names are reduced to the ASCII domain.","schema":{"type":"string","maxLength":253},"examples":{"monitor":{"summary":"Start by monitoring","value":"example.com"},"enforce":{"summary":"Quarantine with strict alignment and a reporting vendor","value":"example.org"},"reject-full":{"summary":"Full reject policy","value":"example.net"}},"style":"form","explode":true},{"name":"policy","in":"query","required":false,"description":"What receivers should do with mail that fails DMARC: none (monitor only), quarantine (spam folder), reject (refuse).","schema":{"default":"none","type":"string","enum":["none","quarantine","reject"]},"examples":{"monitor":{"summary":"Start by monitoring","value":"none"},"enforce":{"summary":"Quarantine with strict alignment and a reporting vendor","value":"quarantine"},"reject-full":{"summary":"Full reject policy","value":"reject"}},"style":"form","explode":true},{"name":"subdomainPolicy","in":"query","required":false,"description":"sp=: policy for subdomains. Defaults to the main policy when omitted.","schema":{"type":"string","enum":["none","quarantine","reject"]},"examples":{"enforce":{"summary":"Quarantine with strict alignment and a reporting vendor","value":"reject"}},"style":"form","explode":true},{"name":"nonexistentPolicy","in":"query","required":false,"description":"np=: policy for non-existent subdomains (DMARCbis; older receivers ignore it).","schema":{"type":"string","enum":["none","quarantine","reject"]},"examples":{"reject-full":{"summary":"Full reject policy","value":"reject"}},"style":"form","explode":true},{"name":"rua","in":"query","required":false,"description":"Where to send daily aggregate reports: addresses or mailto: URIs, optionally with a size limit (mailto:a@example.com!10m).","schema":{"maxItems":10,"type":"array","items":{"type":"string","maxLength":254}},"examples":{"monitor":{"summary":"Start by monitoring","value":["dmarc-reports@example.com"]},"enforce":{"summary":"Quarantine with strict alignment and a reporting vendor","value":["mailto:abc123@dmarc.vendor.net"]},"reject-full":{"summary":"Full reject policy","value":["dmarc@example.net"]}},"style":"form","explode":true},{"name":"ruf","in":"query","required":false,"description":"Where to send failure (forensic) reports. Most large providers no longer send them.","schema":{"maxItems":10,"type":"array","items":{"type":"string","maxLength":254}},"examples":{"reject-full":{"summary":"Full reject policy","value":["forensic@example.net"]}},"style":"form","explode":true},{"name":"adkim","in":"query","required":false,"description":"DKIM alignment: r relaxed (default) or s strict.","schema":{"type":"string","enum":["r","s"]},"examples":{"enforce":{"summary":"Quarantine with strict alignment and a reporting vendor","value":"s"}},"style":"form","explode":true},{"name":"aspf","in":"query","required":false,"description":"SPF alignment: r relaxed (default) or s strict.","schema":{"type":"string","enum":["r","s"]},"examples":{"enforce":{"summary":"Quarantine with strict alignment and a reporting vendor","value":"s"}},"style":"form","explode":true},{"name":"pct","in":"query","required":false,"description":"Legacy (RFC 7489) percentage of failing mail the policy applies to. Removed in DMARCbis but still honoured by major providers.","schema":{"type":"integer","minimum":0,"maximum":100},"style":"form","explode":true},{"name":"fo","in":"query","required":false,"description":"Failure-report options: any of 0, 1, d, s (for example \"1\" or \"0:s\"). Only matters with ruf.","schema":{"type":"string","maxLength":16},"examples":{"reject-full":{"summary":"Full reject policy","value":"1"}},"style":"form","explode":true},{"name":"ri","in":"query","required":false,"description":"Legacy (RFC 7489) aggregate report interval in seconds (default 86400). Removed in DMARCbis.","schema":{"type":"integer","minimum":1,"maximum":4294967295},"style":"form","explode":true},{"name":"testing","in":"query","required":false,"description":"DMARCbis testing mode (t=y): tells receivers you are still rolling out.","schema":{"default":false,"type":"boolean"},"examples":{"monitor":{"summary":"Start by monitoring","value":false},"enforce":{"summary":"Quarantine with strict alignment and a reporting vendor","value":false},"reject-full":{"summary":"Full reject policy","value":false}},"style":"form","explode":true},{"name":"format","in":"query","required":false,"description":"`text` returns the plain-text summary instead of JSON.","schema":{"enum":["json","text"],"default":"json"}}],"responses":{"200":{"description":"The result.","headers":{"RateLimit":{"description":"Remaining tool-cost units: `\"cost\";r=<remaining>;t=<seconds until full>`.","schema":{"type":"string"}},"RateLimit-Policy":{"description":"Quota: `\"cost\";q=<units>;w=<seconds>`.","schema":{"type":"string"}},"X-Request-Id":{"description":"Request id, also in the body.","schema":{"type":"string"}},"ETag":{"description":"Weak validator for conditional requests.","schema":{"type":"string"}},"Link":{"description":"Permalink to the web page (rel=alternate).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DmarcGenerateResult"}}}},"304":{"description":"Not modified (If-None-Match matched)."},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}},"post":{"operationId":"dmarc_generate_post","summary":"DMARC Record Generator (JSON body)","description":"Same as GET, with the input as a JSON body. Never cached. Add `?fresh=1` to bypass the cache where supported.","tags":["email"],"x-mcp-tool":"dmarc_generate","x-cost":{"lane":"cpu","miss":1,"hit":1},"x-cache-ttl":86400,"x-cache-scope":"public","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DmarcGenerateInput"},"examples":{"monitor":{"summary":"Start by monitoring","value":{"domain":"example.com","policy":"none","rua":["dmarc-reports@example.com"],"testing":false}},"enforce":{"summary":"Quarantine with strict alignment and a reporting vendor","value":{"domain":"example.org","policy":"quarantine","subdomainPolicy":"reject","rua":["mailto:abc123@dmarc.vendor.net"],"adkim":"s","aspf":"s","testing":false}},"reject-full":{"summary":"Full reject policy","value":{"domain":"example.net","policy":"reject","nonexistentPolicy":"reject","rua":["dmarc@example.net"],"ruf":["forensic@example.net"],"fo":"1","testing":false}}}}}},"responses":{"200":{"description":"The result.","headers":{"RateLimit":{"description":"Remaining tool-cost units: `\"cost\";r=<remaining>;t=<seconds until full>`.","schema":{"type":"string"}},"RateLimit-Policy":{"description":"Quota: `\"cost\";q=<units>;w=<seconds>`.","schema":{"type":"string"}},"X-Request-Id":{"description":"Request id, also in the body.","schema":{"type":"string"}},"ETag":{"description":"Weak validator for conditional requests.","schema":{"type":"string"}},"Link":{"description":"Permalink to the web page (rel=alternate).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DmarcGenerateResult"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/api/v1/tools/dns-lookup":{"get":{"operationId":"dns_lookup","summary":"DNS Lookup","description":"Resolve DNS records for a domain or host name from a chosen public resolver (Cloudflare, Google, Quad9, OpenDNS and others) or straight from the domain's authoritative nameserver. Types: A, AAAA, CNAME, MX, NS, TXT, SOA, CAA, DS, DNSKEY, PTR, SRV, HTTPS, TLSA, or ALL for the common ones in one call. URLs and e-mail addresses are reduced to their host; for PTR an IP address is accepted. Returns records with TTLs and parsed fields, the response code (NXDOMAIN and NODATA are normal results), the DNSSEC AD flag and timing. Use dns_propagation to compare resolvers worldwide.\n\nNot for: Checking whether a change has reached resolvers worldwide (use dns_propagation), or parsing SPF/DMARC (use spf_check, dmarc_check).","tags":["dns"],"x-mcp-tool":"dns_lookup","x-cost":{"lane":"dns","miss":"variable","hit":1},"x-cache-ttl":"dynamic","x-cache-scope":"public","parameters":[{"name":"name","in":"query","required":true,"description":"Domain or host name, e.g. example.com or _dmarc.example.com. A URL or e-mail address is reduced to its host; Unicode names are converted to Punycode. For type PTR you may give an IP address.","schema":{"type":"string","maxLength":253},"examples":{"example-a":{"summary":"A records of example.com","value":"example.com"},"google-mx":{"summary":"Mail servers of google.com","value":"google.com"},"cloudflare-all":{"summary":"Common records of cloudflare.com","value":"cloudflare.com"},"github-cname":{"summary":"CNAME of www.github.com","value":"www.github.com"},"cloudflare-dnskey":{"summary":"DNSKEY of cloudflare.com with DNSSEC","value":"cloudflare.com"},"google-dns-ptr":{"summary":"Reverse lookup of 8.8.8.8","value":"8.8.8.8"},"cloudflare-aaaa":{"summary":"IPv6 addresses of cloudflare.com","value":"cloudflare.com"},"cloudflare-ns":{"summary":"Nameservers of cloudflare.com","value":"cloudflare.com"},"google-txt":{"summary":"TXT records of google.com","value":"google.com"},"example-soa":{"summary":"SOA record of example.com","value":"example.com"},"google-caa":{"summary":"CAA records of google.com","value":"google.com"},"cloudflare-ds":{"summary":"DS record of cloudflare.com","value":"cloudflare.com"}},"style":"form","explode":true},{"name":"type","in":"query","required":false,"description":"Record type. ALL runs A, AAAA, CNAME, MX, NS, TXT, SOA, CAA and HTTPS together. ANY is not offered (RFC 8482).","schema":{"default":"A","type":"string","enum":["ALL","A","AAAA","CNAME","MX","NS","TXT","SOA","CAA","DS","DNSKEY","PTR","SRV","HTTPS","TLSA"]},"examples":{"example-a":{"summary":"A records of example.com","value":"A"},"google-mx":{"summary":"Mail servers of google.com","value":"MX"},"cloudflare-all":{"summary":"Common records of cloudflare.com","value":"ALL"},"github-cname":{"summary":"CNAME of www.github.com","value":"CNAME"},"cloudflare-dnskey":{"summary":"DNSKEY of cloudflare.com with DNSSEC","value":"DNSKEY"},"google-dns-ptr":{"summary":"Reverse lookup of 8.8.8.8","value":"PTR"},"cloudflare-aaaa":{"summary":"IPv6 addresses of cloudflare.com","value":"AAAA"},"cloudflare-ns":{"summary":"Nameservers of cloudflare.com","value":"NS"},"google-txt":{"summary":"TXT records of google.com","value":"TXT"},"example-soa":{"summary":"SOA record of example.com","value":"SOA"},"google-caa":{"summary":"CAA records of google.com","value":"CAA"},"cloudflare-ds":{"summary":"DS record of cloudflare.com","value":"DS"}},"style":"form","explode":true},{"name":"resolver","in":"query","required":false,"description":"Which resolver to ask: a public resolver id (cloudflare, google, quad9, opendns, ...) or \"authoritative\" to query the domain's own nameserver directly (no cache).","schema":{"default":"cloudflare","type":"string","enum":["cloudflare","cloudflare-families","google","quad9","quad9-unfiltered","opendns","opendns-familyshield","adguard","adguard-unfiltered","cleanbrowsing-security","controld","nextdns","dns4eu","dns-sb","hurricane-electric","lumen","vercara","ntt","ca-cira-shield","ca-bell","us-att","br-uol","co-colombia-telecomunicaciones","cl-gtd","de-digitalcourage","de-freifunk-muc","de-dnswatch","cz-nic-odvr","ch-swisscom","pl-atman","na-mtc","ru-yandex","ir-shecan","ir-electro","om-ooredoo","tr-teknet","ke-safaricom","ng-mtn","bf-onatel","in-nic-public-dns","bd-mango","pk-ntc","kr-kt","cn-114dns","cn-alidns","tw-hinet","id-telkom","au-telstra","authoritative"]},"examples":{"example-a":{"summary":"A records of example.com","value":"cloudflare"},"google-mx":{"summary":"Mail servers of google.com","value":"google"},"cloudflare-all":{"summary":"Common records of cloudflare.com","value":"cloudflare"},"github-cname":{"summary":"CNAME of www.github.com","value":"cloudflare"},"cloudflare-dnskey":{"summary":"DNSKEY of cloudflare.com with DNSSEC","value":"cloudflare"},"google-dns-ptr":{"summary":"Reverse lookup of 8.8.8.8","value":"cloudflare"},"cloudflare-aaaa":{"summary":"IPv6 addresses of cloudflare.com","value":"cloudflare"},"cloudflare-ns":{"summary":"Nameservers of cloudflare.com","value":"cloudflare"},"google-txt":{"summary":"TXT records of google.com","value":"cloudflare"},"example-soa":{"summary":"SOA record of example.com","value":"cloudflare"},"google-caa":{"summary":"CAA records of google.com","value":"cloudflare"},"cloudflare-ds":{"summary":"DS record of cloudflare.com","value":"cloudflare"}},"style":"form","explode":true},{"name":"dnssec","in":"query","required":false,"description":"Set the DNSSEC OK bit: include RRSIG records and report whether the resolver validated the answer (AD flag).","schema":{"default":false,"type":"boolean"},"examples":{"example-a":{"summary":"A records of example.com","value":false},"google-mx":{"summary":"Mail servers of google.com","value":false},"cloudflare-all":{"summary":"Common records of cloudflare.com","value":false},"github-cname":{"summary":"CNAME of www.github.com","value":false},"cloudflare-dnskey":{"summary":"DNSKEY of cloudflare.com with DNSSEC","value":true},"google-dns-ptr":{"summary":"Reverse lookup of 8.8.8.8","value":false},"cloudflare-aaaa":{"summary":"IPv6 addresses of cloudflare.com","value":false},"cloudflare-ns":{"summary":"Nameservers of cloudflare.com","value":false},"google-txt":{"summary":"TXT records of google.com","value":false},"example-soa":{"summary":"SOA record of example.com","value":false},"google-caa":{"summary":"CAA records of google.com","value":false},"cloudflare-ds":{"summary":"DS record of cloudflare.com","value":true}},"style":"form","explode":true},{"name":"fresh","in":"query","required":false,"description":"Bypass the cache (costs 3x, limited to 10 per hour per network).","schema":{"type":"boolean","default":false}},{"name":"format","in":"query","required":false,"description":"`text` returns the plain-text summary instead of JSON.","schema":{"enum":["json","text"],"default":"json"}}],"responses":{"200":{"description":"The result.","headers":{"RateLimit":{"description":"Remaining tool-cost units: `\"cost\";r=<remaining>;t=<seconds until full>`.","schema":{"type":"string"}},"RateLimit-Policy":{"description":"Quota: `\"cost\";q=<units>;w=<seconds>`.","schema":{"type":"string"}},"X-Request-Id":{"description":"Request id, also in the body.","schema":{"type":"string"}},"ETag":{"description":"Weak validator for conditional requests.","schema":{"type":"string"}},"Link":{"description":"Permalink to the web page (rel=alternate).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DnsLookupResult"}}}},"304":{"description":"Not modified (If-None-Match matched)."},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}},"post":{"operationId":"dns_lookup_post","summary":"DNS Lookup (JSON body)","description":"Same as GET, with the input as a JSON body. Never cached. Add `?fresh=1` to bypass the cache where supported.","tags":["dns"],"x-mcp-tool":"dns_lookup","x-cost":{"lane":"dns","miss":"variable","hit":1},"x-cache-ttl":"dynamic","x-cache-scope":"public","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DnsLookupInput"},"examples":{"example-a":{"summary":"A records of example.com","value":{"name":"example.com","type":"A","resolver":"cloudflare","dnssec":false}},"google-mx":{"summary":"Mail servers of google.com","value":{"name":"google.com","type":"MX","resolver":"google","dnssec":false}},"cloudflare-all":{"summary":"Common records of cloudflare.com","value":{"name":"cloudflare.com","type":"ALL","resolver":"cloudflare","dnssec":false}},"github-cname":{"summary":"CNAME of www.github.com","value":{"name":"www.github.com","type":"CNAME","resolver":"cloudflare","dnssec":false}},"cloudflare-dnskey":{"summary":"DNSKEY of cloudflare.com with DNSSEC","value":{"name":"cloudflare.com","type":"DNSKEY","resolver":"cloudflare","dnssec":true}},"google-dns-ptr":{"summary":"Reverse lookup of 8.8.8.8","value":{"name":"8.8.8.8","type":"PTR","resolver":"cloudflare","dnssec":false}},"cloudflare-aaaa":{"summary":"IPv6 addresses of cloudflare.com","value":{"name":"cloudflare.com","type":"AAAA","resolver":"cloudflare","dnssec":false}},"cloudflare-ns":{"summary":"Nameservers of cloudflare.com","value":{"name":"cloudflare.com","type":"NS","resolver":"cloudflare","dnssec":false}},"google-txt":{"summary":"TXT records of google.com","value":{"name":"google.com","type":"TXT","resolver":"cloudflare","dnssec":false}},"example-soa":{"summary":"SOA record of example.com","value":{"name":"example.com","type":"SOA","resolver":"cloudflare","dnssec":false}},"google-caa":{"summary":"CAA records of google.com","value":{"name":"google.com","type":"CAA","resolver":"cloudflare","dnssec":false}},"cloudflare-ds":{"summary":"DS record of cloudflare.com","value":{"name":"cloudflare.com","type":"DS","resolver":"cloudflare","dnssec":true}}}}}},"responses":{"200":{"description":"The result.","headers":{"RateLimit":{"description":"Remaining tool-cost units: `\"cost\";r=<remaining>;t=<seconds until full>`.","schema":{"type":"string"}},"RateLimit-Policy":{"description":"Quota: `\"cost\";q=<units>;w=<seconds>`.","schema":{"type":"string"}},"X-Request-Id":{"description":"Request id, also in the body.","schema":{"type":"string"}},"ETag":{"description":"Weak validator for conditional requests.","schema":{"type":"string"}},"Link":{"description":"Permalink to the web page (rel=alternate).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DnsLookupResult"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/api/v1/tools/dns-propagation":{"get":{"operationId":"dns_propagation","summary":"DNS Propagation Checker","description":"Ask dozens of public DNS resolvers (anycast services and regional/ISP resolvers in many countries) for the same record and compare the answers with the authoritative nameserver or an expected value. Returns per-resolver status (current, stale, empty, nxdomain, servfail, timeout), answers, remaining TTL and latency, the distinct answer sets with how many resolvers serve each, a one-line verdict and when stale caches should expire. Returns what finished at the deadline with incomplete=true. Use it after changing A, CNAME, MX, NS or TXT records.\n\nNot for: A single quick lookup (use dns_lookup) or checking SPF/DMARC syntax.","tags":["dns"],"x-mcp-tool":"dns_propagation","x-cost":{"lane":"dns","miss":12,"hit":1},"x-cache-ttl":"dynamic","x-cache-scope":"public","parameters":[{"name":"name","in":"query","required":true,"description":"Host name to check, e.g. www.example.com. A URL or e-mail address is reduced to its host; Unicode names are converted to Punycode.","schema":{"type":"string","maxLength":253},"examples":{"example-a":{"summary":"A record of example.com","value":"example.com"},"google-mx":{"summary":"MX records of google.com","value":"google.com"},"cloudflare-ns":{"summary":"Nameservers of cloudflare.com","value":"cloudflare.com"},"expected-ip":{"summary":"Has my new IP arrived?","value":"example.com"}},"style":"form","explode":true},{"name":"type","in":"query","required":false,"description":"Record type to compare across resolvers.","schema":{"default":"A","type":"string","enum":["A","AAAA","CNAME","MX","NS","TXT","SOA","CAA","SRV","DS","DNSKEY","HTTPS"]},"examples":{"example-a":{"summary":"A record of example.com","value":"A"},"google-mx":{"summary":"MX records of google.com","value":"MX"},"cloudflare-ns":{"summary":"Nameservers of cloudflare.com","value":"NS"},"expected-ip":{"summary":"Has my new IP arrived?","value":"A"}},"style":"form","explode":true},{"name":"expected","in":"query","required":false,"description":"The value you expect to see after your change, e.g. a new IP address. Resolvers whose answers include it count as current. For address and name records the whole value must match; for TXT and other text records a substring is enough. Without it the authoritative answer is the reference.","schema":{"type":"string","maxLength":512},"examples":{"expected-ip":{"summary":"Has my new IP arrived?","value":"93.184.216.34"}},"style":"form","explode":true},{"name":"fresh","in":"query","required":false,"description":"Bypass the cache (costs 3x, limited to 10 per hour per network).","schema":{"type":"boolean","default":false}},{"name":"format","in":"query","required":false,"description":"`text` returns the plain-text summary instead of JSON.","schema":{"enum":["json","text"],"default":"json"}}],"responses":{"200":{"description":"The result.","headers":{"RateLimit":{"description":"Remaining tool-cost units: `\"cost\";r=<remaining>;t=<seconds until full>`.","schema":{"type":"string"}},"RateLimit-Policy":{"description":"Quota: `\"cost\";q=<units>;w=<seconds>`.","schema":{"type":"string"}},"X-Request-Id":{"description":"Request id, also in the body.","schema":{"type":"string"}},"ETag":{"description":"Weak validator for conditional requests.","schema":{"type":"string"}},"Link":{"description":"Permalink to the web page (rel=alternate).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DnsPropagationResult"}}}},"304":{"description":"Not modified (If-None-Match matched)."},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}},"post":{"operationId":"dns_propagation_post","summary":"DNS Propagation Checker (JSON body)","description":"Same as GET, with the input as a JSON body. Never cached. Add `?fresh=1` to bypass the cache where supported.","tags":["dns"],"x-mcp-tool":"dns_propagation","x-cost":{"lane":"dns","miss":12,"hit":1},"x-cache-ttl":"dynamic","x-cache-scope":"public","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DnsPropagationInput"},"examples":{"example-a":{"summary":"A record of example.com","value":{"name":"example.com","type":"A"}},"google-mx":{"summary":"MX records of google.com","value":{"name":"google.com","type":"MX"}},"cloudflare-ns":{"summary":"Nameservers of cloudflare.com","value":{"name":"cloudflare.com","type":"NS"}},"expected-ip":{"summary":"Has my new IP arrived?","value":{"name":"example.com","type":"A","expected":"93.184.216.34"}}}}}},"responses":{"200":{"description":"The result.","headers":{"RateLimit":{"description":"Remaining tool-cost units: `\"cost\";r=<remaining>;t=<seconds until full>`.","schema":{"type":"string"}},"RateLimit-Policy":{"description":"Quota: `\"cost\";q=<units>;w=<seconds>`.","schema":{"type":"string"}},"X-Request-Id":{"description":"Request id, also in the body.","schema":{"type":"string"}},"ETag":{"description":"Weak validator for conditional requests.","schema":{"type":"string"}},"Link":{"description":"Permalink to the web page (rel=alternate).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DnsPropagationResult"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/api/v1/tools/domain-availability":{"get":{"operationId":"domain_availability","summary":"Domain Availability Checker","description":"Check whether a domain name looks free to register. Give a bare name (\"acme\") and up to 10 extensions, or a full domain (\"acme.io\"). Each candidate is asked of its registry over RDAP (WHOIS where an extension has no RDAP) and gets a verdict: registered, likely-available, likely-available-whois, or unknown when the registry could not be checked (never treated as available). Registered names include registrar, expiry and lifecycle stage; likely-available names include caveats (premium, reserved or restricted names can still be unavailable) and non-affiliate registrar search links. Searched names are not logged or shared.\n\nNot for: Buying or reserving a name, prices, or the full record of a registered domain (use whois_lookup).","tags":["domain"],"x-mcp-tool":"domain_availability","x-cost":{"lane":"rdap","miss":"variable","hit":1},"x-cache-ttl":"dynamic","x-cache-scope":"public","parameters":[{"name":"name","in":"query","required":true,"description":"A bare name such as \"acme\" (checked under tlds), or a full domain such as \"acme.io\" (checked as is, plus its name under any extra tlds). URLs and e-mail addresses are reduced to their domain.","schema":{"type":"string","minLength":1,"maxLength":512},"examples":{"popular-tlds":{"summary":"acme under .com, .net and .org","value":"acme"},"full-domain":{"summary":"One full domain","value":"example.com"},"default-tlds":{"summary":"A bare name under the default extensions","value":"lookupowl"},"unicode-name":{"summary":"A Unicode name under .de and .com","value":"bücher"}},"style":"form","explode":true},{"name":"tlds","in":"query","required":false,"description":"Extensions to check, without the dot, e.g. [\"com\",\"dev\",\"co.uk\"] (\"com,dev\" also works); at most 10. Empty means com, net, org, io and ai for a bare name.","schema":{"default":[],"maxItems":10,"type":"array","items":{"type":"string","maxLength":126}},"examples":{"popular-tlds":{"summary":"acme under .com, .net and .org","value":["com","net","org"]},"full-domain":{"summary":"One full domain","value":[]},"default-tlds":{"summary":"A bare name under the default extensions","value":[]},"unicode-name":{"summary":"A Unicode name under .de and .com","value":["de","com"]}},"style":"form","explode":true},{"name":"fresh","in":"query","required":false,"description":"Bypass the cache (costs 3x, limited to 10 per hour per network).","schema":{"type":"boolean","default":false}},{"name":"format","in":"query","required":false,"description":"`text` returns the plain-text summary instead of JSON.","schema":{"enum":["json","text"],"default":"json"}}],"responses":{"200":{"description":"The result.","headers":{"RateLimit":{"description":"Remaining tool-cost units: `\"cost\";r=<remaining>;t=<seconds until full>`.","schema":{"type":"string"}},"RateLimit-Policy":{"description":"Quota: `\"cost\";q=<units>;w=<seconds>`.","schema":{"type":"string"}},"X-Request-Id":{"description":"Request id, also in the body.","schema":{"type":"string"}},"ETag":{"description":"Weak validator for conditional requests.","schema":{"type":"string"}},"Link":{"description":"Permalink to the web page (rel=alternate).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainAvailabilityResult"}}}},"304":{"description":"Not modified (If-None-Match matched)."},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}},"post":{"operationId":"domain_availability_post","summary":"Domain Availability Checker (JSON body)","description":"Same as GET, with the input as a JSON body. Never cached. Add `?fresh=1` to bypass the cache where supported.","tags":["domain"],"x-mcp-tool":"domain_availability","x-cost":{"lane":"rdap","miss":"variable","hit":1},"x-cache-ttl":"dynamic","x-cache-scope":"public","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainAvailabilityInput"},"examples":{"popular-tlds":{"summary":"acme under .com, .net and .org","value":{"name":"acme","tlds":["com","net","org"]}},"full-domain":{"summary":"One full domain","value":{"name":"example.com","tlds":[]}},"default-tlds":{"summary":"A bare name under the default extensions","value":{"name":"lookupowl","tlds":[]}},"unicode-name":{"summary":"A Unicode name under .de and .com","value":{"name":"bücher","tlds":["de","com"]}}}}}},"responses":{"200":{"description":"The result.","headers":{"RateLimit":{"description":"Remaining tool-cost units: `\"cost\";r=<remaining>;t=<seconds until full>`.","schema":{"type":"string"}},"RateLimit-Policy":{"description":"Quota: `\"cost\";q=<units>;w=<seconds>`.","schema":{"type":"string"}},"X-Request-Id":{"description":"Request id, also in the body.","schema":{"type":"string"}},"ETag":{"description":"Weak validator for conditional requests.","schema":{"type":"string"}},"Link":{"description":"Permalink to the web page (rel=alternate).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainAvailabilityResult"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/api/v1/tools/domain-report":{"get":{"operationId":"domain_report","summary":"Domain Report: Registration, DNS, Web, Hosting and Email","description":"A one-call overview of a domain that runs LookupOwl's own tools and scores what they find: registration (registrar, age, expiry, holds), DNS (nameservers, addresses, mail records, DNSSEC), web (TLS certificate and a security-headers grade), hosting (host or CDN, DNS and email provider, whether the origin is hidden) and email (SPF, DMARC, DKIM discovery and a blocklist check of the mail servers). Returns an overall score, one score and headline per area, the findings, the key facts and, for every part, whether it worked and the path of the full tool. A part that fails is marked and the rest still arrive. Costs more than a single lookup; pick sections to cut it.\n\nNot for: IP addresses (use ip_location), a deep look at one area (use the tool for it: whois_lookup, dns_lookup, ssl_check, security_headers, website_hosting, spf_check, dmarc_check, dkim_check, blacklist_check) or monitoring over time.","tags":["domain"],"x-mcp-tool":"domain_report","x-cost":{"lane":"http","miss":"variable","hit":1},"x-cache-ttl":"dynamic","x-cache-scope":"public","parameters":[{"name":"domain","in":"query","required":true,"description":"Domain to report on, e.g. example.com. A URL or e-mail address is reduced to its host; Unicode names are converted to Punycode. IP addresses are not accepted (use ip_location).","schema":{"type":"string","maxLength":253},"examples":{"example-com":{"summary":"example.com, every section","value":"example.com"},"github-com":{"summary":"github.com, every section","value":"github.com"},"registration-dns":{"summary":"wikipedia.org, registration and DNS only (cheap)","value":"wikipedia.org"}},"style":"form","explode":true},{"name":"sections","in":"query","required":false,"description":"Which sections to run: registration, dns, web (certificate and security headers), hosting and email (SPF, DMARC, DKIM, blocklists). Default all. Fewer sections cost less.","schema":{"default":["registration","dns","web","hosting","email"],"minItems":1,"maxItems":5,"type":"array","items":{"type":"string","enum":["registration","dns","web","hosting","email"]}},"examples":{"example-com":{"summary":"example.com, every section","value":["registration","dns","web","hosting","email"]},"github-com":{"summary":"github.com, every section","value":["registration","dns","web","hosting","email"]},"registration-dns":{"summary":"wikipedia.org, registration and DNS only (cheap)","value":["registration","dns"]}},"style":"form","explode":true},{"name":"format","in":"query","required":false,"description":"`text` returns the plain-text summary instead of JSON.","schema":{"enum":["json","text"],"default":"json"}}],"responses":{"200":{"description":"The result.","headers":{"RateLimit":{"description":"Remaining tool-cost units: `\"cost\";r=<remaining>;t=<seconds until full>`.","schema":{"type":"string"}},"RateLimit-Policy":{"description":"Quota: `\"cost\";q=<units>;w=<seconds>`.","schema":{"type":"string"}},"X-Request-Id":{"description":"Request id, also in the body.","schema":{"type":"string"}},"ETag":{"description":"Weak validator for conditional requests.","schema":{"type":"string"}},"Link":{"description":"Permalink to the web page (rel=alternate).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainReportResult"}}}},"304":{"description":"Not modified (If-None-Match matched)."},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}},"post":{"operationId":"domain_report_post","summary":"Domain Report: Registration, DNS, Web, Hosting and Email (JSON body)","description":"Same as GET, with the input as a JSON body. Never cached. Add `?fresh=1` to bypass the cache where supported.","tags":["domain"],"x-mcp-tool":"domain_report","x-cost":{"lane":"http","miss":"variable","hit":1},"x-cache-ttl":"dynamic","x-cache-scope":"public","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainReportInput"},"examples":{"example-com":{"summary":"example.com, every section","value":{"domain":"example.com","sections":["registration","dns","web","hosting","email"]}},"github-com":{"summary":"github.com, every section","value":{"domain":"github.com","sections":["registration","dns","web","hosting","email"]}},"registration-dns":{"summary":"wikipedia.org, registration and DNS only (cheap)","value":{"domain":"wikipedia.org","sections":["registration","dns"]}}}}}},"responses":{"200":{"description":"The result.","headers":{"RateLimit":{"description":"Remaining tool-cost units: `\"cost\";r=<remaining>;t=<seconds until full>`.","schema":{"type":"string"}},"RateLimit-Policy":{"description":"Quota: `\"cost\";q=<units>;w=<seconds>`.","schema":{"type":"string"}},"X-Request-Id":{"description":"Request id, also in the body.","schema":{"type":"string"}},"ETag":{"description":"Weak validator for conditional requests.","schema":{"type":"string"}},"Link":{"description":"Permalink to the web page (rel=alternate).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainReportResult"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/api/v1/tools/epp-status":{"get":{"operationId":"epp_status","summary":"EPP Status Codes","description":"Explain domain registration status codes (EPP or RDAP spelling, any case, or lines pasted from a WHOIS record). For each code: a plain-English meaning, who sets it (registrar or registry), a severity, what the owner should do, what a buyer should know, how to remove it, and where it sits in the domain lifecycle. A set of codes also gets an interpretation, for example a full registrar lock or a domain on hold. Unrecognised values are reported as such, not guessed. Pure reference data: no network access, instant.\n\nNot for: Looking up the statuses of a particular domain (use whois_lookup, which includes these explanations).","tags":["domain"],"x-mcp-tool":"epp_status","x-cost":{"lane":"cpu","miss":1,"hit":1},"x-cache-ttl":86400,"x-cache-scope":"public","parameters":[{"name":"codes","in":"query","required":true,"description":"Status codes in EPP (clientTransferProhibited) or RDAP (\"client transfer prohibited\") spelling, any case. Lines copied from a WHOIS record work too, with or without the \"Domain Status:\" label and the icann.org link. Commas, semicolons and line breaks separate codes.","schema":{"minItems":1,"maxItems":20,"type":"array","items":{"type":"string","maxLength":500}},"examples":{"transfer-lock":{"summary":"clientTransferProhibited","value":["clientTransferProhibited"]},"expiry-path":{"summary":"redemptionPeriod and pendingDelete","value":["redemptionPeriod","pendingDelete"]},"rdap-spelling":{"summary":"RDAP spelling: client hold","value":["client hold"]},"full-lock":{"summary":"The three registrar locks together","value":["clientDeleteProhibited","clientTransferProhibited","clientUpdateProhibited"]}},"style":"form","explode":true},{"name":"format","in":"query","required":false,"description":"`text` returns the plain-text summary instead of JSON.","schema":{"enum":["json","text"],"default":"json"}}],"responses":{"200":{"description":"The result.","headers":{"RateLimit":{"description":"Remaining tool-cost units: `\"cost\";r=<remaining>;t=<seconds until full>`.","schema":{"type":"string"}},"RateLimit-Policy":{"description":"Quota: `\"cost\";q=<units>;w=<seconds>`.","schema":{"type":"string"}},"X-Request-Id":{"description":"Request id, also in the body.","schema":{"type":"string"}},"ETag":{"description":"Weak validator for conditional requests.","schema":{"type":"string"}},"Link":{"description":"Permalink to the web page (rel=alternate).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EppStatusResult"}}}},"304":{"description":"Not modified (If-None-Match matched)."},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}},"post":{"operationId":"epp_status_post","summary":"EPP Status Codes (JSON body)","description":"Same as GET, with the input as a JSON body. Never cached. Add `?fresh=1` to bypass the cache where supported.","tags":["domain"],"x-mcp-tool":"epp_status","x-cost":{"lane":"cpu","miss":1,"hit":1},"x-cache-ttl":86400,"x-cache-scope":"public","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EppStatusInput"},"examples":{"transfer-lock":{"summary":"clientTransferProhibited","value":{"codes":["clientTransferProhibited"]}},"expiry-path":{"summary":"redemptionPeriod and pendingDelete","value":{"codes":["redemptionPeriod","pendingDelete"]}},"rdap-spelling":{"summary":"RDAP spelling: client hold","value":{"codes":["client hold"]}},"full-lock":{"summary":"The three registrar locks together","value":{"codes":["clientDeleteProhibited","clientTransferProhibited","clientUpdateProhibited"]}}}}}},"responses":{"200":{"description":"The result.","headers":{"RateLimit":{"description":"Remaining tool-cost units: `\"cost\";r=<remaining>;t=<seconds until full>`.","schema":{"type":"string"}},"RateLimit-Policy":{"description":"Quota: `\"cost\";q=<units>;w=<seconds>`.","schema":{"type":"string"}},"X-Request-Id":{"description":"Request id, also in the body.","schema":{"type":"string"}},"ETag":{"description":"Weak validator for conditional requests.","schema":{"type":"string"}},"Link":{"description":"Permalink to the web page (rel=alternate).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EppStatusResult"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/api/v1/tools/http-headers":{"get":{"operationId":"http_headers","summary":"HTTP Headers Checker","description":"Fetch a public http(s) URL from our server and return the redirect chain hop by hop (status, headers, server IP, timing), loop and downgrade detection, and an analysis of the final response: graded security headers (HSTS, CSP, X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Permissions-Policy), cache semantics, cookie flags, server software and CDN. A bare host tries https first, then http. Follows at most 10 redirects; private and internal addresses are refused. Requests go out over HTTP/1.1 (the httpVersion field), so it does not show which protocol a site supports: an h3 entry in the alt-svc header means it offers HTTP/3. Response bodies are never kept.\n\nNot for: Certificates (use ssl_check), DNS records (use dns_lookup) or page content.","tags":["web"],"x-mcp-tool":"http_headers","x-cost":{"lane":"http","miss":3,"hit":1},"x-cache-ttl":120,"x-cache-scope":"public","parameters":[{"name":"url","in":"query","required":true,"description":"URL or host to fetch, e.g. https://example.com/page or example.com (https is tried first, then http). Only public http(s) addresses on ports 80, 443, 8080 and 8443 are fetched; private, loopback and internal addresses are refused.","schema":{"type":"string","maxLength":2048},"examples":{"example-com":{"summary":"Headers of example.com","value":"https://example.com/"},"http-to-https":{"summary":"Follow the redirect from http to https","value":"http://github.com"},"head-only":{"summary":"Headers only (HEAD)","value":"https://www.cloudflare.com/"},"first-hop":{"summary":"Stop at the first redirect","value":"http://google.com"}},"style":"form","explode":true},{"name":"method","in":"query","required":false,"description":"GET shows what a browser receives; HEAD asks for headers only (a few servers answer it differently).","schema":{"default":"GET","type":"string","enum":["GET","HEAD"]},"examples":{"example-com":{"summary":"Headers of example.com","value":"GET"},"http-to-https":{"summary":"Follow the redirect from http to https","value":"GET"},"head-only":{"summary":"Headers only (HEAD)","value":"HEAD"},"first-hop":{"summary":"Stop at the first redirect","value":"GET"}},"style":"form","explode":true},{"name":"followRedirects","in":"query","required":false,"description":"Follow redirects (up to 10 hops, each checked again) or stop at the first response.","schema":{"default":true,"type":"boolean"},"examples":{"example-com":{"summary":"Headers of example.com","value":true},"http-to-https":{"summary":"Follow the redirect from http to https","value":true},"head-only":{"summary":"Headers only (HEAD)","value":true},"first-hop":{"summary":"Stop at the first redirect","value":false}},"style":"form","explode":true},{"name":"fresh","in":"query","required":false,"description":"Bypass the cache (costs 3x, limited to 10 per hour per network).","schema":{"type":"boolean","default":false}},{"name":"format","in":"query","required":false,"description":"`text` returns the plain-text summary instead of JSON.","schema":{"enum":["json","text"],"default":"json"}}],"responses":{"200":{"description":"The result.","headers":{"RateLimit":{"description":"Remaining tool-cost units: `\"cost\";r=<remaining>;t=<seconds until full>`.","schema":{"type":"string"}},"RateLimit-Policy":{"description":"Quota: `\"cost\";q=<units>;w=<seconds>`.","schema":{"type":"string"}},"X-Request-Id":{"description":"Request id, also in the body.","schema":{"type":"string"}},"ETag":{"description":"Weak validator for conditional requests.","schema":{"type":"string"}},"Link":{"description":"Permalink to the web page (rel=alternate).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpHeadersResult"}}}},"304":{"description":"Not modified (If-None-Match matched)."},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}},"post":{"operationId":"http_headers_post","summary":"HTTP Headers Checker (JSON body)","description":"Same as GET, with the input as a JSON body. Never cached. Add `?fresh=1` to bypass the cache where supported.","tags":["web"],"x-mcp-tool":"http_headers","x-cost":{"lane":"http","miss":3,"hit":1},"x-cache-ttl":120,"x-cache-scope":"public","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpHeadersInput"},"examples":{"example-com":{"summary":"Headers of example.com","value":{"url":"https://example.com/","method":"GET","followRedirects":true}},"http-to-https":{"summary":"Follow the redirect from http to https","value":{"url":"http://github.com","method":"GET","followRedirects":true}},"head-only":{"summary":"Headers only (HEAD)","value":{"url":"https://www.cloudflare.com/","method":"HEAD","followRedirects":true}},"first-hop":{"summary":"Stop at the first redirect","value":{"url":"http://google.com","method":"GET","followRedirects":false}}}}}},"responses":{"200":{"description":"The result.","headers":{"RateLimit":{"description":"Remaining tool-cost units: `\"cost\";r=<remaining>;t=<seconds until full>`.","schema":{"type":"string"}},"RateLimit-Policy":{"description":"Quota: `\"cost\";q=<units>;w=<seconds>`.","schema":{"type":"string"}},"X-Request-Id":{"description":"Request id, also in the body.","schema":{"type":"string"}},"ETag":{"description":"Weak validator for conditional requests.","schema":{"type":"string"}},"Link":{"description":"Permalink to the web page (rel=alternate).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpHeadersResult"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/api/v1/tools/ip-convert":{"get":{"operationId":"ip_convert","summary":"IP Address Converter","description":"Convert IP addresses between notations. IPv4 or IPv6 to unsigned integer, hex and binary (and back from integers), with the signed 32-bit value for databases. IPv4 returns every standard IPv6 embedding: IPv4-mapped, NAT64 (well-known, local-use and your own prefix), 6to4, deprecated IPv4-compatible and ISATAP. IPv6 returns the embedded IPv4 and its type (mapped, NAT64, 6to4, Teredo with server/client/port, ISATAP) or \"none\" for native addresses. Up to 500 addresses. Pure calculation, no network access.\n\nNot for: Getting a working IPv6 address for a server (conversion does not create one) or looking up an address owner (use ip_whois).","tags":["ip"],"x-mcp-tool":"ip_convert","x-cost":{"lane":"cpu","miss":1,"hit":1},"x-cache-ttl":86400,"x-cache-scope":"public","parameters":[{"name":"address","in":"query","required":true,"description":"One or more IP addresses, one per line (commas and spaces also separate), up to 500. IPv4 dotted quads, IPv6 in any form, or integers written as decimal (3232235777), 0x hex (0xc0a80101) or 0b binary. Leading zeros in a dotted quad are rejected because they are ambiguous.","schema":{"type":"string","maxLength":32768},"examples":{"ipv4-decimal":{"summary":"IPv4 address to decimal","value":"192.168.1.1"},"decimal-to-ip":{"summary":"Integer back to an address","value":"3232235777\n0xc0a80101"},"v4-to-v6":{"summary":"IPv4 inside IPv6","value":"192.0.2.33"},"v6-to-v4":{"summary":"Find the IPv4 in an IPv6 address","value":"::ffff:192.0.2.1\n64:ff9b::8.8.8.8\n2001:0:4136:e378:8000:63bf:3fff:fdd2\n2606:4700:4700::1111"}},"style":"form","explode":true},{"name":"mode","in":"query","required":false,"description":"decimal: integer, hex and binary forms. v4-to-v6: IPv6 embeddings of IPv4 addresses. v6-to-v4: extract the IPv4 inside IPv6 addresses. all: whatever applies.","schema":{"default":"all","type":"string","enum":["all","decimal","v4-to-v6","v6-to-v4"]},"examples":{"ipv4-decimal":{"summary":"IPv4 address to decimal","value":"decimal"},"decimal-to-ip":{"summary":"Integer back to an address","value":"decimal"},"v4-to-v6":{"summary":"IPv4 inside IPv6","value":"v4-to-v6"},"v6-to-v4":{"summary":"Find the IPv4 in an IPv6 address","value":"v6-to-v4"}},"style":"form","explode":true},{"name":"nat64Prefix","in":"query","required":false,"description":"Your own NAT64 prefix (/32, /40, /48, /56, /64 or /96, RFC 6052), e.g. 2001:db8:64::/96, used to embed and to extract.","schema":{"type":"string","maxLength":64},"style":"form","explode":true},{"name":"format","in":"query","required":false,"description":"`text` returns the plain-text summary instead of JSON.","schema":{"enum":["json","text"],"default":"json"}}],"responses":{"200":{"description":"The result.","headers":{"RateLimit":{"description":"Remaining tool-cost units: `\"cost\";r=<remaining>;t=<seconds until full>`.","schema":{"type":"string"}},"RateLimit-Policy":{"description":"Quota: `\"cost\";q=<units>;w=<seconds>`.","schema":{"type":"string"}},"X-Request-Id":{"description":"Request id, also in the body.","schema":{"type":"string"}},"ETag":{"description":"Weak validator for conditional requests.","schema":{"type":"string"}},"Link":{"description":"Permalink to the web page (rel=alternate).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IpConvertResult"}}}},"304":{"description":"Not modified (If-None-Match matched)."},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}},"post":{"operationId":"ip_convert_post","summary":"IP Address Converter (JSON body)","description":"Same as GET, with the input as a JSON body. Never cached. Add `?fresh=1` to bypass the cache where supported.","tags":["ip"],"x-mcp-tool":"ip_convert","x-cost":{"lane":"cpu","miss":1,"hit":1},"x-cache-ttl":86400,"x-cache-scope":"public","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IpConvertInput"},"examples":{"ipv4-decimal":{"summary":"IPv4 address to decimal","value":{"address":"192.168.1.1","mode":"decimal"}},"decimal-to-ip":{"summary":"Integer back to an address","value":{"address":"3232235777\n0xc0a80101","mode":"decimal"}},"v4-to-v6":{"summary":"IPv4 inside IPv6","value":{"address":"192.0.2.33","mode":"v4-to-v6"}},"v6-to-v4":{"summary":"Find the IPv4 in an IPv6 address","value":{"address":"::ffff:192.0.2.1\n64:ff9b::8.8.8.8\n2001:0:4136:e378:8000:63bf:3fff:fdd2\n2606:4700:4700::1111","mode":"v6-to-v4"}}}}}},"responses":{"200":{"description":"The result.","headers":{"RateLimit":{"description":"Remaining tool-cost units: `\"cost\";r=<remaining>;t=<seconds until full>`.","schema":{"type":"string"}},"RateLimit-Policy":{"description":"Quota: `\"cost\";q=<units>;w=<seconds>`.","schema":{"type":"string"}},"X-Request-Id":{"description":"Request id, also in the body.","schema":{"type":"string"}},"ETag":{"description":"Weak validator for conditional requests.","schema":{"type":"string"}},"Link":{"description":"Permalink to the web page (rel=alternate).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IpConvertResult"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/api/v1/tools/ip-location":{"get":{"operationId":"ip_location","summary":"IP Location Lookup","description":"Locate an IP address, or every address of a domain, using the free DB-IP Lite city and ASN databases. Accepts an IPv4 or IPv6 address, a domain name or a URL. A domain is resolved and up to 6 of its addresses are located. Returns city, region, country, continent, approximate coordinates with a typical radius, the AS number and organisation, the country the address block is registered in (RDAP) and whether it agrees with the DB-IP location, and a flag for well-known anycast and CDN addresses. IP location is approximate: VPNs, mobile networks and carrier-grade NAT put people in other cities. Private and reserved addresses return status special_purpose. The result carries the attribution \"IP geolocation by DB-IP\" (https://db-ip.com) that the data licence (CC BY 4.0) requires; show it wherever you show the data. While the databases are still downloading, the call fails with UNAVAILABLE.\n\nNot for: Street-level or device location, who owns an address (use ip_whois), reverse DNS (use reverse_dns) or finding who hosts a website (use website_hosting).","tags":["ip"],"x-mcp-tool":"ip_location","x-cost":{"lane":"dns","miss":"variable","hit":1},"x-cache-ttl":"dynamic","x-cache-scope":"public","parameters":[{"name":"q","in":"query","required":true,"description":"An IPv4 or IPv6 address, a domain name, or a URL (the host is used). A domain is resolved and each of its addresses (up to 6) is located. Private and reserved addresses are answered as special-purpose, not looked up.","schema":{"type":"string","maxLength":2048},"examples":{"google-dns":{"summary":"Google Public DNS (8.8.8.8), an anycast address","value":"8.8.8.8"},"domain":{"summary":"Every address of a domain","value":"example.com"},"ipv6":{"summary":"An IPv6 address","value":"2606:4700:4700::1111"},"private":{"summary":"A private address has no public location","value":"192.168.1.1"}},"style":"form","explode":true},{"name":"registry","in":"query","required":false,"description":"Also ask the Regional Internet Registry (RDAP) which country the address block is registered in, and compare it with the DB-IP location. One extra lookup per address, for the first three addresses.","schema":{"default":true,"type":"boolean"},"examples":{"google-dns":{"summary":"Google Public DNS (8.8.8.8), an anycast address","value":true},"domain":{"summary":"Every address of a domain","value":true},"ipv6":{"summary":"An IPv6 address","value":true},"private":{"summary":"A private address has no public location","value":true}},"style":"form","explode":true},{"name":"fresh","in":"query","required":false,"description":"Bypass the cache (costs 3x, limited to 10 per hour per network).","schema":{"type":"boolean","default":false}},{"name":"format","in":"query","required":false,"description":"`text` returns the plain-text summary instead of JSON.","schema":{"enum":["json","text"],"default":"json"}}],"responses":{"200":{"description":"The result.","headers":{"RateLimit":{"description":"Remaining tool-cost units: `\"cost\";r=<remaining>;t=<seconds until full>`.","schema":{"type":"string"}},"RateLimit-Policy":{"description":"Quota: `\"cost\";q=<units>;w=<seconds>`.","schema":{"type":"string"}},"X-Request-Id":{"description":"Request id, also in the body.","schema":{"type":"string"}},"ETag":{"description":"Weak validator for conditional requests.","schema":{"type":"string"}},"Link":{"description":"Permalink to the web page (rel=alternate).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IpLocationResult"}}}},"304":{"description":"Not modified (If-None-Match matched)."},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}},"post":{"operationId":"ip_location_post","summary":"IP Location Lookup (JSON body)","description":"Same as GET, with the input as a JSON body. Never cached. Add `?fresh=1` to bypass the cache where supported.","tags":["ip"],"x-mcp-tool":"ip_location","x-cost":{"lane":"dns","miss":"variable","hit":1},"x-cache-ttl":"dynamic","x-cache-scope":"public","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IpLocationInput"},"examples":{"google-dns":{"summary":"Google Public DNS (8.8.8.8), an anycast address","value":{"q":"8.8.8.8","registry":true}},"domain":{"summary":"Every address of a domain","value":{"q":"example.com","registry":true}},"ipv6":{"summary":"An IPv6 address","value":{"q":"2606:4700:4700::1111","registry":true}},"private":{"summary":"A private address has no public location","value":{"q":"192.168.1.1","registry":true}}}}}},"responses":{"200":{"description":"The result.","headers":{"RateLimit":{"description":"Remaining tool-cost units: `\"cost\";r=<remaining>;t=<seconds until full>`.","schema":{"type":"string"}},"RateLimit-Policy":{"description":"Quota: `\"cost\";q=<units>;w=<seconds>`.","schema":{"type":"string"}},"X-Request-Id":{"description":"Request id, also in the body.","schema":{"type":"string"}},"ETag":{"description":"Weak validator for conditional requests.","schema":{"type":"string"}},"Link":{"description":"Permalink to the web page (rel=alternate).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IpLocationResult"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/api/v1/tools/ip-range-convert":{"get":{"operationId":"ip_range_convert","summary":"CIDR / IP Range Converter","description":"Convert between CIDR notation and IP ranges for IPv4 and IPv6, in bulk (up to 1,000 lines and about 10,000 resulting blocks per call). A CIDR block returns its first and last address, exact size, netmask and wildcard. A start-end range returns the minimal exact list of CIDR blocks (at most 62 for IPv4, 254 for IPv6) plus the smallest single covering block and how many extra addresses it would admit. Accepts \"a - b\", \"a to b\" and short forms like 10.0.0.5-20. Pure calculation, no network access.\n\nNot for: Subnet details such as usable hosts and broadcast (use subnet_calculate) or merging many overlapping networks.","tags":["ip"],"x-mcp-tool":"ip_range_convert","x-cost":{"lane":"cpu","miss":1,"hit":1},"x-cache-ttl":86400,"x-cache-scope":"public","parameters":[{"name":"input","in":"query","required":true,"description":"One item per line (commas and semicolons also separate): CIDR blocks such as 10.0.0.0/24 or 2001:db8::/48, or ranges such as \"10.0.0.1 - 10.0.0.9\", \"10.0.0.5-20\", \"192.0.2.1 to 192.0.2.77\". IPv4 and IPv6, up to 1,000 items.","schema":{"type":"string","maxLength":65536},"examples":{"cidr4":{"summary":"IPv4 CIDR to range","value":"192.168.1.0/24\n10.0.0.0/22"},"range4":{"summary":"IPv4 range to CIDR","value":"10.0.0.5 - 10.0.0.20"},"cidr6":{"summary":"IPv6 prefix to range","value":"2001:db8::/32"},"range6":{"summary":"IPv6 range to prefixes","value":"2620:0:2d0:200::7-2620:0:2d0:2df::7"},"mixed-auto":{"summary":"Mixed list, auto-detected","value":"203.0.113.0/28\n198.51.100.10-198.51.100.20\n2001:db8::/126"}},"style":"form","explode":true},{"name":"mode","in":"query","required":false,"description":"auto detects each line; cidr-to-range expects CIDR blocks; range-to-cidr expects start-end ranges.","schema":{"default":"auto","type":"string","enum":["auto","cidr-to-range","range-to-cidr"]},"examples":{"cidr4":{"summary":"IPv4 CIDR to range","value":"cidr-to-range"},"range4":{"summary":"IPv4 range to CIDR","value":"range-to-cidr"},"cidr6":{"summary":"IPv6 prefix to range","value":"cidr-to-range"},"range6":{"summary":"IPv6 range to prefixes","value":"range-to-cidr"},"mixed-auto":{"summary":"Mixed list, auto-detected","value":"auto"}},"style":"form","explode":true},{"name":"family","in":"query","required":false,"description":"Only accept this IP family: 4, 6 or any.","schema":{"default":"any","type":"string","enum":["4","6","any"]},"examples":{"cidr4":{"summary":"IPv4 CIDR to range","value":"4"},"range4":{"summary":"IPv4 range to CIDR","value":"4"},"cidr6":{"summary":"IPv6 prefix to range","value":"6"},"range6":{"summary":"IPv6 range to prefixes","value":"6"},"mixed-auto":{"summary":"Mixed list, auto-detected","value":"any"}},"style":"form","explode":true},{"name":"format","in":"query","required":false,"description":"`text` returns the plain-text summary instead of JSON.","schema":{"enum":["json","text"],"default":"json"}}],"responses":{"200":{"description":"The result.","headers":{"RateLimit":{"description":"Remaining tool-cost units: `\"cost\";r=<remaining>;t=<seconds until full>`.","schema":{"type":"string"}},"RateLimit-Policy":{"description":"Quota: `\"cost\";q=<units>;w=<seconds>`.","schema":{"type":"string"}},"X-Request-Id":{"description":"Request id, also in the body.","schema":{"type":"string"}},"ETag":{"description":"Weak validator for conditional requests.","schema":{"type":"string"}},"Link":{"description":"Permalink to the web page (rel=alternate).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IpRangeConvertResult"}}}},"304":{"description":"Not modified (If-None-Match matched)."},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}},"post":{"operationId":"ip_range_convert_post","summary":"CIDR / IP Range Converter (JSON body)","description":"Same as GET, with the input as a JSON body. Never cached. Add `?fresh=1` to bypass the cache where supported.","tags":["ip"],"x-mcp-tool":"ip_range_convert","x-cost":{"lane":"cpu","miss":1,"hit":1},"x-cache-ttl":86400,"x-cache-scope":"public","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IpRangeConvertInput"},"examples":{"cidr4":{"summary":"IPv4 CIDR to range","value":{"input":"192.168.1.0/24\n10.0.0.0/22","mode":"cidr-to-range","family":"4"}},"range4":{"summary":"IPv4 range to CIDR","value":{"input":"10.0.0.5 - 10.0.0.20","mode":"range-to-cidr","family":"4"}},"cidr6":{"summary":"IPv6 prefix to range","value":{"input":"2001:db8::/32","mode":"cidr-to-range","family":"6"}},"range6":{"summary":"IPv6 range to prefixes","value":{"input":"2620:0:2d0:200::7-2620:0:2d0:2df::7","mode":"range-to-cidr","family":"6"}},"mixed-auto":{"summary":"Mixed list, auto-detected","value":{"input":"203.0.113.0/28\n198.51.100.10-198.51.100.20\n2001:db8::/126","mode":"auto","family":"any"}}}}}},"responses":{"200":{"description":"The result.","headers":{"RateLimit":{"description":"Remaining tool-cost units: `\"cost\";r=<remaining>;t=<seconds until full>`.","schema":{"type":"string"}},"RateLimit-Policy":{"description":"Quota: `\"cost\";q=<units>;w=<seconds>`.","schema":{"type":"string"}},"X-Request-Id":{"description":"Request id, also in the body.","schema":{"type":"string"}},"ETag":{"description":"Weak validator for conditional requests.","schema":{"type":"string"}},"Link":{"description":"Permalink to the web page (rel=alternate).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IpRangeConvertResult"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/api/v1/tools/ip-whois":{"get":{"operationId":"ip_whois","summary":"IP WHOIS Lookup","description":"Find the registered owner of an IPv4 or IPv6 address or CIDR block through RDAP, from the Regional Internet Registry that holds it (ARIN, RIPE NCC, APNIC, LACNIC or AFRINIC). Returns the most specific registered network: address range and CIDRs, network name and handle, type, country, parent network, status, registration and last-changed dates, origin AS numbers when published, contacts and the abuse mailbox. Private, loopback, documentation and other reserved addresses return status \"special_purpose\" without any lookup. This is registration data, not geolocation or reputation.\n\nNot for: Locating a user (it is a registry record, not a position), reverse DNS (use reverse_dns), domain names (use whois_lookup) or AS numbers (use asn_lookup).","tags":["ip"],"x-mcp-tool":"ip_whois","x-cost":{"lane":"rdap","miss":1,"hit":1},"x-cache-ttl":"dynamic","x-cache-scope":"public","parameters":[{"name":"q","in":"query","required":true,"description":"IPv4 or IPv6 address, or a CIDR block, e.g. 8.8.8.8, 2606:4700:4700::1111 or 1.1.1.0/24. Brackets, ports and URLs around an address are removed.","schema":{"type":"string","minLength":1,"maxLength":512},"examples":{"google-dns":{"summary":"Google Public DNS (8.8.8.8)","value":"8.8.8.8"},"cloudflare-v6":{"summary":"Cloudflare DNS over IPv6","value":"2606:4700:4700::1111"},"cidr-block":{"summary":"A /24 block","value":"1.1.1.0/24"},"private-address":{"summary":"A private address has no owner to look up","value":"192.168.1.1"}},"style":"form","explode":true},{"name":"includeRaw","in":"query","required":false,"description":"Include the raw RDAP JSON from the Regional Internet Registry in the result. Large; off by default.","schema":{"default":false,"type":"boolean"},"examples":{"google-dns":{"summary":"Google Public DNS (8.8.8.8)","value":false},"cloudflare-v6":{"summary":"Cloudflare DNS over IPv6","value":false},"cidr-block":{"summary":"A /24 block","value":false},"private-address":{"summary":"A private address has no owner to look up","value":false}},"style":"form","explode":true},{"name":"fresh","in":"query","required":false,"description":"Bypass the cache (costs 3x, limited to 10 per hour per network).","schema":{"type":"boolean","default":false}},{"name":"format","in":"query","required":false,"description":"`text` returns the plain-text summary instead of JSON.","schema":{"enum":["json","text"],"default":"json"}}],"responses":{"200":{"description":"The result.","headers":{"RateLimit":{"description":"Remaining tool-cost units: `\"cost\";r=<remaining>;t=<seconds until full>`.","schema":{"type":"string"}},"RateLimit-Policy":{"description":"Quota: `\"cost\";q=<units>;w=<seconds>`.","schema":{"type":"string"}},"X-Request-Id":{"description":"Request id, also in the body.","schema":{"type":"string"}},"ETag":{"description":"Weak validator for conditional requests.","schema":{"type":"string"}},"Link":{"description":"Permalink to the web page (rel=alternate).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IpWhoisResult"}}}},"304":{"description":"Not modified (If-None-Match matched)."},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}},"post":{"operationId":"ip_whois_post","summary":"IP WHOIS Lookup (JSON body)","description":"Same as GET, with the input as a JSON body. Never cached. Add `?fresh=1` to bypass the cache where supported.","tags":["ip"],"x-mcp-tool":"ip_whois","x-cost":{"lane":"rdap","miss":1,"hit":1},"x-cache-ttl":"dynamic","x-cache-scope":"public","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IpWhoisInput"},"examples":{"google-dns":{"summary":"Google Public DNS (8.8.8.8)","value":{"q":"8.8.8.8","includeRaw":false}},"cloudflare-v6":{"summary":"Cloudflare DNS over IPv6","value":{"q":"2606:4700:4700::1111","includeRaw":false}},"cidr-block":{"summary":"A /24 block","value":{"q":"1.1.1.0/24","includeRaw":false}},"private-address":{"summary":"A private address has no owner to look up","value":{"q":"192.168.1.1","includeRaw":false}}}}}},"responses":{"200":{"description":"The result.","headers":{"RateLimit":{"description":"Remaining tool-cost units: `\"cost\";r=<remaining>;t=<seconds until full>`.","schema":{"type":"string"}},"RateLimit-Policy":{"description":"Quota: `\"cost\";q=<units>;w=<seconds>`.","schema":{"type":"string"}},"X-Request-Id":{"description":"Request id, also in the body.","schema":{"type":"string"}},"ETag":{"description":"Weak validator for conditional requests.","schema":{"type":"string"}},"Link":{"description":"Permalink to the web page (rel=alternate).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IpWhoisResult"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/api/v1/tools/ipv6-format":{"get":{"operationId":"ipv6_format","summary":"IPv6 Compress and Expand","description":"Canonicalise, expand and validate IPv6 addresses in bulk (up to 1,000). Compression follows RFC 5952 exactly: lowercase, no leading zeros, \"::\" replaces the longest run of zero groups (the first on a tie) and never a single group, and IPv4-mapped addresses keep a dotted ending. Expansion gives the 32-digit form, the leading-zero-free form, the ip6.arpa nibble form and binary. Prefixes, zone ids, [brackets]:port and URL hosts are preserved. Invalid input gets a precise error with a position.\n\nNot for: Subnet math (use subnet_calculate) or finding the IPv4 inside an address (use ip_convert).","tags":["ip"],"x-mcp-tool":"ipv6_format","x-cost":{"lane":"cpu","miss":1,"hit":1},"x-cache-ttl":86400,"x-cache-scope":"public","parameters":[{"name":"addresses","in":"query","required":true,"description":"One or more IPv6 addresses, one per line (commas and spaces also separate), up to 1,000. Prefix lengths (/64), zone ids (%eth0), [brackets] with :port and URL hosts (http://[2001:db8::1]:8080/) are accepted and kept.","schema":{"type":"string","maxLength":65536},"examples":{"compress":{"summary":"Compress a long address","value":"2001:0db8:0000:0000:0000:ff00:0042:8329"},"expand":{"summary":"Expand a short address","value":"2001:db8::ff00:42:8329"},"rfc5952-rules":{"summary":"RFC 5952 edge cases","value":"2001:db8:0:0:1:0:0:1\n2001:0:0:1:0:0:0:1\n::ffff:102:304\n[FE80::1%eth0]:443"}},"style":"form","explode":true},{"name":"style","in":"query","required":false,"description":"compressed returns only the RFC 5952 form, expanded only the full forms, all returns everything.","schema":{"default":"all","type":"string","enum":["all","compressed","expanded"]},"examples":{"compress":{"summary":"Compress a long address","value":"compressed"},"expand":{"summary":"Expand a short address","value":"expanded"},"rfc5952-rules":{"summary":"RFC 5952 edge cases","value":"all"}},"style":"form","explode":true},{"name":"format","in":"query","required":false,"description":"`text` returns the plain-text summary instead of JSON.","schema":{"enum":["json","text"],"default":"json"}}],"responses":{"200":{"description":"The result.","headers":{"RateLimit":{"description":"Remaining tool-cost units: `\"cost\";r=<remaining>;t=<seconds until full>`.","schema":{"type":"string"}},"RateLimit-Policy":{"description":"Quota: `\"cost\";q=<units>;w=<seconds>`.","schema":{"type":"string"}},"X-Request-Id":{"description":"Request id, also in the body.","schema":{"type":"string"}},"ETag":{"description":"Weak validator for conditional requests.","schema":{"type":"string"}},"Link":{"description":"Permalink to the web page (rel=alternate).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Ipv6FormatResult"}}}},"304":{"description":"Not modified (If-None-Match matched)."},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}},"post":{"operationId":"ipv6_format_post","summary":"IPv6 Compress and Expand (JSON body)","description":"Same as GET, with the input as a JSON body. Never cached. Add `?fresh=1` to bypass the cache where supported.","tags":["ip"],"x-mcp-tool":"ipv6_format","x-cost":{"lane":"cpu","miss":1,"hit":1},"x-cache-ttl":86400,"x-cache-scope":"public","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Ipv6FormatInput"},"examples":{"compress":{"summary":"Compress a long address","value":{"addresses":"2001:0db8:0000:0000:0000:ff00:0042:8329","style":"compressed"}},"expand":{"summary":"Expand a short address","value":{"addresses":"2001:db8::ff00:42:8329","style":"expanded"}},"rfc5952-rules":{"summary":"RFC 5952 edge cases","value":{"addresses":"2001:db8:0:0:1:0:0:1\n2001:0:0:1:0:0:0:1\n::ffff:102:304\n[FE80::1%eth0]:443","style":"all"}}}}}},"responses":{"200":{"description":"The result.","headers":{"RateLimit":{"description":"Remaining tool-cost units: `\"cost\";r=<remaining>;t=<seconds until full>`.","schema":{"type":"string"}},"RateLimit-Policy":{"description":"Quota: `\"cost\";q=<units>;w=<seconds>`.","schema":{"type":"string"}},"X-Request-Id":{"description":"Request id, also in the body.","schema":{"type":"string"}},"ETag":{"description":"Weak validator for conditional requests.","schema":{"type":"string"}},"Link":{"description":"Permalink to the web page (rel=alternate).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Ipv6FormatResult"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/api/v1/tools/mac-lookup":{"get":{"operationId":"mac_lookup","summary":"MAC Address Lookup","description":"Identify the registered manufacturer of MAC addresses and OUIs from the IEEE Registration Authority lists (MA-L, MA-M, MA-S, IAB and CID; the longest matching prefix wins). Accepts any notation (colons, hyphens, dots, bare hex, EUI-64, an OUI alone), up to 500 per call, and finds the addresses in pasted ARP or DHCP table rows. For each address returns the vendor, registered address and country, the block type, the multicast and locally administered bits, whether it looks like a randomized (private Wi-Fi) address, well-known special addresses (broadcast, multicast, spanning tree, VRRP) and virtual machine prefixes (VMware, Hyper-V, QEMU/KVM, VirtualBox). A company name lists that company's blocks instead. A vendor is the registered maker of the network chip or card, not the device model or seller. Answers come from a bundled snapshot; nothing is sent to a third party.\n\nNot for: Identifying a device model, its owner or its location, or looking up an IP address (use ip_whois).","tags":["ip"],"x-mcp-tool":"mac_lookup","x-cost":{"lane":"cpu","miss":"variable","hit":1},"x-cache-ttl":86400,"x-cache-scope":"public","parameters":[{"name":"query","in":"query","required":true,"description":"One or more MAC addresses, OUIs or block prefixes, one per line (commas and spaces also separate), up to 500. Any notation: aa:bb:cc:dd:ee:ff, aa-bb-cc-dd-ee-ff, aabb.ccdd.eeff, aabbccddeeff, or just the first 6 digits (the OUI). Pasted ARP or DHCP table rows are fine: the MAC addresses in each row are found. Or a company name such as \"Raspberry Pi\" to list that company's registered blocks.","schema":{"type":"string","maxLength":65536},"examples":{"virtual-machine":{"summary":"A VMware virtual machine","value":"00:50:56:C0:00:08"},"phone-private":{"summary":"A phone using a private Wi-Fi address","value":"3E:5B:7C:12:34:56"},"oui-only":{"summary":"Just the OUI, in Cisco dotted style","value":"0000.0c07.ac01"},"arp-table":{"summary":"Rows pasted from an ARP table","value":"? (192.168.1.1) at 00:00:0c:07:ac:01 on en0\n? (192.168.1.20) at 08:00:27:12:34:56 on en0\n? (192.168.1.255) at ff:ff:ff:ff:ff:ff on en0\n? (224.0.0.251) at 1:0:5e:0:0:fb on en0"},"company":{"summary":"All the blocks registered to a company","value":"Raspberry Pi"}},"style":"form","explode":true},{"name":"mode","in":"query","required":false,"description":"auto: a single line that is not a MAC address but looks like a company name is searched as a name. mac: always read the input as addresses. vendor: always search registered company names.","schema":{"default":"auto","type":"string","enum":["auto","mac","vendor"]},"examples":{"virtual-machine":{"summary":"A VMware virtual machine","value":"auto"},"phone-private":{"summary":"A phone using a private Wi-Fi address","value":"auto"},"oui-only":{"summary":"Just the OUI, in Cisco dotted style","value":"auto"},"arp-table":{"summary":"Rows pasted from an ARP table","value":"auto"},"company":{"summary":"All the blocks registered to a company","value":"auto"}},"style":"form","explode":true},{"name":"format","in":"query","required":false,"description":"`text` returns the plain-text summary instead of JSON.","schema":{"enum":["json","text"],"default":"json"}}],"responses":{"200":{"description":"The result.","headers":{"RateLimit":{"description":"Remaining tool-cost units: `\"cost\";r=<remaining>;t=<seconds until full>`.","schema":{"type":"string"}},"RateLimit-Policy":{"description":"Quota: `\"cost\";q=<units>;w=<seconds>`.","schema":{"type":"string"}},"X-Request-Id":{"description":"Request id, also in the body.","schema":{"type":"string"}},"ETag":{"description":"Weak validator for conditional requests.","schema":{"type":"string"}},"Link":{"description":"Permalink to the web page (rel=alternate).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MacLookupResult"}}}},"304":{"description":"Not modified (If-None-Match matched)."},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}},"post":{"operationId":"mac_lookup_post","summary":"MAC Address Lookup (JSON body)","description":"Same as GET, with the input as a JSON body. Never cached. Add `?fresh=1` to bypass the cache where supported.","tags":["ip"],"x-mcp-tool":"mac_lookup","x-cost":{"lane":"cpu","miss":"variable","hit":1},"x-cache-ttl":86400,"x-cache-scope":"public","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MacLookupInput"},"examples":{"virtual-machine":{"summary":"A VMware virtual machine","value":{"query":"00:50:56:C0:00:08","mode":"auto"}},"phone-private":{"summary":"A phone using a private Wi-Fi address","value":{"query":"3E:5B:7C:12:34:56","mode":"auto"}},"oui-only":{"summary":"Just the OUI, in Cisco dotted style","value":{"query":"0000.0c07.ac01","mode":"auto"}},"arp-table":{"summary":"Rows pasted from an ARP table","value":{"query":"? (192.168.1.1) at 00:00:0c:07:ac:01 on en0\n? (192.168.1.20) at 08:00:27:12:34:56 on en0\n? (192.168.1.255) at ff:ff:ff:ff:ff:ff on en0\n? (224.0.0.251) at 1:0:5e:0:0:fb on en0","mode":"auto"}},"company":{"summary":"All the blocks registered to a company","value":{"query":"Raspberry Pi","mode":"auto"}}}}}},"responses":{"200":{"description":"The result.","headers":{"RateLimit":{"description":"Remaining tool-cost units: `\"cost\";r=<remaining>;t=<seconds until full>`.","schema":{"type":"string"}},"RateLimit-Policy":{"description":"Quota: `\"cost\";q=<units>;w=<seconds>`.","schema":{"type":"string"}},"X-Request-Id":{"description":"Request id, also in the body.","schema":{"type":"string"}},"ETag":{"description":"Weak validator for conditional requests.","schema":{"type":"string"}},"Link":{"description":"Permalink to the web page (rel=alternate).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MacLookupResult"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/api/v1/tools/password-generator":{"get":{"operationId":"password_generate","summary":"Password Generator","description":"Generate cryptographically random passwords, passphrases or PINs using crypto.getRandomValues with unbiased rejection sampling (never Math.random). Passwords: choose length 4-128, character classes, exclusions and look-alike removal; the entropy estimate accounts for the \"one of each class\" rule. Passphrases: 3-12 words from a 1,024-word list (10 bits each). PINs: 4-12 digits. Returns up to 50 values per call, each call fresh and uncached, plus entropy in bits and a strength label.\n\nNot for: Checking the strength of a password you already have (never send real passwords to a remote tool).","tags":["security"],"x-mcp-tool":"password_generate","x-cost":{"lane":"cpu","miss":1,"hit":1},"x-cache-ttl":0,"x-cache-scope":"public","parameters":[{"name":"mode","in":"query","required":false,"description":"password: random characters. passphrase: random words from a 1,024-word list (10 bits each). pin: random digits.","schema":{"default":"password","type":"string","enum":["password","passphrase","pin"]},"examples":{"default-20":{"summary":"20-character password","value":"password"},"passphrase-6":{"summary":"Six-word passphrase","value":"passphrase"},"no-lookalikes":{"summary":"Readable password without look-alikes","value":"password"},"pin-6":{"summary":"6-digit PIN","value":"pin"}},"style":"form","explode":true},{"name":"length","in":"query","required":false,"description":"Characters in a password (4-128, default 20) or digits in a PIN (4-12, default 6). Ignored for passphrases.","schema":{"type":"integer","minimum":4,"maximum":128},"examples":{"default-20":{"summary":"20-character password","value":20},"no-lookalikes":{"summary":"Readable password without look-alikes","value":16},"pin-6":{"summary":"6-digit PIN","value":6}},"style":"form","explode":true},{"name":"words","in":"query","required":false,"description":"Words in a passphrase (3-12, default 6).","schema":{"type":"integer","minimum":3,"maximum":12},"examples":{"passphrase-6":{"summary":"Six-word passphrase","value":6}},"style":"form","explode":true},{"name":"lower","in":"query","required":false,"description":"Password: include lowercase letters.","schema":{"default":true,"type":"boolean"},"examples":{"default-20":{"summary":"20-character password","value":true},"passphrase-6":{"summary":"Six-word passphrase","value":true},"no-lookalikes":{"summary":"Readable password without look-alikes","value":true},"pin-6":{"summary":"6-digit PIN","value":true}},"style":"form","explode":true},{"name":"upper","in":"query","required":false,"description":"Password: include uppercase letters.","schema":{"default":true,"type":"boolean"},"examples":{"default-20":{"summary":"20-character password","value":true},"passphrase-6":{"summary":"Six-word passphrase","value":true},"no-lookalikes":{"summary":"Readable password without look-alikes","value":true},"pin-6":{"summary":"6-digit PIN","value":true}},"style":"form","explode":true},{"name":"digits","in":"query","required":false,"description":"Password: include digits.","schema":{"default":true,"type":"boolean"},"examples":{"default-20":{"summary":"20-character password","value":true},"passphrase-6":{"summary":"Six-word passphrase","value":true},"no-lookalikes":{"summary":"Readable password without look-alikes","value":true},"pin-6":{"summary":"6-digit PIN","value":true}},"style":"form","explode":true},{"name":"symbols","in":"query","required":false,"description":"Password: include symbols (!@#$%^&*()-_=+[]{};:,.?/~).","schema":{"default":true,"type":"boolean"},"examples":{"default-20":{"summary":"20-character password","value":true},"passphrase-6":{"summary":"Six-word passphrase","value":true},"no-lookalikes":{"summary":"Readable password without look-alikes","value":false},"pin-6":{"summary":"6-digit PIN","value":true}},"style":"form","explode":true},{"name":"excludeSimilar","in":"query","required":false,"description":"Password: leave out look-alike characters (i l L I | 1 o O 0).","schema":{"default":false,"type":"boolean"},"examples":{"default-20":{"summary":"20-character password","value":false},"passphrase-6":{"summary":"Six-word passphrase","value":false},"no-lookalikes":{"summary":"Readable password without look-alikes","value":true},"pin-6":{"summary":"6-digit PIN","value":false}},"style":"form","explode":true},{"name":"exclude","in":"query","required":false,"description":"Password: extra characters to never use.","schema":{"default":"","type":"string","maxLength":64},"examples":{"default-20":{"summary":"20-character password","value":""},"passphrase-6":{"summary":"Six-word passphrase","value":""},"no-lookalikes":{"summary":"Readable password without look-alikes","value":""},"pin-6":{"summary":"6-digit PIN","value":""}},"style":"form","explode":true},{"name":"requireEach","in":"query","required":false,"description":"Password: guarantee at least one character from every selected class.","schema":{"default":true,"type":"boolean"},"examples":{"default-20":{"summary":"20-character password","value":true},"passphrase-6":{"summary":"Six-word passphrase","value":true},"no-lookalikes":{"summary":"Readable password without look-alikes","value":true},"pin-6":{"summary":"6-digit PIN","value":true}},"style":"form","explode":true},{"name":"separator","in":"query","required":false,"description":"Passphrase: text between words.","schema":{"default":"-","type":"string","maxLength":4},"examples":{"default-20":{"summary":"20-character password","value":"-"},"passphrase-6":{"summary":"Six-word passphrase","value":"-"},"no-lookalikes":{"summary":"Readable password without look-alikes","value":"-"},"pin-6":{"summary":"6-digit PIN","value":"-"}},"style":"form","explode":true},{"name":"capitalize","in":"query","required":false,"description":"Passphrase: capitalise each word.","schema":{"default":false,"type":"boolean"},"examples":{"default-20":{"summary":"20-character password","value":false},"passphrase-6":{"summary":"Six-word passphrase","value":false},"no-lookalikes":{"summary":"Readable password without look-alikes","value":false},"pin-6":{"summary":"6-digit PIN","value":false}},"style":"form","explode":true},{"name":"includeNumber","in":"query","required":false,"description":"Passphrase: add one random digit to one random word.","schema":{"default":false,"type":"boolean"},"examples":{"default-20":{"summary":"20-character password","value":false},"passphrase-6":{"summary":"Six-word passphrase","value":false},"no-lookalikes":{"summary":"Readable password without look-alikes","value":false},"pin-6":{"summary":"6-digit PIN","value":false}},"style":"form","explode":true},{"name":"count","in":"query","required":false,"description":"How many to generate (1-50).","schema":{"default":1,"type":"integer","minimum":1,"maximum":50},"examples":{"default-20":{"summary":"20-character password","value":1},"passphrase-6":{"summary":"Six-word passphrase","value":1},"no-lookalikes":{"summary":"Readable password without look-alikes","value":3},"pin-6":{"summary":"6-digit PIN","value":1}},"style":"form","explode":true},{"name":"format","in":"query","required":false,"description":"`text` returns the plain-text summary instead of JSON.","schema":{"enum":["json","text"],"default":"json"}}],"responses":{"200":{"description":"The result.","headers":{"RateLimit":{"description":"Remaining tool-cost units: `\"cost\";r=<remaining>;t=<seconds until full>`.","schema":{"type":"string"}},"RateLimit-Policy":{"description":"Quota: `\"cost\";q=<units>;w=<seconds>`.","schema":{"type":"string"}},"X-Request-Id":{"description":"Request id, also in the body.","schema":{"type":"string"}},"ETag":{"description":"Weak validator for conditional requests.","schema":{"type":"string"}},"Link":{"description":"Permalink to the web page (rel=alternate).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PasswordGenerateResult"}}}},"304":{"description":"Not modified (If-None-Match matched)."},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}},"post":{"operationId":"password_generate_post","summary":"Password Generator (JSON body)","description":"Same as GET, with the input as a JSON body. Never cached. Add `?fresh=1` to bypass the cache where supported.","tags":["security"],"x-mcp-tool":"password_generate","x-cost":{"lane":"cpu","miss":1,"hit":1},"x-cache-ttl":0,"x-cache-scope":"public","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PasswordGenerateInput"},"examples":{"default-20":{"summary":"20-character password","value":{"mode":"password","length":20,"lower":true,"upper":true,"digits":true,"symbols":true,"excludeSimilar":false,"exclude":"","requireEach":true,"separator":"-","capitalize":false,"includeNumber":false,"count":1}},"passphrase-6":{"summary":"Six-word passphrase","value":{"mode":"passphrase","words":6,"lower":true,"upper":true,"digits":true,"symbols":true,"excludeSimilar":false,"exclude":"","requireEach":true,"separator":"-","capitalize":false,"includeNumber":false,"count":1}},"no-lookalikes":{"summary":"Readable password without look-alikes","value":{"mode":"password","length":16,"lower":true,"upper":true,"digits":true,"symbols":false,"excludeSimilar":true,"exclude":"","requireEach":true,"separator":"-","capitalize":false,"includeNumber":false,"count":3}},"pin-6":{"summary":"6-digit PIN","value":{"mode":"pin","length":6,"lower":true,"upper":true,"digits":true,"symbols":true,"excludeSimilar":false,"exclude":"","requireEach":true,"separator":"-","capitalize":false,"includeNumber":false,"count":1}}}}}},"responses":{"200":{"description":"The result.","headers":{"RateLimit":{"description":"Remaining tool-cost units: `\"cost\";r=<remaining>;t=<seconds until full>`.","schema":{"type":"string"}},"RateLimit-Policy":{"description":"Quota: `\"cost\";q=<units>;w=<seconds>`.","schema":{"type":"string"}},"X-Request-Id":{"description":"Request id, also in the body.","schema":{"type":"string"}},"ETag":{"description":"Weak validator for conditional requests.","schema":{"type":"string"}},"Link":{"description":"Permalink to the web page (rel=alternate).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PasswordGenerateResult"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/api/v1/tools/punycode-converter":{"get":{"operationId":"punycode_convert","summary":"Punycode / IDN Converter","description":"Convert domain names between Unicode and Punycode (xn--) using UTS #46 non-transitional processing, label by label. Accepts Unicode names, Punycode, URLs and e-mail addresses (only the domain is converted). Returns the A-label and U-label forms, per-label length against the 63-octet limit, total length against 253, and clear errors for invalid Punycode, hyphen rules, bidi violations or IP-like endings. Warns about mixed scripts, lookalike (homograph) characters, emoji, silently remapped characters and names that differ under older IDNA2003 rules (ß, ς). Up to 500 names.\n\nNot for: Checking whether a domain is registered (use whois_lookup or domain_availability).","tags":["domain"],"x-mcp-tool":"punycode_convert","x-cost":{"lane":"cpu","miss":1,"hit":1},"x-cache-ttl":86400,"x-cache-scope":"public","parameters":[{"name":"domains","in":"query","required":true,"description":"One or more domain names, URLs or e-mail addresses, one per line (commas and spaces also separate), up to 500. Unicode names (bücher.de, 例え.jp, пример.рф) or Punycode (xn--bcher-kva.de). Only the domain part of a URL or e-mail address is converted.","schema":{"type":"string","maxLength":65536},"examples":{"german":{"summary":"German umlaut to Punycode","value":"bücher.de"},"decode":{"summary":"Punycode back to Unicode","value":"xn--80ak6aa92e.com\nxn--e1afmkfd.xn--p1ai"},"homograph":{"summary":"Lookalike (homograph) warning","value":"аpple.com"},"eszett":{"summary":"ß versus ss","value":"Straße.de\nhttps://例え.jp/path\nbob@münchen.de"}},"style":"form","explode":true},{"name":"format","in":"query","required":false,"description":"`text` returns the plain-text summary instead of JSON.","schema":{"enum":["json","text"],"default":"json"}}],"responses":{"200":{"description":"The result.","headers":{"RateLimit":{"description":"Remaining tool-cost units: `\"cost\";r=<remaining>;t=<seconds until full>`.","schema":{"type":"string"}},"RateLimit-Policy":{"description":"Quota: `\"cost\";q=<units>;w=<seconds>`.","schema":{"type":"string"}},"X-Request-Id":{"description":"Request id, also in the body.","schema":{"type":"string"}},"ETag":{"description":"Weak validator for conditional requests.","schema":{"type":"string"}},"Link":{"description":"Permalink to the web page (rel=alternate).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PunycodeConvertResult"}}}},"304":{"description":"Not modified (If-None-Match matched)."},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}},"post":{"operationId":"punycode_convert_post","summary":"Punycode / IDN Converter (JSON body)","description":"Same as GET, with the input as a JSON body. Never cached. Add `?fresh=1` to bypass the cache where supported.","tags":["domain"],"x-mcp-tool":"punycode_convert","x-cost":{"lane":"cpu","miss":1,"hit":1},"x-cache-ttl":86400,"x-cache-scope":"public","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PunycodeConvertInput"},"examples":{"german":{"summary":"German umlaut to Punycode","value":{"domains":"bücher.de"}},"decode":{"summary":"Punycode back to Unicode","value":{"domains":"xn--80ak6aa92e.com\nxn--e1afmkfd.xn--p1ai"}},"homograph":{"summary":"Lookalike (homograph) warning","value":{"domains":"аpple.com"}},"eszett":{"summary":"ß versus ss","value":{"domains":"Straße.de\nhttps://例え.jp/path\nbob@münchen.de"}}}}}},"responses":{"200":{"description":"The result.","headers":{"RateLimit":{"description":"Remaining tool-cost units: `\"cost\";r=<remaining>;t=<seconds until full>`.","schema":{"type":"string"}},"RateLimit-Policy":{"description":"Quota: `\"cost\";q=<units>;w=<seconds>`.","schema":{"type":"string"}},"X-Request-Id":{"description":"Request id, also in the body.","schema":{"type":"string"}},"ETag":{"description":"Weak validator for conditional requests.","schema":{"type":"string"}},"Link":{"description":"Permalink to the web page (rel=alternate).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PunycodeConvertResult"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/api/v1/tools/reverse-dns":{"get":{"operationId":"reverse_dns","summary":"Reverse DNS Lookup","description":"Reverse DNS lookup: turn a public IPv4 or IPv6 address into the host names published in its PTR record (via in-addr.arpa / ip6.arpa) and verify forward-confirmed reverse DNS (FCrDNS) by resolving each name back to an address. Accepts an IP, an arpa name or a URL containing an IP. Private, loopback, link-local and documentation addresses are refused. Returns the names with TTLs, the response code, and per-name forward results with a confirmed/partial/failed verdict. A missing PTR record is a normal result, not an error.\n\nNot for: Finding every domain hosted on an IP (that needs passive DNS), or WHOIS/ownership of the address block (use ip_whois).","tags":["dns"],"x-mcp-tool":"reverse_dns","x-cost":{"lane":"dns","miss":3,"hit":1},"x-cache-ttl":"dynamic","x-cache-scope":"public","parameters":[{"name":"ip","in":"query","required":true,"description":"A public IPv4 or IPv6 address, e.g. 8.8.8.8 or 2001:4860:4860::8888. A full in-addr.arpa / ip6.arpa name or a URL containing an address is reduced to the address. Private and reserved addresses are refused.","schema":{"type":"string","maxLength":253},"examples":{"google-dns":{"summary":"Reverse lookup of 8.8.8.8","value":"8.8.8.8"},"cloudflare-dns":{"summary":"Reverse lookup of 1.1.1.1","value":"1.1.1.1"},"google-dns-v6":{"summary":"IPv6 reverse lookup","value":"2001:4860:4860::8888"}},"style":"form","explode":true},{"name":"forwardConfirm","in":"query","required":false,"description":"Also resolve each returned host name (up to 5) and check that it points back to the same address (forward-confirmed reverse DNS, what mail servers and bot verification rely on).","schema":{"default":true,"type":"boolean"},"examples":{"google-dns":{"summary":"Reverse lookup of 8.8.8.8","value":true},"cloudflare-dns":{"summary":"Reverse lookup of 1.1.1.1","value":true},"google-dns-v6":{"summary":"IPv6 reverse lookup","value":true}},"style":"form","explode":true},{"name":"fresh","in":"query","required":false,"description":"Bypass the cache (costs 3x, limited to 10 per hour per network).","schema":{"type":"boolean","default":false}},{"name":"format","in":"query","required":false,"description":"`text` returns the plain-text summary instead of JSON.","schema":{"enum":["json","text"],"default":"json"}}],"responses":{"200":{"description":"The result.","headers":{"RateLimit":{"description":"Remaining tool-cost units: `\"cost\";r=<remaining>;t=<seconds until full>`.","schema":{"type":"string"}},"RateLimit-Policy":{"description":"Quota: `\"cost\";q=<units>;w=<seconds>`.","schema":{"type":"string"}},"X-Request-Id":{"description":"Request id, also in the body.","schema":{"type":"string"}},"ETag":{"description":"Weak validator for conditional requests.","schema":{"type":"string"}},"Link":{"description":"Permalink to the web page (rel=alternate).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReverseDnsResult"}}}},"304":{"description":"Not modified (If-None-Match matched)."},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}},"post":{"operationId":"reverse_dns_post","summary":"Reverse DNS Lookup (JSON body)","description":"Same as GET, with the input as a JSON body. Never cached. Add `?fresh=1` to bypass the cache where supported.","tags":["dns"],"x-mcp-tool":"reverse_dns","x-cost":{"lane":"dns","miss":3,"hit":1},"x-cache-ttl":"dynamic","x-cache-scope":"public","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReverseDnsInput"},"examples":{"google-dns":{"summary":"Reverse lookup of 8.8.8.8","value":{"ip":"8.8.8.8","forwardConfirm":true}},"cloudflare-dns":{"summary":"Reverse lookup of 1.1.1.1","value":{"ip":"1.1.1.1","forwardConfirm":true}},"google-dns-v6":{"summary":"IPv6 reverse lookup","value":{"ip":"2001:4860:4860::8888","forwardConfirm":true}}}}}},"responses":{"200":{"description":"The result.","headers":{"RateLimit":{"description":"Remaining tool-cost units: `\"cost\";r=<remaining>;t=<seconds until full>`.","schema":{"type":"string"}},"RateLimit-Policy":{"description":"Quota: `\"cost\";q=<units>;w=<seconds>`.","schema":{"type":"string"}},"X-Request-Id":{"description":"Request id, also in the body.","schema":{"type":"string"}},"ETag":{"description":"Weak validator for conditional requests.","schema":{"type":"string"}},"Link":{"description":"Permalink to the web page (rel=alternate).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReverseDnsResult"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/api/v1/tools/security-headers":{"get":{"operationId":"security_headers","summary":"Security Headers Checker","description":"Fetch a public http(s) URL from our server, follow its redirects (up to 10) and grade the security headers of the final response from A+ to F with published rules: Content-Security-Policy (parsed and evaluated: unsafe-inline, unsafe-eval, wildcards, missing object-src and base-uri, report-only), Strict-Transport-Security (max-age, includeSubDomains, preload), X-Frame-Options or frame-ancestors, X-Content-Type-Options, Referrer-Policy, Permissions-Policy and Cross-Origin-Opener, Embedder and Resource Policy. Also reports leaked server versions, deprecated or harmful headers (X-XSS-Protection, Public-Key-Pins), a dangerous CORS pair, headers sent twice with conflicting values, and cookie flags. Every finding says what the header is, why it matters and the exact header line to add, optionally as a snippet for nginx, Apache, Caddy, Cloudflare, Vercel, Netlify, Next.js or Express. Response bodies are never read, so meta-tag policies and Subresource Integrity are not checked.\n\nNot for: Raw header inspection and caching (use http_headers), certificates (use ssl_check) or DNS records (use dns_lookup).","tags":["security"],"x-mcp-tool":"security_headers","x-cost":{"lane":"http","miss":3,"hit":1},"x-cache-ttl":300,"x-cache-scope":"public","parameters":[{"name":"url","in":"query","required":true,"description":"URL or host to check, e.g. https://example.com/ or example.com (https is tried first, then http). Only public http(s) addresses on ports 80, 443, 8080 and 8443 are fetched; private, loopback and internal addresses are refused.","schema":{"type":"string","maxLength":2048},"examples":{"example-com":{"summary":"Grade example.com","value":"https://example.com/"},"github-com":{"summary":"Grade github.com","value":"https://github.com/"},"http-start":{"summary":"Start on http and follow the redirect","value":"http://www.mozilla.org"}},"style":"form","explode":true},{"name":"followRedirects","in":"query","required":false,"description":"Follow redirects (up to 10 hops, each checked again) and grade the final response, or stop at the first response. A redirect response is not graded.","schema":{"default":true,"type":"boolean"},"examples":{"example-com":{"summary":"Grade example.com","value":true},"github-com":{"summary":"Grade github.com","value":true},"http-start":{"summary":"Start on http and follow the redirect","value":true}},"style":"form","explode":true},{"name":"platform","in":"query","required":false,"description":"Format of the copy-paste fix snippets: header (a plain header line), nginx, apache, caddy, cloudflare, vercel, netlify, nextjs or express.","schema":{"default":"header","type":"string","enum":["header","nginx","apache","caddy","cloudflare","vercel","netlify","nextjs","express"]},"examples":{"example-com":{"summary":"Grade example.com","value":"header"},"github-com":{"summary":"Grade github.com","value":"header"},"http-start":{"summary":"Start on http and follow the redirect","value":"nginx"}},"style":"form","explode":true},{"name":"fresh","in":"query","required":false,"description":"Bypass the cache (costs 3x, limited to 10 per hour per network).","schema":{"type":"boolean","default":false}},{"name":"format","in":"query","required":false,"description":"`text` returns the plain-text summary instead of JSON.","schema":{"enum":["json","text"],"default":"json"}}],"responses":{"200":{"description":"The result.","headers":{"RateLimit":{"description":"Remaining tool-cost units: `\"cost\";r=<remaining>;t=<seconds until full>`.","schema":{"type":"string"}},"RateLimit-Policy":{"description":"Quota: `\"cost\";q=<units>;w=<seconds>`.","schema":{"type":"string"}},"X-Request-Id":{"description":"Request id, also in the body.","schema":{"type":"string"}},"ETag":{"description":"Weak validator for conditional requests.","schema":{"type":"string"}},"Link":{"description":"Permalink to the web page (rel=alternate).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SecurityHeadersResult"}}}},"304":{"description":"Not modified (If-None-Match matched)."},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}},"post":{"operationId":"security_headers_post","summary":"Security Headers Checker (JSON body)","description":"Same as GET, with the input as a JSON body. Never cached. Add `?fresh=1` to bypass the cache where supported.","tags":["security"],"x-mcp-tool":"security_headers","x-cost":{"lane":"http","miss":3,"hit":1},"x-cache-ttl":300,"x-cache-scope":"public","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SecurityHeadersInput"},"examples":{"example-com":{"summary":"Grade example.com","value":{"url":"https://example.com/","followRedirects":true,"platform":"header"}},"github-com":{"summary":"Grade github.com","value":{"url":"https://github.com/","followRedirects":true,"platform":"header"}},"http-start":{"summary":"Start on http and follow the redirect","value":{"url":"http://www.mozilla.org","followRedirects":true,"platform":"nginx"}}}}}},"responses":{"200":{"description":"The result.","headers":{"RateLimit":{"description":"Remaining tool-cost units: `\"cost\";r=<remaining>;t=<seconds until full>`.","schema":{"type":"string"}},"RateLimit-Policy":{"description":"Quota: `\"cost\";q=<units>;w=<seconds>`.","schema":{"type":"string"}},"X-Request-Id":{"description":"Request id, also in the body.","schema":{"type":"string"}},"ETag":{"description":"Weak validator for conditional requests.","schema":{"type":"string"}},"Link":{"description":"Permalink to the web page (rel=alternate).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SecurityHeadersResult"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/api/v1/tools/spf-checker":{"get":{"operationId":"spf_check","summary":"SPF Record Checker","description":"Fetch and validate the SPF (RFC 7208) record of a domain. Finds the single v=spf1 TXT record (flags none or several), parses every term, then recursively resolves include, redirect, a, mx and exists to count DNS lookups (limit 10) and void lookups (limit 2) across the whole tree, as receivers do. Returns the record, final policy (-all, ~all, ?all, +all), the evaluation tree, and issues: syntax errors, includes that publish no SPF record or do not exist, loops, more than 10 lookups, +all, deprecated ptr, oversize records. Walks at most 60 DNS queries.\n\nNot for: Generating a record (use spf_generate) or checking DMARC (use dmarc_check).","tags":["email"],"x-mcp-tool":"spf_check","x-cost":{"lane":"dns","miss":6,"hit":1},"x-cache-ttl":"dynamic","x-cache-scope":"public","parameters":[{"name":"domain","in":"query","required":true,"description":"Domain whose SPF record to check, e.g. example.com. A URL or e-mail address is reduced to its domain; Unicode names are converted to Punycode.","schema":{"type":"string","maxLength":253},"examples":{"google-com":{"summary":"SPF of google.com","value":"google.com"},"github-com":{"summary":"SPF of github.com","value":"github.com"},"example-com":{"summary":"SPF of example.com (null sender policy)","value":"example.com"}},"style":"form","explode":true},{"name":"fresh","in":"query","required":false,"description":"Bypass the cache (costs 3x, limited to 10 per hour per network).","schema":{"type":"boolean","default":false}},{"name":"format","in":"query","required":false,"description":"`text` returns the plain-text summary instead of JSON.","schema":{"enum":["json","text"],"default":"json"}}],"responses":{"200":{"description":"The result.","headers":{"RateLimit":{"description":"Remaining tool-cost units: `\"cost\";r=<remaining>;t=<seconds until full>`.","schema":{"type":"string"}},"RateLimit-Policy":{"description":"Quota: `\"cost\";q=<units>;w=<seconds>`.","schema":{"type":"string"}},"X-Request-Id":{"description":"Request id, also in the body.","schema":{"type":"string"}},"ETag":{"description":"Weak validator for conditional requests.","schema":{"type":"string"}},"Link":{"description":"Permalink to the web page (rel=alternate).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SpfCheckResult"}}}},"304":{"description":"Not modified (If-None-Match matched)."},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}},"post":{"operationId":"spf_check_post","summary":"SPF Record Checker (JSON body)","description":"Same as GET, with the input as a JSON body. Never cached. Add `?fresh=1` to bypass the cache where supported.","tags":["email"],"x-mcp-tool":"spf_check","x-cost":{"lane":"dns","miss":6,"hit":1},"x-cache-ttl":"dynamic","x-cache-scope":"public","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SpfCheckInput"},"examples":{"google-com":{"summary":"SPF of google.com","value":{"domain":"google.com"}},"github-com":{"summary":"SPF of github.com","value":{"domain":"github.com"}},"example-com":{"summary":"SPF of example.com (null sender policy)","value":{"domain":"example.com"}}}}}},"responses":{"200":{"description":"The result.","headers":{"RateLimit":{"description":"Remaining tool-cost units: `\"cost\";r=<remaining>;t=<seconds until full>`.","schema":{"type":"string"}},"RateLimit-Policy":{"description":"Quota: `\"cost\";q=<units>;w=<seconds>`.","schema":{"type":"string"}},"X-Request-Id":{"description":"Request id, also in the body.","schema":{"type":"string"}},"ETag":{"description":"Weak validator for conditional requests.","schema":{"type":"string"}},"Link":{"description":"Permalink to the web page (rel=alternate).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SpfCheckResult"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/api/v1/tools/spf-generator":{"get":{"operationId":"spf_generate","summary":"SPF Record Generator","description":"Generate an SPF (RFC 7208) TXT record from structured choices: mail providers (Google Workspace, Microsoft 365, SendGrid, Mailchimp, Amazon SES and more), custom includes, your own IPv4/IPv6 addresses or networks, mx/a, and a policy qualifier (~all, -all, ?all) or redirect. Inputs are validated and normalised; returns the record, TXT strings split at 255 bytes, a zone-file line, the DNS-lookup count against the limit of 10 (marked as an estimate when included services are opaque) and warnings. Pure calculation, no DNS queries.\n\nNot for: Checking a published SPF record (use spf_check).","tags":["email"],"x-mcp-tool":"spf_generate","x-cost":{"lane":"cpu","miss":1,"hit":1},"x-cache-ttl":86400,"x-cache-scope":"public","parameters":[{"name":"domain","in":"query","required":false,"description":"Your domain, e.g. example.com. Optional: used for the zone-file line and publishing notes. URLs, e-mail addresses and Unicode names are reduced to the ASCII domain.","schema":{"type":"string","maxLength":253},"examples":{"google-workspace":{"summary":"Google Workspace only","value":"example.com"},"own-servers":{"summary":"Your own mail servers","value":"example.org"}},"style":"form","explode":true},{"name":"providers","in":"query","required":false,"description":"Mail services that send as your domain; each adds its documented include. Known ids: amazon-ses, brevo, cloudflare-email-routing, constant-contact, fastmail, godaddy, google-workspace, mailchimp, mailgun, mandrill, microsoft-365, postmark, proton-mail, salesforce, sendgrid, sparkpost, zendesk, zoho-mail.","schema":{"maxItems":20,"type":"array","items":{"type":"string","enum":["amazon-ses","brevo","cloudflare-email-routing","constant-contact","fastmail","godaddy","google-workspace","mailchimp","mailgun","mandrill","microsoft-365","postmark","proton-mail","salesforce","sendgrid","sparkpost","zendesk","zoho-mail"]}},"examples":{"google-workspace":{"summary":"Google Workspace only","value":["google-workspace"]},"m365-sendgrid":{"summary":"Microsoft 365 plus SendGrid, strict","value":["microsoft-365","sendgrid"]}},"style":"form","explode":true},{"name":"includes","in":"query","required":false,"description":"Extra domains to include (include:<domain>) for services not in the provider list.","schema":{"maxItems":20,"type":"array","items":{"type":"string","maxLength":253}},"style":"form","explode":true},{"name":"ip4","in":"query","required":false,"description":"Your own IPv4 addresses or networks, e.g. 192.0.2.10 or 203.0.113.0/24.","schema":{"maxItems":50,"type":"array","items":{"type":"string","maxLength":64}},"examples":{"own-servers":{"summary":"Your own mail servers","value":["203.0.113.0/28"]}},"style":"form","explode":true},{"name":"ip6","in":"query","required":false,"description":"Your own IPv6 addresses or networks, e.g. 2001:db8::/32.","schema":{"maxItems":50,"type":"array","items":{"type":"string","maxLength":64}},"examples":{"own-servers":{"summary":"Your own mail servers","value":["2001:db8:25::/48"]}},"style":"form","explode":true},{"name":"includeMx","in":"query","required":false,"description":"Authorize the servers in your MX records (mx).","schema":{"default":false,"type":"boolean"},"examples":{"google-workspace":{"summary":"Google Workspace only","value":false},"m365-sendgrid":{"summary":"Microsoft 365 plus SendGrid, strict","value":false},"own-servers":{"summary":"Your own mail servers","value":true}},"style":"form","explode":true},{"name":"includeA","in":"query","required":false,"description":"Authorize the A/AAAA address of your domain (a).","schema":{"default":false,"type":"boolean"},"examples":{"google-workspace":{"summary":"Google Workspace only","value":false},"m365-sendgrid":{"summary":"Microsoft 365 plus SendGrid, strict","value":false},"own-servers":{"summary":"Your own mail servers","value":false}},"style":"form","explode":true},{"name":"redirect","in":"query","required":false,"description":"Delegate the whole policy to another domain (redirect=domain) instead of ending with an \"all\" qualifier.","schema":{"type":"string","maxLength":253},"style":"form","explode":true},{"name":"all","in":"query","required":false,"description":"What receivers should do with mail from other servers: ~all softfail (recommended while testing), -all fail (strictest), ?all neutral (no protection).","schema":{"default":"~all","type":"string","enum":["~all","-all","?all"]},"examples":{"google-workspace":{"summary":"Google Workspace only","value":"~all"},"m365-sendgrid":{"summary":"Microsoft 365 plus SendGrid, strict","value":"-all"},"own-servers":{"summary":"Your own mail servers","value":"-all"}},"style":"form","explode":true},{"name":"format","in":"query","required":false,"description":"`text` returns the plain-text summary instead of JSON.","schema":{"enum":["json","text"],"default":"json"}}],"responses":{"200":{"description":"The result.","headers":{"RateLimit":{"description":"Remaining tool-cost units: `\"cost\";r=<remaining>;t=<seconds until full>`.","schema":{"type":"string"}},"RateLimit-Policy":{"description":"Quota: `\"cost\";q=<units>;w=<seconds>`.","schema":{"type":"string"}},"X-Request-Id":{"description":"Request id, also in the body.","schema":{"type":"string"}},"ETag":{"description":"Weak validator for conditional requests.","schema":{"type":"string"}},"Link":{"description":"Permalink to the web page (rel=alternate).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SpfGenerateResult"}}}},"304":{"description":"Not modified (If-None-Match matched)."},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}},"post":{"operationId":"spf_generate_post","summary":"SPF Record Generator (JSON body)","description":"Same as GET, with the input as a JSON body. Never cached. Add `?fresh=1` to bypass the cache where supported.","tags":["email"],"x-mcp-tool":"spf_generate","x-cost":{"lane":"cpu","miss":1,"hit":1},"x-cache-ttl":86400,"x-cache-scope":"public","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SpfGenerateInput"},"examples":{"google-workspace":{"summary":"Google Workspace only","value":{"domain":"example.com","providers":["google-workspace"],"includeMx":false,"includeA":false,"all":"~all"}},"m365-sendgrid":{"summary":"Microsoft 365 plus SendGrid, strict","value":{"providers":["microsoft-365","sendgrid"],"includeMx":false,"includeA":false,"all":"-all"}},"own-servers":{"summary":"Your own mail servers","value":{"domain":"example.org","ip4":["203.0.113.0/28"],"ip6":["2001:db8:25::/48"],"includeMx":true,"includeA":false,"all":"-all"}}}}}},"responses":{"200":{"description":"The result.","headers":{"RateLimit":{"description":"Remaining tool-cost units: `\"cost\";r=<remaining>;t=<seconds until full>`.","schema":{"type":"string"}},"RateLimit-Policy":{"description":"Quota: `\"cost\";q=<units>;w=<seconds>`.","schema":{"type":"string"}},"X-Request-Id":{"description":"Request id, also in the body.","schema":{"type":"string"}},"ETag":{"description":"Weak validator for conditional requests.","schema":{"type":"string"}},"Link":{"description":"Permalink to the web page (rel=alternate).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SpfGenerateResult"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/api/v1/tools/ssl-checker":{"get":{"operationId":"ssl_check","summary":"SSL Certificate Checker","description":"Connect to a host and port over TLS and inspect the certificate chain the server presents (no data is sent after the handshake). Returns a verdict (valid, expiring, expired, not-yet-valid, self-signed, untrusted, hostname-mismatch, outdated-tls), days to expiry, issuer, the chain with SANs, key type and size, signature algorithm, negotiated protocol and cipher, and issues with fixes: missing intermediates, expired certificates, name mismatch, weak keys or signatures. A server that refuses TLS 1.2 and 1.3 and only speaks TLS 1.0 or 1.1 gets the verdict outdated-tls with the fix (enable TLS 1.2 and 1.3); its chain is read but not checked for trust. Ports 443, 465, 587 (STARTTLS), 636, 853, 993, 995 and 8443; only public hosts.\n\nNot for: Scanning supported cipher suites or protocol versions, or HTTP headers (use http_headers).","tags":["security"],"x-mcp-tool":"ssl_check","x-cost":{"lane":"http","miss":5,"hit":1},"x-cache-ttl":600,"x-cache-scope":"public","parameters":[{"name":"host","in":"query","required":true,"description":"Domain name or public IP address to connect to, e.g. example.com. A URL or host:port is reduced to its host (and port). Private, loopback and internal addresses are refused.","schema":{"type":"string","maxLength":2048},"examples":{"example-com":{"summary":"Certificate of example.com","value":"example.com"},"github-com":{"summary":"Certificate of github.com","value":"github.com"},"expired":{"summary":"An expired certificate (badssl.com)","value":"expired.badssl.com"},"smtp-starttls":{"summary":"STARTTLS on a mail submission port","value":"smtp.gmail.com"}},"style":"form","explode":true},{"name":"port","in":"query","required":false,"description":"TCP port. Allowed: 443, 465, 587, 636, 853, 993, 995, 8443 (587 is SMTP with STARTTLS). A port written in the host overrides this.","schema":{"default":443,"type":"integer","minimum":1,"maximum":65535},"examples":{"example-com":{"summary":"Certificate of example.com","value":443},"github-com":{"summary":"Certificate of github.com","value":443},"expired":{"summary":"An expired certificate (badssl.com)","value":443},"smtp-starttls":{"summary":"STARTTLS on a mail submission port","value":587}},"style":"form","explode":true},{"name":"fresh","in":"query","required":false,"description":"Bypass the cache (costs 3x, limited to 10 per hour per network).","schema":{"type":"boolean","default":false}},{"name":"format","in":"query","required":false,"description":"`text` returns the plain-text summary instead of JSON.","schema":{"enum":["json","text"],"default":"json"}}],"responses":{"200":{"description":"The result.","headers":{"RateLimit":{"description":"Remaining tool-cost units: `\"cost\";r=<remaining>;t=<seconds until full>`.","schema":{"type":"string"}},"RateLimit-Policy":{"description":"Quota: `\"cost\";q=<units>;w=<seconds>`.","schema":{"type":"string"}},"X-Request-Id":{"description":"Request id, also in the body.","schema":{"type":"string"}},"ETag":{"description":"Weak validator for conditional requests.","schema":{"type":"string"}},"Link":{"description":"Permalink to the web page (rel=alternate).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SslCheckResult"}}}},"304":{"description":"Not modified (If-None-Match matched)."},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}},"post":{"operationId":"ssl_check_post","summary":"SSL Certificate Checker (JSON body)","description":"Same as GET, with the input as a JSON body. Never cached. Add `?fresh=1` to bypass the cache where supported.","tags":["security"],"x-mcp-tool":"ssl_check","x-cost":{"lane":"http","miss":5,"hit":1},"x-cache-ttl":600,"x-cache-scope":"public","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SslCheckInput"},"examples":{"example-com":{"summary":"Certificate of example.com","value":{"host":"example.com","port":443}},"github-com":{"summary":"Certificate of github.com","value":{"host":"github.com","port":443}},"expired":{"summary":"An expired certificate (badssl.com)","value":{"host":"expired.badssl.com","port":443}},"smtp-starttls":{"summary":"STARTTLS on a mail submission port","value":{"host":"smtp.gmail.com","port":587}}}}}},"responses":{"200":{"description":"The result.","headers":{"RateLimit":{"description":"Remaining tool-cost units: `\"cost\";r=<remaining>;t=<seconds until full>`.","schema":{"type":"string"}},"RateLimit-Policy":{"description":"Quota: `\"cost\";q=<units>;w=<seconds>`.","schema":{"type":"string"}},"X-Request-Id":{"description":"Request id, also in the body.","schema":{"type":"string"}},"ETag":{"description":"Weak validator for conditional requests.","schema":{"type":"string"}},"Link":{"description":"Permalink to the web page (rel=alternate).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SslCheckResult"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/api/v1/tools/subnet-calculator":{"get":{"operationId":"subnet_calculate","summary":"IP Subnet Calculator","description":"Compute exact subnet facts for an IPv4 or IPv6 network: network address, netmask and wildcard, broadcast (IPv4), first and last usable host, exact total and usable address counts (RFC 3021 /31 and RFC 6164 /127 handled), address type with its RFC, reverse DNS zone and binary/hex/integer forms. Accepts CIDR, address+netmask, address+wildcard or a range that is one block. Optionally splits into smaller subnets (256 per page) and subtracts AWS, Azure or Google Cloud reserved addresses. Pure calculation, no network access.\n\nNot for: Converting arbitrary start-end ranges to CIDR lists (use ip_range_convert) or looking up who owns an address (use ip_whois).","tags":["ip"],"x-mcp-tool":"subnet_calculate","x-cost":{"lane":"cpu","miss":1,"hit":1},"x-cache-ttl":86400,"x-cache-scope":"public","parameters":[{"name":"cidr","in":"query","required":true,"description":"IPv4 or IPv6 network in any common notation: CIDR (10.0.0.0/22, 2001:db8::/48), address + netmask (10.0.0.1 255.255.252.0), address + wildcard (10.0.0.1 0.0.3.255), a start-end range that is exactly one block, or a single address.","schema":{"type":"string","maxLength":128},"examples":{"v4-22":{"summary":"10.0.0.0/22 private block","value":"10.0.0.0/22"},"v6-48-split":{"summary":"IPv6 /48 split into /52s","value":"2001:db8::/48"},"mask-form":{"summary":"Address plus netmask","value":"192.168.1.77 255.255.255.0"},"aws-24":{"summary":"A /24 subnet in AWS","value":"10.0.1.0/24"},"p2p-31":{"summary":"Point-to-point /31 (RFC 3021)","value":"192.0.2.0/31"}},"style":"form","explode":true},{"name":"splitPrefix","in":"query","required":false,"description":"Also split the network into subnets of this prefix length (longer than the network prefix). Rows are returned 256 at a time.","schema":{"type":"integer","minimum":0,"maximum":128},"examples":{"v6-48-split":{"summary":"IPv6 /48 split into /52s","value":52}},"style":"form","explode":true},{"name":"cloud","in":"query","required":false,"description":"Subtract the addresses a cloud provider reserves per subnet (IPv4 only): aws and azure keep 5, gcp keeps 4.","schema":{"default":"none","type":"string","enum":["none","aws","azure","gcp"]},"examples":{"v4-22":{"summary":"10.0.0.0/22 private block","value":"none"},"v6-48-split":{"summary":"IPv6 /48 split into /52s","value":"none"},"mask-form":{"summary":"Address plus netmask","value":"none"},"aws-24":{"summary":"A /24 subnet in AWS","value":"aws"},"p2p-31":{"summary":"Point-to-point /31 (RFC 3021)","value":"none"}},"style":"form","explode":true},{"name":"cursor","in":"query","required":false,"description":"Offset into the split list for paging; pass the previous nextCursor.","schema":{"default":0,"type":"integer","minimum":0,"maximum":9007199254740991},"examples":{"v4-22":{"summary":"10.0.0.0/22 private block","value":0},"v6-48-split":{"summary":"IPv6 /48 split into /52s","value":0},"mask-form":{"summary":"Address plus netmask","value":0},"aws-24":{"summary":"A /24 subnet in AWS","value":0},"p2p-31":{"summary":"Point-to-point /31 (RFC 3021)","value":0}},"style":"form","explode":true},{"name":"format","in":"query","required":false,"description":"`text` returns the plain-text summary instead of JSON.","schema":{"enum":["json","text"],"default":"json"}}],"responses":{"200":{"description":"The result.","headers":{"RateLimit":{"description":"Remaining tool-cost units: `\"cost\";r=<remaining>;t=<seconds until full>`.","schema":{"type":"string"}},"RateLimit-Policy":{"description":"Quota: `\"cost\";q=<units>;w=<seconds>`.","schema":{"type":"string"}},"X-Request-Id":{"description":"Request id, also in the body.","schema":{"type":"string"}},"ETag":{"description":"Weak validator for conditional requests.","schema":{"type":"string"}},"Link":{"description":"Permalink to the web page (rel=alternate).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubnetCalculateResult"}}}},"304":{"description":"Not modified (If-None-Match matched)."},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}},"post":{"operationId":"subnet_calculate_post","summary":"IP Subnet Calculator (JSON body)","description":"Same as GET, with the input as a JSON body. Never cached. Add `?fresh=1` to bypass the cache where supported.","tags":["ip"],"x-mcp-tool":"subnet_calculate","x-cost":{"lane":"cpu","miss":1,"hit":1},"x-cache-ttl":86400,"x-cache-scope":"public","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubnetCalculateInput"},"examples":{"v4-22":{"summary":"10.0.0.0/22 private block","value":{"cidr":"10.0.0.0/22","cloud":"none","cursor":0}},"v6-48-split":{"summary":"IPv6 /48 split into /52s","value":{"cidr":"2001:db8::/48","splitPrefix":52,"cloud":"none","cursor":0}},"mask-form":{"summary":"Address plus netmask","value":{"cidr":"192.168.1.77 255.255.255.0","cloud":"none","cursor":0}},"aws-24":{"summary":"A /24 subnet in AWS","value":{"cidr":"10.0.1.0/24","cloud":"aws","cursor":0}},"p2p-31":{"summary":"Point-to-point /31 (RFC 3021)","value":{"cidr":"192.0.2.0/31","cloud":"none","cursor":0}}}}}},"responses":{"200":{"description":"The result.","headers":{"RateLimit":{"description":"Remaining tool-cost units: `\"cost\";r=<remaining>;t=<seconds until full>`.","schema":{"type":"string"}},"RateLimit-Policy":{"description":"Quota: `\"cost\";q=<units>;w=<seconds>`.","schema":{"type":"string"}},"X-Request-Id":{"description":"Request id, also in the body.","schema":{"type":"string"}},"ETag":{"description":"Weak validator for conditional requests.","schema":{"type":"string"}},"Link":{"description":"Permalink to the web page (rel=alternate).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubnetCalculateResult"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/api/v1/tools/website-hosting":{"get":{"operationId":"website_hosting","summary":"Who Hosts This Website","description":"Identify who is behind a website from a domain or URL. Resolves A, AAAA and the CNAME chain; maps each IP to its network owner (AS number and organisation, DB-IP Lite) and country; recognises CDNs, proxies and hosting platforms (Cloudflare, Fastly, Akamai, CloudFront, Vercel, Netlify, GitHub Pages, Shopify and others) from IP ranges, AS numbers, CNAMEs and, only when those do not settle it, one HEAD request for response headers; reads the DNS provider from the nameservers and the email provider from the MX records; and looks up the abuse contact of the serving network. Says plainly when a CDN hides the origin server (it never tries to unmask it). Every finding lists its evidence. Accepts domains and URLs only. Network owners and countries need the DB-IP data to be downloaded (the result notes it when not); show the attribution field (\"IP geolocation by DB-IP\", https://db-ip.com) with them.\n\nNot for: IP addresses (use ip_location or ip_whois), finding the origin behind a CDN, subdomain discovery, technology fingerprinting of page content or registrar lookups (use whois_lookup).","tags":["domain"],"x-mcp-tool":"website_hosting","x-cost":{"lane":"http","miss":"variable","hit":1},"x-cache-ttl":"dynamic","x-cache-scope":"public","parameters":[{"name":"target","in":"query","required":true,"description":"A domain name or a website address, e.g. example.com or https://www.example.com/page. Only the host is used. IP addresses are not accepted here (use ip_location for those).","schema":{"type":"string","maxLength":2048},"examples":{"cloudflare-site":{"summary":"A site behind Cloudflare: the origin is hidden","value":"www.cloudflare.com"},"github-pages":{"summary":"A site on a hosting platform (GitHub Pages)","value":"pages.github.com"},"plain-host":{"summary":"A site on its own hosting company network","value":"example.com"},"no-probe":{"summary":"Network and DNS data only, no request to the site","value":"wikipedia.org"}},"style":"form","explode":true},{"name":"probe","in":"query","required":false,"description":"Allow one request to the site (HEAD, over https) to read response headers that give away CDNs and platforms. It is only made when the DNS and network data have not already identified the host. Switch off to use DNS and network data alone.","schema":{"default":true,"type":"boolean"},"examples":{"cloudflare-site":{"summary":"A site behind Cloudflare: the origin is hidden","value":true},"github-pages":{"summary":"A site on a hosting platform (GitHub Pages)","value":true},"plain-host":{"summary":"A site on its own hosting company network","value":true},"no-probe":{"summary":"Network and DNS data only, no request to the site","value":false}},"style":"form","explode":true},{"name":"includeAbuse","in":"query","required":false,"description":"Also look up the abuse contact of the network that serves the site (one registry lookup).","schema":{"default":true,"type":"boolean"},"examples":{"cloudflare-site":{"summary":"A site behind Cloudflare: the origin is hidden","value":true},"github-pages":{"summary":"A site on a hosting platform (GitHub Pages)","value":true},"plain-host":{"summary":"A site on its own hosting company network","value":true},"no-probe":{"summary":"Network and DNS data only, no request to the site","value":false}},"style":"form","explode":true},{"name":"fresh","in":"query","required":false,"description":"Bypass the cache (costs 3x, limited to 10 per hour per network).","schema":{"type":"boolean","default":false}},{"name":"format","in":"query","required":false,"description":"`text` returns the plain-text summary instead of JSON.","schema":{"enum":["json","text"],"default":"json"}}],"responses":{"200":{"description":"The result.","headers":{"RateLimit":{"description":"Remaining tool-cost units: `\"cost\";r=<remaining>;t=<seconds until full>`.","schema":{"type":"string"}},"RateLimit-Policy":{"description":"Quota: `\"cost\";q=<units>;w=<seconds>`.","schema":{"type":"string"}},"X-Request-Id":{"description":"Request id, also in the body.","schema":{"type":"string"}},"ETag":{"description":"Weak validator for conditional requests.","schema":{"type":"string"}},"Link":{"description":"Permalink to the web page (rel=alternate).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebsiteHostingResult"}}}},"304":{"description":"Not modified (If-None-Match matched)."},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}},"post":{"operationId":"website_hosting_post","summary":"Who Hosts This Website (JSON body)","description":"Same as GET, with the input as a JSON body. Never cached. Add `?fresh=1` to bypass the cache where supported.","tags":["domain"],"x-mcp-tool":"website_hosting","x-cost":{"lane":"http","miss":"variable","hit":1},"x-cache-ttl":"dynamic","x-cache-scope":"public","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebsiteHostingInput"},"examples":{"cloudflare-site":{"summary":"A site behind Cloudflare: the origin is hidden","value":{"target":"www.cloudflare.com","probe":true,"includeAbuse":true}},"github-pages":{"summary":"A site on a hosting platform (GitHub Pages)","value":{"target":"pages.github.com","probe":true,"includeAbuse":true}},"plain-host":{"summary":"A site on its own hosting company network","value":{"target":"example.com","probe":true,"includeAbuse":true}},"no-probe":{"summary":"Network and DNS data only, no request to the site","value":{"target":"wikipedia.org","probe":false,"includeAbuse":false}}}}}},"responses":{"200":{"description":"The result.","headers":{"RateLimit":{"description":"Remaining tool-cost units: `\"cost\";r=<remaining>;t=<seconds until full>`.","schema":{"type":"string"}},"RateLimit-Policy":{"description":"Quota: `\"cost\";q=<units>;w=<seconds>`.","schema":{"type":"string"}},"X-Request-Id":{"description":"Request id, also in the body.","schema":{"type":"string"}},"ETag":{"description":"Weak validator for conditional requests.","schema":{"type":"string"}},"Link":{"description":"Permalink to the web page (rel=alternate).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebsiteHostingResult"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/api/v1/tools/what-is-my-ip":{"get":{"operationId":"what_is_my_ip","summary":"What Is My IP Address","description":"Return the public IP address the HTTP request came from, with its version (IPv4 or IPv6), optionally its reverse DNS host name and the registered network (name, range, country, registry). The answer depends on the caller, so it is never cached or shared. Over MCP it would report the AI host's address rather than the user's, so it is only offered on the REST API and the web page. Private or loopback addresses are flagged as not public.\n\nNot for: Looking up an arbitrary address (use ip_whois, reverse_dns or asn_lookup).","tags":["ip"],"x-mcp-tool":null,"x-cost":{"lane":"dns","miss":1,"hit":1},"x-cache-ttl":0,"x-cache-scope":"requester","parameters":[{"name":"details","in":"query","required":false,"description":"Also look up the reverse DNS name and the registered network (name, range, country) of the address. Each lookup is given about two seconds and is simply left out when it does not answer.","schema":{"default":true,"type":"boolean"},"examples":{"with-details":{"summary":"My address with reverse DNS and network","value":true},"address-only":{"summary":"Just my address","value":false}},"style":"form","explode":true},{"name":"format","in":"query","required":false,"description":"`text` returns the plain-text summary instead of JSON.","schema":{"enum":["json","text"],"default":"json"}}],"responses":{"200":{"description":"The result.","headers":{"RateLimit":{"description":"Remaining tool-cost units: `\"cost\";r=<remaining>;t=<seconds until full>`.","schema":{"type":"string"}},"RateLimit-Policy":{"description":"Quota: `\"cost\";q=<units>;w=<seconds>`.","schema":{"type":"string"}},"X-Request-Id":{"description":"Request id, also in the body.","schema":{"type":"string"}},"ETag":{"description":"Weak validator for conditional requests.","schema":{"type":"string"}},"Link":{"description":"Permalink to the web page (rel=alternate).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WhatIsMyIpResult"}}}},"304":{"description":"Not modified (If-None-Match matched)."},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}},"post":{"operationId":"what_is_my_ip_post","summary":"What Is My IP Address (JSON body)","description":"Same as GET, with the input as a JSON body. Never cached. Add `?fresh=1` to bypass the cache where supported.","tags":["ip"],"x-mcp-tool":null,"x-cost":{"lane":"dns","miss":1,"hit":1},"x-cache-ttl":0,"x-cache-scope":"requester","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WhatIsMyIpInput"},"examples":{"with-details":{"summary":"My address with reverse DNS and network","value":{"details":true}},"address-only":{"summary":"Just my address","value":{"details":false}}}}}},"responses":{"200":{"description":"The result.","headers":{"RateLimit":{"description":"Remaining tool-cost units: `\"cost\";r=<remaining>;t=<seconds until full>`.","schema":{"type":"string"}},"RateLimit-Policy":{"description":"Quota: `\"cost\";q=<units>;w=<seconds>`.","schema":{"type":"string"}},"X-Request-Id":{"description":"Request id, also in the body.","schema":{"type":"string"}},"ETag":{"description":"Weak validator for conditional requests.","schema":{"type":"string"}},"Link":{"description":"Permalink to the web page (rel=alternate).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WhatIsMyIpResult"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/api/v1/tools/whois-lookup":{"get":{"operationId":"whois_lookup","summary":"WHOIS Lookup","description":"Look up the public registration record of a domain name: registrar (IANA id, abuse contact), creation, update and expiry dates with age and days left, lifecycle stage (new, expiring soon, redemption, pending delete), EPP statuses with plain-English meaning, nameservers, DNSSEC and contacts (mostly redacted by registries). Uses RDAP, asks the registrar for more when the registry points to it, and falls back to WHOIS (port 43) for extensions without RDAP. Accepts a domain, URL or e-mail address; Unicode is converted to Punycode. An unregistered name returns status \"not_found\" with an availability verdict; premium or reserved names can still be unavailable.\n\nNot for: IP addresses (use ip_whois), AS numbers (use asn_lookup), DNS records (use dns_lookup) or checking several names at once (use domain_availability).","tags":["domain"],"x-mcp-tool":"whois_lookup","x-cost":{"lane":"rdap","miss":"variable","hit":1},"x-cache-ttl":"dynamic","x-cache-scope":"public","parameters":[{"name":"q","in":"query","required":true,"description":"Domain name to look up, e.g. example.com. A URL or e-mail address is reduced to its registrable domain; Unicode names are converted to Punycode.","schema":{"type":"string","minLength":1,"maxLength":512},"examples":{"example-com":{"summary":"example.com","value":"example.com"},"google-com":{"summary":"google.com with its registrar","value":"google.com"},"url-input":{"summary":"Paste a URL","value":"https://www.github.com/torvalds/linux"},"registry-only-raw":{"summary":"wikipedia.org, registry only, with raw JSON","value":"wikipedia.org"}},"style":"form","explode":true},{"name":"followRegistrar","in":"query","required":false,"description":"Also ask the registrar's own RDAP server when the registry points to it. Adds registrar-side contacts and expiry date; costs one more upstream request.","schema":{"default":true,"type":"boolean"},"examples":{"example-com":{"summary":"example.com","value":true},"google-com":{"summary":"google.com with its registrar","value":true},"url-input":{"summary":"Paste a URL","value":true},"registry-only-raw":{"summary":"wikipedia.org, registry only, with raw JSON","value":false}},"style":"form","explode":true},{"name":"includeRaw","in":"query","required":false,"description":"Include the raw RDAP JSON from the registry (and registrar) in the result. Large; off by default.","schema":{"default":false,"type":"boolean"},"examples":{"example-com":{"summary":"example.com","value":false},"google-com":{"summary":"google.com with its registrar","value":false},"url-input":{"summary":"Paste a URL","value":false},"registry-only-raw":{"summary":"wikipedia.org, registry only, with raw JSON","value":true}},"style":"form","explode":true},{"name":"fresh","in":"query","required":false,"description":"Bypass the cache (costs 3x, limited to 10 per hour per network).","schema":{"type":"boolean","default":false}},{"name":"format","in":"query","required":false,"description":"`text` returns the plain-text summary instead of JSON.","schema":{"enum":["json","text"],"default":"json"}}],"responses":{"200":{"description":"The result.","headers":{"RateLimit":{"description":"Remaining tool-cost units: `\"cost\";r=<remaining>;t=<seconds until full>`.","schema":{"type":"string"}},"RateLimit-Policy":{"description":"Quota: `\"cost\";q=<units>;w=<seconds>`.","schema":{"type":"string"}},"X-Request-Id":{"description":"Request id, also in the body.","schema":{"type":"string"}},"ETag":{"description":"Weak validator for conditional requests.","schema":{"type":"string"}},"Link":{"description":"Permalink to the web page (rel=alternate).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WhoisLookupResult"}}}},"304":{"description":"Not modified (If-None-Match matched)."},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}},"post":{"operationId":"whois_lookup_post","summary":"WHOIS Lookup (JSON body)","description":"Same as GET, with the input as a JSON body. Never cached. Add `?fresh=1` to bypass the cache where supported.","tags":["domain"],"x-mcp-tool":"whois_lookup","x-cost":{"lane":"rdap","miss":"variable","hit":1},"x-cache-ttl":"dynamic","x-cache-scope":"public","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WhoisLookupInput"},"examples":{"example-com":{"summary":"example.com","value":{"q":"example.com","followRegistrar":true,"includeRaw":false}},"google-com":{"summary":"google.com with its registrar","value":{"q":"google.com","followRegistrar":true,"includeRaw":false}},"url-input":{"summary":"Paste a URL","value":{"q":"https://www.github.com/torvalds/linux","followRegistrar":true,"includeRaw":false}},"registry-only-raw":{"summary":"wikipedia.org, registry only, with raw JSON","value":{"q":"wikipedia.org","followRegistrar":false,"includeRaw":true}}}}}},"responses":{"200":{"description":"The result.","headers":{"RateLimit":{"description":"Remaining tool-cost units: `\"cost\";r=<remaining>;t=<seconds until full>`.","schema":{"type":"string"}},"RateLimit-Policy":{"description":"Quota: `\"cost\";q=<units>;w=<seconds>`.","schema":{"type":"string"}},"X-Request-Id":{"description":"Request id, also in the body.","schema":{"type":"string"}},"ETag":{"description":"Weak validator for conditional requests.","schema":{"type":"string"}},"Link":{"description":"Permalink to the web page (rel=alternate).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WhoisLookupResult"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}}},"components":{"schemas":{"Problem":{"type":"object","description":"RFC 9457 problem details. `code` is the stable machine-readable error code.","required":["type","title","status","code","detail","requestId"],"properties":{"type":{"type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"code":{"type":"string","description":"Stable error code. Treat unknown values as a generic failure.","examples":["INVALID_INPUT","RATE_LIMITED","UPSTREAM_ERROR"]},"detail":{"type":"string"},"field":{"type":"string","description":"The input field the problem refers to."},"hint":{"type":"string"},"retryAfter":{"type":"integer","description":"Seconds to wait before retrying."},"requestId":{"type":"string"}}},"ToolResultEnvelope":{"type":"object","description":"Envelope around every tool result. `data` holds the tool-specific output.","required":["tool","version","requestId","data","summary","meta","permalink"],"properties":{"tool":{"type":"string","description":"Tool id."},"version":{"type":"integer","description":"Output version of the tool."},"requestId":{"type":"string"},"data":{},"summary":{"type":"string","description":"Compact plain-text summary of the result."},"incomplete":{"type":"boolean","description":"A deadline was reached; data holds what finished."},"warnings":{"type":"array","items":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"}}}},"meta":{"type":"object","required":["cache","durationMs","fetchedAt"],"properties":{"cache":{"enum":["hit","miss","stale","coalesced","bypass"]},"durationMs":{"type":"number"},"fetchedAt":{"type":"string","format":"date-time"},"expiresAt":{"type":"string","format":"date-time"},"sources":{"type":"array","items":{"type":"object","required":["name"],"properties":{"name":{"type":"string"},"url":{"type":"string"},"license":{"type":"string"}}}}}},"permalink":{"type":"string","format":"uri","description":"Shareable web page for this result."}}},"ToolDescriptor":{"type":"object","required":["id","name","title","summary","category","links"],"properties":{"id":{"type":"string"},"name":{"type":"string","description":"MCP tool name and OpenAPI operationId."},"title":{"type":"string"},"summary":{"type":"string"},"description":{"type":"string"},"category":{"type":"string"},"execution":{"enum":["pure","network","fanout"]},"surfaces":{"type":"object","additionalProperties":{"type":"boolean"}},"links":{"type":"object","additionalProperties":{"type":"string"}},"pages":{"type":"array","items":{"type":"object","properties":{"slug":{"type":"string"},"url":{"type":"string"}}}},"examples":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"input":{}}}}}},"AsnLookupInput":{"type":"object","properties":{"q":{"type":"string","minLength":1,"maxLength":512,"description":"AS number, e.g. AS13335, 13335 or asdot notation such as 1.10. A leading \"AS\" is optional."},"includeRaw":{"default":false,"description":"Include the raw RDAP JSON from the Regional Internet Registry in the result. Large; off by default.","type":"boolean"}},"required":["q"],"additionalProperties":false},"AsnLookupOutput":{"type":"object","properties":{"query":{"type":"object","properties":{"kind":{"type":"string","enum":["domain","ip","autnum","nameserver","entity","tld"]},"key":{"type":"string"},"display":{"type":"string"},"input":{"type":"string"},"notices":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"],"additionalProperties":{}},"description":"What was changed to make the input usable (URL reduced to a host, IDN converted, ...)."}},"required":["kind","key","display","input","notices"],"additionalProperties":{}},"status":{"type":"string","enum":["found","not_found","special_purpose","no_rdap_service"],"description":"found: a record exists. not_found: the registry says there is none. special_purpose: reserved address space or AS number, nothing to look up. no_rdap_service: no RDAP (and for domains no WHOIS) service exists."},"source":{"type":"string","enum":["rdap","whois","none"],"description":"Where the record came from."},"availability":{"description":"Domains only. \"likely-available\" is a registry saying there is no record; premium or reserved names can still be unavailable.","type":"object","properties":{"verdict":{"type":"string","enum":["likely-available","registered","likely-available-whois","unknown"]},"caveats":{"type":"array","items":{"type":"string"}},"registerLinks":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"url":{"type":"string"},"affiliate":{"type":"boolean"}},"required":["name","url","affiliate"],"additionalProperties":{}}}},"required":["verdict","caveats","registerLinks"],"additionalProperties":{}},"registrar":{"description":"Outcome of asking the registrar after the registry. The merged data is in domain.","type":"object","properties":{"status":{"type":"string"},"url":{"type":"string"}},"required":["status"],"additionalProperties":{}},"whois":{"description":"Raw WHOIS reply, only when the TLD has no RDAP service.","type":"object","properties":{"server":{"type":"string"},"text":{"type":"string"},"notFound":{"type":"boolean"},"rateLimited":{"type":"boolean"},"referralChain":{"type":"array","items":{"type":"string"}}},"required":["server","text","notFound","rateLimited","referralChain"],"additionalProperties":{}},"error":{"type":"object","properties":{"code":{"type":"string"},"httpStatus":{"type":"number"},"title":{"type":"string"},"description":{"type":"array","items":{"type":"string"}},"retryAfter":{"type":"number"}},"required":["code"],"additionalProperties":{}},"provenance":{"type":"object","properties":{"bootstrap":{"type":"object","properties":{"kind":{"type":"string"},"entry":{"type":"string"},"source":{"type":"string"}},"required":["kind","entry","source"],"additionalProperties":{}},"serverUrl":{"type":"string"},"queryUrl":{"type":"string"},"finalUrl":{"type":"string"},"registrarUrl":{"type":"string"},"whoisServer":{"type":"string"},"trace":{"type":"array","items":{"type":"object","properties":{"step":{"type":"string"},"label":{"type":"string"},"ms":{"type":"number"},"url":{"type":"string"},"host":{"type":"string"},"status":{"type":["number","string"]},"note":{"type":"string"}},"required":["step","label","ms"],"additionalProperties":{}}},"totalMs":{"type":"number"},"fetchedAt":{"type":"string"},"cache":{"type":"string","enum":["hit","miss","stale","coalesced","bypass","hit-or-miss"]},"stale":{"description":"True when this is a stored copy served because the registry is not answering.","type":"boolean"}},"required":["trace","totalMs","fetchedAt","cache"],"additionalProperties":{},"description":"How the answer was obtained: which bootstrap entry, which servers, timings."},"raw":{"description":"Raw upstream RDAP JSON. Only with includeRaw.","type":"object","properties":{"registry":{},"registrar":{}},"additionalProperties":{}},"autnum":{"type":"object","properties":{"objectClassName":{"type":"string","const":"autnum"},"handle":{"type":"string"},"startAutnum":{"type":"number"},"endAutnum":{"type":"number"},"name":{"type":"string"},"type":{"type":"string"},"country":{"type":"string"},"status":{"type":"array","items":{"type":"string"}},"events":{"type":"object","properties":{"registration":{"type":"object","properties":{"action":{"type":"string"},"raw":{"type":"string"},"date":{"description":"ISO-8601 UTC.","type":"string"}},"required":["action","raw"],"additionalProperties":{}},"expiration":{"type":"object","properties":{"action":{"type":"string"},"raw":{"type":"string"},"date":{"description":"ISO-8601 UTC.","type":"string"}},"required":["action","raw"],"additionalProperties":{}},"lastChanged":{"type":"object","properties":{"action":{"type":"string"},"raw":{"type":"string"},"date":{"description":"ISO-8601 UTC.","type":"string"}},"required":["action","raw"],"additionalProperties":{}},"registrarExpiration":{"type":"object","properties":{"action":{"type":"string"},"raw":{"type":"string"},"date":{"description":"ISO-8601 UTC.","type":"string"}},"required":["action","raw"],"additionalProperties":{}},"all":{"type":"array","items":{},"description":"Every event as the registry sent it: { action, raw, date?, actor? }."}},"required":["all"],"additionalProperties":{}},"contacts":{"type":"array","items":{"type":"object","properties":{"roles":{"type":"array","items":{"type":"string"}},"name":{"type":"string"},"org":{"type":"string"},"emails":{"type":"array","items":{"type":"string"}},"isRedacted":{"type":"boolean"}},"required":["roles","emails","isRedacted"],"additionalProperties":{}}},"abuse":{"type":"object","properties":{"email":{"type":"string"},"phone":{"type":"string"}},"additionalProperties":{}},"rir":{"type":"string"}},"required":["objectClassName","status","events","contacts"],"additionalProperties":{}}},"required":["query","status","source","provenance"],"additionalProperties":{}},"AsnLookupResult":{"allOf":[{"$ref":"#/components/schemas/ToolResultEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/AsnLookupOutput"}}}]},"BlacklistCheckInput":{"type":"object","properties":{"target":{"type":"string","maxLength":253,"description":"A public IPv4 or IPv6 address, or a domain. A URL or e-mail address is reduced to its host. Private and reserved addresses are refused."},"scope":{"default":"mx","description":"For a domain: mx = check its mail servers' IPs (default), a = the IP of the domain itself, both = both, domain = check the domain name against domain blocklists (Spamhaus DBL, URIBL, ...). Ignored for an IP address.","type":"string","enum":["mx","a","both","domain"]}},"required":["target"],"additionalProperties":false},"BlacklistCheckOutput":{"type":"object","properties":{"target":{"type":"string"},"mode":{"type":"string","enum":["ip","domain"]},"scope":{"type":"string","enum":["mx","a","both","domain"]},"verdict":{"type":"string","enum":["clean","listed","policy-only","inconclusive"],"description":"listed = on at least one list that mail servers act on; policy-only = only on policy or collateral lists (PBL, UCEPROTECT 2 and 3, backscatter, new-domain age); clean = on none; inconclusive = too few lists answered to say."},"subjects":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["ip","domain"]},"value":{"type":"string"},"source":{"type":"string","enum":["input","mx","a","host"]},"via":{"type":"string"},"listed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"clean":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"errors":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"refused":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"skipped":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"results":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"zone":{"type":"string"},"status":{"type":"string","enum":["listed","clean","error","refused","skipped"],"description":"listed, clean, error (no usable answer in time), refused (the list refused our query: neither listed nor clean) or skipped (not asked)."},"codes":{"type":"array","items":{"type":"string"}},"meaning":{"type":"string"},"weight":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"category":{"type":"string"},"txt":{"type":"string"},"detail":{"type":"string"},"delistUrl":{"type":"string"},"ms":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","name","zone","status","codes","meaning","weight","category","delistUrl","ms"],"additionalProperties":false}}},"required":["kind","value","source","listed","clean","errors","refused","skipped","results"],"additionalProperties":false}},"summary":{"type":"object","properties":{"subjects":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"asked":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"listed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"clean":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"errors":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"refused":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"skipped":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"weightedScore":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["subjects","asked","listed","clean","errors","refused","skipped","weightedScore"],"additionalProperties":false},"notChecked":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"reason":{"type":"string"}},"required":["id","name","reason"],"additionalProperties":false}},"registryVerified":{"type":"string"},"created":{"type":"string"},"notes":{"type":"array","items":{"type":"string"}},"dnsQueries":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"incomplete":{"type":"boolean"}},"required":["target","mode","scope","verdict","subjects","summary","notChecked","registryVerified","notes","dnsQueries"],"additionalProperties":false},"BlacklistCheckResult":{"allOf":[{"$ref":"#/components/schemas/ToolResultEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/BlacklistCheckOutput"}}}]},"DkimCheckInput":{"type":"object","properties":{"domain":{"type":"string","maxLength":253,"description":"Domain that sends the mail, e.g. example.com. A URL, an e-mail address or a full key name such as google._domainkey.example.com is reduced to the domain (and the selector, when it is in the name)."},"selector":{"description":"DKIM selector, the \"s=\" value of a DKIM-Signature header, e.g. google or selector1. Leave it out to try a short list of common selectors.","type":"string","maxLength":100},"discover":{"default":true,"description":"When no selector is given, try the documented list of common selectors (at most 24). DKIM selectors cannot be listed, so finding none is not proof that the domain has no DKIM.","type":"boolean"}},"required":["domain"],"additionalProperties":false},"DkimCheckOutput":{"type":"object","properties":{"domain":{"type":"string"},"mode":{"type":"string","enum":["selector","discovery"]},"status":{"type":"string","enum":["ok","warning","error","missing","none-found","dns-error"],"description":"ok / warning / error: the worst finding among the keys found. missing: the given selector has no record. none-found: discovery tried common selectors and found none (not proof of no DKIM). dns-error: the resolver could not answer."},"found":{"type":"array","items":{"type":"object","properties":{"selector":{"type":"string"},"fqdn":{"type":"string","description":"The DNS name that was read."},"status":{"type":"string","enum":["ok","warning","error","revoked"]},"record":{"description":"The TXT record text (key truncated in the middle only if very long).","type":"string"},"cnameChain":{"type":"array","items":{"type":"string"},"description":"CNAME targets followed to reach the record (typically a provider such as Microsoft 365 or Amazon SES)."},"provider":{"type":"string"},"keyType":{"type":"string","enum":["rsa","ed25519","unknown","revoked"]},"keyBits":{"description":"RSA modulus length in bits, or 256 for Ed25519.","type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"tags":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"value":{"type":"string"}},"required":["name","value"],"additionalProperties":false}},"testing":{"type":"boolean","description":"t=y is set."},"hashes":{"type":"array","items":{"type":"string"},"description":"h= hash algorithms; empty means any."},"services":{"type":"array","items":{"type":"string"},"description":"s= service types; empty means all."},"ttl":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"issues":{"type":"array","items":{"type":"object","properties":{"severity":{"type":"string","enum":["error","warning","info"]},"code":{"type":"string"},"message":{"type":"string"},"tag":{"type":"string"}},"required":["severity","code","message"],"additionalProperties":false}}},"required":["selector","fqdn","status","cnameChain","keyType","tags","testing","hashes","services","issues"],"additionalProperties":false}},"discovery":{"type":"object","properties":{"tried":{"type":"array","items":{"type":"string"},"description":"Selectors that were asked about (given selector, or the discovery list)."},"cap":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"domainkeyExists":{"description":"Whether _domainkey.<domain> exists in DNS (RFC 8020): false means no selector exists at all. null = not checked or unclear.","type":["boolean","null"]},"conclusive":{"type":"boolean","description":"True only when the answer proves there is no DKIM key (the selector was asked for directly and does not exist, or _domainkey does not exist and the probes agree)."},"errors":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Selectors whose lookup failed (timeouts, server errors)."},"mxHint":{"description":"Provider guessed from the MX records, whose selectors were tried first.","type":"string"},"wildcard":{"description":"True when the domain answers every selector name with the same record (a wildcard), so only keys that differ from it are listed.","type":"boolean"}},"required":["tried","cap","domainkeyExists","conclusive","errors"],"additionalProperties":false},"issues":{"type":"array","items":{"type":"object","properties":{"severity":{"type":"string","enum":["error","warning","info"]},"code":{"type":"string"},"message":{"type":"string"}},"required":["severity","code","message"],"additionalProperties":false}},"notes":{"type":"array","items":{"type":"string"}},"dnsQueries":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"ttl":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"incomplete":{"description":"The time limit was reached before every selector was tried.","type":"boolean"}},"required":["domain","mode","status","found","discovery","issues","notes","dnsQueries"],"additionalProperties":false},"DkimCheckResult":{"allOf":[{"$ref":"#/components/schemas/ToolResultEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/DkimCheckOutput"}}}]},"DmarcCheckInput":{"type":"object","properties":{"domain":{"type":"string","maxLength":253,"description":"Domain to check, e.g. example.com (not _dmarc.example.com, though that is accepted). A URL or e-mail address is reduced to its domain; Unicode names are converted to Punycode. For a subdomain without its own record the organizational domain's record is used, as receivers do."}},"required":["domain"],"additionalProperties":false},"DmarcCheckOutput":{"type":"object","properties":{"domain":{"type":"string"},"status":{"type":"string","enum":["ok","warning","error","missing","dns-error"],"description":"ok = valid, warning = valid with warnings, error = the record is invalid and receivers ignore it, missing = no DMARC record at the domain or its organizational domain, dns-error = the resolver returned SERVFAIL or REFUSED."},"valid":{"type":"boolean"},"strength":{"type":"string","enum":["none","monitoring","partial","enforcing"],"description":"none = no usable policy, monitoring = p=none, partial = quarantine/reject for only part of the mail (pct below 100), enforcing = quarantine or reject."},"record":{"type":"string"},"records":{"type":"array","items":{"type":"string"},"description":"Every TXT record at the DMARC name that starts with v=DMARC1 (more than one disables DMARC)."},"host":{"description":"The DNS name the record was found at.","type":"string"},"policyDomain":{"description":"The domain that publishes the record.","type":"string"},"inherited":{"type":"boolean","description":"The record belongs to the organizational domain, not to the domain asked about."},"queried":{"type":"array","items":{"type":"string"},"description":"DNS names asked for the policy, in order."},"policy":{"type":"object","properties":{"p":{"type":"string","enum":["none","quarantine","reject"]},"sp":{"type":"string","enum":["none","quarantine","reject"]},"np":{"type":"string","enum":["none","quarantine","reject"]},"pct":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"adkim":{"type":"string","enum":["r","s"]},"aspf":{"type":"string","enum":["r","s"]},"fo":{"type":"array","items":{"type":"string"}},"ri":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"t":{"type":"string","enum":["y","n"]},"psd":{"type":"string","enum":["y","n","u"]}},"additionalProperties":false},"effective":{"description":"The policy that applies to mail from the domain asked about (sp for a subdomain using the parent's record).","type":"object","properties":{"policy":{"type":"string","enum":["none","quarantine","reject"]},"applies":{"type":"string","enum":["p","sp"]}},"required":["policy","applies"],"additionalProperties":false},"tags":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"value":{"type":"string"}},"required":["name","value"],"additionalProperties":false}},"destinations":{"type":"array","items":{"type":"object","properties":{"tag":{"type":"string","enum":["rua","ruf"],"description":"rua = aggregate reports, ruf = failure reports."},"uri":{"type":"string"},"address":{"type":"string"},"domain":{"description":"Domain of the report mailbox.","type":"string"},"maxSize":{"type":"string"},"external":{"type":"boolean","description":"The mailbox is in a different organizational domain, so the receiving domain must authorize the reports."},"authorized":{"description":"true = authorization record found, false = missing, null = not applicable or could not be checked.","type":["boolean","null"]},"authorizationHost":{"description":"TXT name that must exist at the receiving domain.","type":"string"}},"required":["tag","uri","external","authorized"],"additionalProperties":false}},"issues":{"type":"array","items":{"type":"object","properties":{"severity":{"type":"string","enum":["error","warning","info"]},"code":{"type":"string"},"message":{"type":"string"},"tag":{"type":"string"}},"required":["severity","code","message"],"additionalProperties":false}},"notes":{"type":"array","items":{"type":"string"}},"dnsQueries":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"ttl":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["domain","status","valid","strength","records","inherited","queried","tags","destinations","issues","notes","dnsQueries"],"additionalProperties":false},"DmarcCheckResult":{"allOf":[{"$ref":"#/components/schemas/ToolResultEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/DmarcCheckOutput"}}}]},"DmarcGenerateInput":{"type":"object","properties":{"domain":{"type":"string","maxLength":253,"description":"The domain to protect, e.g. example.com (the record is published at _dmarc.<domain>). URLs, e-mail addresses and Unicode names are reduced to the ASCII domain."},"policy":{"default":"none","description":"What receivers should do with mail that fails DMARC: none (monitor only), quarantine (spam folder), reject (refuse).","type":"string","enum":["none","quarantine","reject"]},"subdomainPolicy":{"description":"sp=: policy for subdomains. Defaults to the main policy when omitted.","type":"string","enum":["none","quarantine","reject"]},"nonexistentPolicy":{"description":"np=: policy for non-existent subdomains (DMARCbis; older receivers ignore it).","type":"string","enum":["none","quarantine","reject"]},"rua":{"description":"Where to send daily aggregate reports: addresses or mailto: URIs, optionally with a size limit (mailto:a@example.com!10m).","maxItems":10,"type":"array","items":{"type":"string","maxLength":254}},"ruf":{"description":"Where to send failure (forensic) reports. Most large providers no longer send them.","maxItems":10,"type":"array","items":{"type":"string","maxLength":254}},"adkim":{"description":"DKIM alignment: r relaxed (default) or s strict.","type":"string","enum":["r","s"]},"aspf":{"description":"SPF alignment: r relaxed (default) or s strict.","type":"string","enum":["r","s"]},"pct":{"description":"Legacy (RFC 7489) percentage of failing mail the policy applies to. Removed in DMARCbis but still honoured by major providers.","type":"integer","minimum":0,"maximum":100},"fo":{"description":"Failure-report options: any of 0, 1, d, s (for example \"1\" or \"0:s\"). Only matters with ruf.","type":"string","maxLength":16},"ri":{"description":"Legacy (RFC 7489) aggregate report interval in seconds (default 86400). Removed in DMARCbis.","type":"integer","minimum":1,"maximum":4294967295},"testing":{"default":false,"description":"DMARCbis testing mode (t=y): tells receivers you are still rolling out.","type":"boolean"}},"required":["domain"],"additionalProperties":false},"DmarcGenerateOutput":{"type":"object","properties":{"domain":{"type":"string"},"host":{"type":"string","description":"TXT record name: _dmarc.<domain>."},"record":{"type":"string"},"length":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"chunks":{"type":"array","items":{"type":"string"}},"zoneLine":{"type":"string"},"tags":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"value":{"type":"string"}},"required":["name","value"],"additionalProperties":false}},"valid":{"type":"boolean"},"issues":{"type":"array","items":{"type":"object","properties":{"severity":{"type":"string","enum":["error","warning","info"]},"code":{"type":"string"},"message":{"type":"string"},"tag":{"type":"string"}},"required":["severity","code","message"],"additionalProperties":false}},"externalAuthorizations":{"type":"array","items":{"type":"object","properties":{"reportDomain":{"type":"string"},"host":{"type":"string"},"value":{"type":"string"},"zoneLine":{"type":"string"}},"required":["reportDomain","host","value","zoneLine"],"additionalProperties":false},"description":"TXT records the receiving domain must publish before it can accept reports for your domain."},"rollout":{"type":"array","items":{"type":"object","properties":{"step":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"title":{"type":"string"},"record":{"type":"string"},"advice":{"type":"string"},"current":{"type":"boolean"}},"required":["step","title","record","advice","current"],"additionalProperties":false},"description":"A staged path from monitoring to full enforcement."},"notes":{"type":"array","items":{"type":"string"}}},"required":["domain","host","record","length","chunks","zoneLine","tags","valid","issues","externalAuthorizations","rollout","notes"],"additionalProperties":false},"DmarcGenerateResult":{"allOf":[{"$ref":"#/components/schemas/ToolResultEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/DmarcGenerateOutput"}}}]},"DnsLookupInput":{"type":"object","properties":{"name":{"type":"string","maxLength":253,"description":"Domain or host name, e.g. example.com or _dmarc.example.com. A URL or e-mail address is reduced to its host; Unicode names are converted to Punycode. For type PTR you may give an IP address."},"type":{"default":"A","description":"Record type. ALL runs A, AAAA, CNAME, MX, NS, TXT, SOA, CAA and HTTPS together. ANY is not offered (RFC 8482).","type":"string","enum":["ALL","A","AAAA","CNAME","MX","NS","TXT","SOA","CAA","DS","DNSKEY","PTR","SRV","HTTPS","TLSA"]},"resolver":{"default":"cloudflare","description":"Which resolver to ask: a public resolver id (cloudflare, google, quad9, opendns, ...) or \"authoritative\" to query the domain's own nameserver directly (no cache).","type":"string","enum":["cloudflare","cloudflare-families","google","quad9","quad9-unfiltered","opendns","opendns-familyshield","adguard","adguard-unfiltered","cleanbrowsing-security","controld","nextdns","dns4eu","dns-sb","hurricane-electric","lumen","vercara","ntt","ca-cira-shield","ca-bell","us-att","br-uol","co-colombia-telecomunicaciones","cl-gtd","de-digitalcourage","de-freifunk-muc","de-dnswatch","cz-nic-odvr","ch-swisscom","pl-atman","na-mtc","ru-yandex","ir-shecan","ir-electro","om-ooredoo","tr-teknet","ke-safaricom","ng-mtn","bf-onatel","in-nic-public-dns","bd-mango","pk-ntc","kr-kt","cn-114dns","cn-alidns","tw-hinet","id-telkom","au-telstra","authoritative"]},"dnssec":{"default":false,"description":"Set the DNSSEC OK bit: include RRSIG records and report whether the resolver validated the answer (AD flag).","type":"boolean"}},"required":["name"],"additionalProperties":false},"DnsLookupOutput":{"type":"object","properties":{"name":{"type":"string","description":"The name that was queried (ASCII, no trailing dot; the arpa name for an IP)."},"type":{"type":"string"},"resolver":{"type":"string","description":"Resolver id that answered."},"resolverName":{"type":"string"},"server":{"description":"IP address of the server that answered.","type":"string"},"nameserver":{"description":"Authoritative mode: host name of the nameserver asked.","type":"string"},"rcode":{"type":"string","enum":["NOERROR","NXDOMAIN","SERVFAIL","REFUSED","FORMERR","NOTIMP","TIMEOUT","NETWORK"],"description":"DNS response code. NOERROR with no records means the name exists but has none of this type (NODATA)."},"ad":{"type":"boolean","description":"DNSSEC \"authenticated data\": the resolver validated every answer returned."},"dnssec":{"type":"boolean","description":"Whether the DNSSEC OK bit was set on the query."},"ms":{"type":"number","description":"Wall-clock time for the whole lookup."},"minTtl":{"description":"Smallest TTL among the returned records, seconds.","type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"records":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"type":{"type":"string"},"ttl":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"data":{"type":"string","description":"Record data in zone-file presentation format."},"fields":{"description":"Parsed fields, e.g. preference and exchange for MX.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":["string","number","boolean"]}}},"required":["name","type","ttl","data"],"additionalProperties":false}},"authority":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"type":{"type":"string"},"ttl":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"data":{"type":"string","description":"Record data in zone-file presentation format."},"fields":{"description":"Parsed fields, e.g. preference and exchange for MX.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":["string","number","boolean"]}}},"required":["name","type","ttl","data"],"additionalProperties":false},"description":"SOA of the enclosing zone when the answer was empty (negative caching time)."},"queries":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string"},"rcode":{"type":"string","enum":["NOERROR","NXDOMAIN","SERVFAIL","REFUSED","FORMERR","NOTIMP","TIMEOUT","NETWORK"]},"records":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Answer records in this response."},"ms":{"type":"number"},"ad":{"type":"boolean"},"error":{"type":"string"}},"required":["type","rcode","records","ms"],"additionalProperties":false},"description":"One entry per DNS question sent (several for type ALL)."},"ede":{"type":"array","items":{"type":"string"},"description":"Extended DNS Errors (RFC 8914) the resolver attached, e.g. DNSSEC validation failures."},"notes":{"type":"array","items":{"type":"string"}},"truncated":{"type":"boolean","description":"The record list was cut at the output limit."}},"required":["name","type","resolver","resolverName","rcode","ad","dnssec","ms","records","authority","queries","ede","notes","truncated"],"additionalProperties":false},"DnsLookupResult":{"allOf":[{"$ref":"#/components/schemas/ToolResultEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/DnsLookupOutput"}}}]},"DnsPropagationInput":{"type":"object","properties":{"name":{"type":"string","maxLength":253,"description":"Host name to check, e.g. www.example.com. A URL or e-mail address is reduced to its host; Unicode names are converted to Punycode."},"type":{"default":"A","description":"Record type to compare across resolvers.","type":"string","enum":["A","AAAA","CNAME","MX","NS","TXT","SOA","CAA","SRV","DS","DNSKEY","HTTPS"]},"expected":{"description":"The value you expect to see after your change, e.g. a new IP address. Resolvers whose answers include it count as current. For address and name records the whole value must match; for TXT and other text records a substring is enough. Without it the authoritative answer is the reference.","type":"string","maxLength":512}},"required":["name"],"additionalProperties":false},"DnsPropagationOutput":{"type":"object","properties":{"name":{"type":"string"},"type":{"type":"string"},"expected":{"type":"string"},"reference":{"type":"object","properties":{"source":{"type":"string","enum":["authoritative","expected","majority","none"],"description":"What the resolvers were compared with."},"answers":{"type":"array","items":{"type":"string"}}},"required":["source","answers"],"additionalProperties":false},"authoritative":{"type":"array","items":{"type":"object","properties":{"ns":{"type":"string","description":"Authoritative nameserver host name that answered."},"ip":{"type":"string"},"status":{"type":"string","enum":["current","stale","empty","nxdomain","servfail","refused","timeout","error"]},"rcode":{"type":"string","enum":["NOERROR","NXDOMAIN","SERVFAIL","REFUSED","FORMERR","NOTIMP","TIMEOUT","NETWORK"]},"answers":{"type":"array","items":{"type":"string"}},"ttl":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"ms":{"type":"number"},"serial":{"description":"SOA serial, when the record type is SOA.","type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["ns","status","rcode","answers","ms"],"additionalProperties":false}},"resolvers":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"provider":{"type":"string"},"country":{"type":"string","description":"ISO 3166-1 alpha-2."},"city":{"type":"string"},"kind":{"type":"string","enum":["global","regional","isp"],"description":"global = anycast public resolver, regional = public resolver of a country, isp = access provider resolver."},"filtering":{"description":"The resolver blocks malware/adult content by policy, so a missing answer may be a block rather than a stale cache.","type":"boolean"},"status":{"type":"string","enum":["current","stale","empty","nxdomain","servfail","refused","timeout","error"],"description":"current = matches the reference, stale = answers differ from it, empty = NOERROR without data."},"rcode":{"type":"string","enum":["NOERROR","NXDOMAIN","SERVFAIL","REFUSED","FORMERR","NOTIMP","TIMEOUT","NETWORK"]},"answers":{"type":"array","items":{"type":"string"}},"ttl":{"description":"Remaining cache lifetime reported by the resolver, seconds.","type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"ms":{"type":"number"},"error":{"type":"string"}},"required":["id","name","provider","country","kind","status","rcode","answers","ms"],"additionalProperties":false}},"counts":{"type":"object","properties":{"total":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"answered":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"current":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"stale":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"empty":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"nxdomain":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"servfail":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"refused":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"timeout":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"error":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["total","answered","current","stale","empty","nxdomain","servfail","refused","timeout","error"],"additionalProperties":false},"consensus":{"type":"object","properties":{"withData":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Resolvers that returned at least one record."},"agreeing":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Resolvers in the largest group that gave the same non-empty answer."},"distinctAnswerSets":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"groups":{"type":"array","items":{"type":"object","properties":{"answers":{"type":"array","items":{"type":"string"}},"resolvers":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"ids":{"type":"array","items":{"type":"string"}},"current":{"type":"boolean"}},"required":["answers","resolvers","ids","current"],"additionalProperties":false}}},"required":["withData","agreeing","distinctAnswerSets","groups"],"additionalProperties":false},"summary":{"type":"string"},"eta":{"type":"string"},"etaSeconds":{"description":"Longest remaining TTL among stale resolvers: when the old answer should be gone.","type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"minTtl":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"flushLinks":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"url":{"type":"string"}},"required":["name","url"],"additionalProperties":false}},"incomplete":{"type":"boolean","description":"The deadline passed before every resolver answered; see pending."},"pending":{"type":"array","items":{"type":"string"},"description":"Ids of resolvers that had not answered when the deadline passed."},"notes":{"type":"array","items":{"type":"string"}}},"required":["name","type","reference","authoritative","resolvers","counts","consensus","summary","flushLinks","incomplete","pending","notes"],"additionalProperties":false},"DnsPropagationResult":{"allOf":[{"$ref":"#/components/schemas/ToolResultEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/DnsPropagationOutput"}}}]},"DomainAvailabilityInput":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":512,"description":"A bare name such as \"acme\" (checked under tlds), or a full domain such as \"acme.io\" (checked as is, plus its name under any extra tlds). URLs and e-mail addresses are reduced to their domain."},"tlds":{"default":[],"description":"Extensions to check, without the dot, e.g. [\"com\",\"dev\",\"co.uk\"] (\"com,dev\" also works); at most 10. Empty means com, net, org, io and ai for a bare name.","maxItems":10,"type":"array","items":{"type":"string","maxLength":126}}},"required":["name"],"additionalProperties":false},"DomainAvailabilityOutput":{"type":"object","properties":{"name":{"type":"string","description":"What was asked for, as typed."},"results":{"type":"array","items":{"type":"object","properties":{"domain":{"type":"string","description":"The candidate in ASCII (Punycode) form."},"unicode":{"type":"string","description":"The candidate as people read it (Unicode form)."},"tld":{"type":"string"},"verdict":{"type":"string","enum":["likely-available","likely-available-whois","registered","unknown","invalid"],"description":"registered: the registry has a record. likely-available: the registry says there is none (premium, reserved or restricted names can still be unavailable). likely-available-whois: same, from a WHOIS server (less certain). unknown: could not be checked, never read it as available. invalid: not a name that can be registered."},"status":{"type":"string","description":"The lookup outcome behind the verdict: found, not_found, rate_limited, timeout, ... or \"invalid\"."},"source":{"type":"string","enum":["rdap","whois","none"]},"caveats":{"type":"array","items":{"type":"string"}},"registerLinks":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"url":{"type":"string"},"affiliate":{"type":"boolean"}},"required":["name","url","affiliate"],"additionalProperties":false},"description":"Registrar search pages, only for likely-available names. Check affiliate before presenting them."},"registrar":{"type":"string"},"registeredOn":{"description":"ISO-8601 UTC, registered rows only.","type":"string"},"expires":{"description":"ISO-8601 UTC, registered rows only.","type":"string"},"stage":{"description":"Lifecycle stage of a registered name, e.g. redemption or pending-delete (it may be released later).","type":"string"},"code":{"description":"Stable code for why a row is unknown or invalid.","type":"string"},"message":{"description":"Plain-English reason for an unknown or invalid row.","type":"string"},"retryAfter":{"description":"Seconds to wait before retrying an unknown row.","type":"number"},"checkedAt":{"description":"When the registry was asked (ISO-8601 UTC); older than the request when served from the cache.","type":"string"},"cache":{"type":"string","enum":["hit","miss","stale","coalesced","bypass","hit-or-miss"]}},"required":["domain","unicode","tld","verdict","status","source","caveats","registerLinks"],"additionalProperties":false}},"truncated":{"type":"boolean","description":"More names were requested than the limit of 10; the rest were not checked."},"incomplete":{"description":"The deadline passed before every registry answered; unanswered rows are unknown.","type":"boolean"},"notes":{"type":"array","items":{"type":"string"}}},"required":["name","results","truncated","notes"],"additionalProperties":false},"DomainAvailabilityResult":{"allOf":[{"$ref":"#/components/schemas/ToolResultEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/DomainAvailabilityOutput"}}}]},"DomainReportInput":{"type":"object","properties":{"domain":{"type":"string","maxLength":253,"description":"Domain to report on, e.g. example.com. A URL or e-mail address is reduced to its host; Unicode names are converted to Punycode. IP addresses are not accepted (use ip_location)."},"sections":{"default":["registration","dns","web","hosting","email"],"description":"Which sections to run: registration, dns, web (certificate and security headers), hosting and email (SPF, DMARC, DKIM, blocklists). Default all. Fewer sections cost less.","minItems":1,"maxItems":5,"type":"array","items":{"type":"string","enum":["registration","dns","web","hosting","email"]}}},"required":["domain"],"additionalProperties":false},"DomainReportOutput":{"type":"object","properties":{"domain":{"type":"string","description":"The name the DNS, web and hosting sections ran on."},"registrable":{"type":"string","description":"The registrable domain the registration and email sections ran on."},"score":{"anyOf":[{"type":"integer","minimum":0,"maximum":100},{"type":"null"}],"description":"Weighted score of the scored areas (registration 20, DNS 20, web 30, email 30, re-weighted over the areas that answered). Null when none did."},"rating":{"type":"string","enum":["excellent","good","attention","poor","unknown"]},"summary":{"type":"string"},"areas":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","enum":["registration","dns","web","hosting","email"]},"title":{"type":"string"},"status":{"type":"string","enum":["good","ok","attention","problem","info","unavailable"]},"score":{"anyOf":[{"type":"integer","minimum":0,"maximum":100},{"type":"null"}],"description":"0-100, or null when the area is not scored (hosting) or nothing could be read."},"headline":{"type":"string","description":"One plain sentence."},"facts":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string"},"value":{"type":"string"}},"required":["label","value"],"additionalProperties":false}},"findings":{"type":"array","items":{"type":"object","properties":{"severity":{"type":"string","enum":["good","info","warning","error"]},"text":{"type":"string"}},"required":["severity","text"],"additionalProperties":false}},"parts":{"type":"array","items":{"type":"object","properties":{"tool":{"type":"string","description":"The tool that produced this part, e.g. ssl-checker."},"label":{"type":"string"},"status":{"type":"string","enum":["ok","failed"]},"cache":{"description":"hit, miss, stale or coalesced: where the part came from.","type":"string"},"code":{"description":"Error code of a failed part.","type":"string"},"message":{"description":"Why a part failed, in plain words.","type":"string"},"href":{"type":"string","description":"Path of the full tool page for this domain."}},"required":["tool","label","status","href"],"additionalProperties":false}}},"required":["id","title","status","score","headline","facts","findings","parts"],"additionalProperties":false}},"notes":{"type":"array","items":{"type":"string"}},"incomplete":{"description":"A section did not finish in time; it is marked in its area.","type":"boolean"}},"required":["domain","registrable","score","rating","summary","areas","notes"],"additionalProperties":false},"DomainReportResult":{"allOf":[{"$ref":"#/components/schemas/ToolResultEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/DomainReportOutput"}}}]},"EppStatusInput":{"type":"object","properties":{"codes":{"minItems":1,"maxItems":20,"type":"array","items":{"type":"string","maxLength":500},"description":"Status codes in EPP (clientTransferProhibited) or RDAP (\"client transfer prohibited\") spelling, any case. Lines copied from a WHOIS record work too, with or without the \"Domain Status:\" label and the icann.org link. Commas, semicolons and line breaks separate codes."}},"required":["codes"],"additionalProperties":false},"EppStatusOutput":{"type":"object","properties":{"results":{"type":"array","items":{"type":"object","properties":{"input":{"type":"string","description":"The code as it was understood (links and labels around it removed)."},"known":{"type":"boolean","description":"False for a value that is not a standard EPP/RDAP status; registries sometimes invent their own."},"rdap":{"type":"string","description":"RDAP spelling, lower case, e.g. \"client transfer prohibited\"."},"epp":{"description":"EPP camelCase spelling, e.g. \"clientTransferProhibited\".","type":"string"},"slug":{"type":"string"},"label":{"type":"string"},"summary":{"type":"string","description":"One plain-English sentence."},"details":{"type":"array","items":{"type":"string"},"description":"Longer explanation, one paragraph per item."},"setBy":{"type":"string","enum":["registrar","registry","either"]},"category":{"type":"string"},"severity":{"type":"string","enum":["positive","neutral","info","warning","danger"]},"howToRemove":{"type":"array","items":{"type":"string"}},"forOwners":{"type":"string"},"forBuyers":{"type":"string"},"lifecycle":{"description":"Where the status sits in the life of a domain.","type":"string"},"related":{"type":"array","items":{"type":"string"},"description":"RDAP spellings of statuses that usually appear with this one."},"registrySpecific":{"type":"boolean","description":"Outside ICANN's standard list (e.g. a ccTLD registry's own status)."},"icannUrl":{"type":"string"}},"required":["input","known","rdap","label","summary","details","category","severity","howToRemove","related","registrySpecific"],"additionalProperties":false}},"interpretation":{"type":"array","items":{"type":"string"},"description":"What the set of statuses means together, e.g. a full registrar lock or a domain on hold. Empty when there is nothing to add."},"unknown":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"How many values were not recognised."},"truncated":{"type":"boolean","description":"More than 20 distinct values were given; the rest were ignored."}},"required":["results","interpretation","unknown","truncated"],"additionalProperties":false},"EppStatusResult":{"allOf":[{"$ref":"#/components/schemas/ToolResultEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/EppStatusOutput"}}}]},"HttpHeadersInput":{"type":"object","properties":{"url":{"type":"string","maxLength":2048,"description":"URL or host to fetch, e.g. https://example.com/page or example.com (https is tried first, then http). Only public http(s) addresses on ports 80, 443, 8080 and 8443 are fetched; private, loopback and internal addresses are refused."},"method":{"default":"GET","description":"GET shows what a browser receives; HEAD asks for headers only (a few servers answer it differently).","type":"string","enum":["GET","HEAD"]},"followRedirects":{"default":true,"description":"Follow redirects (up to 10 hops, each checked again) or stop at the first response.","type":"boolean"}},"required":["url"],"additionalProperties":false},"HttpHeadersOutput":{"type":"object","properties":{"url":{"type":"string","description":"The URL that was requested (canonical form)."},"method":{"type":"string","enum":["GET","HEAD"]},"finalUrl":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Status of the last response."},"statusText":{"type":"string"},"ok":{"type":"boolean","description":"The last response is 2xx."},"hops":{"type":"array","items":{"type":"object","properties":{"url":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"statusText":{"type":"string"},"headers":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"},"description":"Response headers, names lower-cased; repeated headers joined with \", \" (Set-Cookie with a newline)."},"location":{"description":"Absolute redirect target of a 3xx hop.","type":"string"},"ip":{"description":"Address that answered.","type":"string"},"httpVersion":{"description":"The HTTP version LookupOwl used to ask for this URL: \"1.1\", because it does not negotiate HTTP/2 or HTTP/3. It is not the best version the site supports: a site that offers HTTP/3 says so in its alt-svc header (an h3 entry).","type":"string"},"ms":{"type":"number","description":"Time until the response headers arrived."}},"required":["url","status","headers","ms"],"additionalProperties":false},"description":"Every response in order; the last one is the final response."},"totalMs":{"type":"number"},"redirects":{"type":"object","properties":{"count":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"loop":{"type":"boolean"},"tooMany":{"type":"boolean"},"notFollowed":{"type":"boolean"},"httpsUpgrade":{"type":"boolean","description":"An http:// URL was redirected to https:// on the same host."},"downgrade":{"type":"boolean","description":"An https:// URL was redirected to http://."},"crossDomain":{"type":"boolean"},"chain":{"type":"array","items":{"type":"object","properties":{"from":{"type":"string"},"to":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["from","to","status"],"additionalProperties":false}}},"required":["count","loop","tooMany","notFollowed","httpsUpgrade","downgrade","crossDomain","chain"],"additionalProperties":false},"security":{"type":"object","properties":{"score":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"0-100, weighted over HSTS, CSP, frame protection, nosniff, Referrer-Policy and Permissions-Policy."},"grade":{"type":"string","description":"A+ to F, or n/a when the last response is a redirect (its headers belong to the page it points to)."},"checks":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"header":{"type":"string"},"present":{"type":"boolean"},"value":{"type":"string"},"rating":{"type":"string","enum":["good","ok","weak","missing"]},"weight":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"message":{"type":"string"}},"required":["id","header","present","rating","weight","message"],"additionalProperties":false}}},"required":["score","grade","checks"],"additionalProperties":false},"caching":{"type":"object","properties":{"cacheControl":{"type":"string"},"maxAge":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"sMaxAge":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"staleWhileRevalidate":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"noStore":{"type":"boolean"},"noCache":{"type":"boolean"},"private":{"type":"boolean"},"public":{"type":"boolean"},"immutable":{"type":"boolean"},"mustRevalidate":{"type":"boolean"},"expires":{"type":"string"},"etag":{"type":"boolean"},"lastModified":{"type":"string"},"age":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"vary":{"type":"string"},"cdnStatus":{"type":"string"},"cacheability":{"type":"string","enum":["no-store","revalidate","cacheable","unspecified"]},"summary":{"type":"string"}},"required":["noStore","noCache","private","public","immutable","mustRevalidate","cacheability","summary"],"additionalProperties":false},"cookies":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"secure":{"type":"boolean"},"httpOnly":{"type":"boolean"},"sameSite":{"type":"string"},"path":{"type":"string"},"domain":{"type":"string"},"persistent":{"type":"boolean"},"issues":{"type":"array","items":{"type":"string"}}},"required":["name","secure","httpOnly","persistent","issues"],"additionalProperties":false},"description":"Cookies set by the final response: names and flags only, never values."},"server":{"type":"object","properties":{"software":{"type":"string"},"version":{"type":"string"},"poweredBy":{"type":"string"},"cdn":{"type":"string"},"via":{"type":"string"},"versionDisclosed":{"type":"boolean"}},"required":["versionDisclosed"],"additionalProperties":false},"content":{"type":"object","properties":{"type":{"type":"string"},"length":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"encoding":{"type":"string"},"language":{"type":"string"}},"additionalProperties":false},"issues":{"type":"array","items":{"type":"object","properties":{"severity":{"type":"string","enum":["error","warning","info"]},"code":{"type":"string"},"message":{"type":"string"}},"required":["severity","code","message"],"additionalProperties":false}},"notes":{"type":"array","items":{"type":"string"}}},"required":["url","method","finalUrl","status","ok","hops","totalMs","redirects","security","caching","cookies","server","content","issues","notes"],"additionalProperties":false},"HttpHeadersResult":{"allOf":[{"$ref":"#/components/schemas/ToolResultEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/HttpHeadersOutput"}}}]},"IpConvertInput":{"type":"object","properties":{"address":{"type":"string","maxLength":32768,"description":"One or more IP addresses, one per line (commas and spaces also separate), up to 500. IPv4 dotted quads, IPv6 in any form, or integers written as decimal (3232235777), 0x hex (0xc0a80101) or 0b binary. Leading zeros in a dotted quad are rejected because they are ambiguous."},"mode":{"default":"all","description":"decimal: integer, hex and binary forms. v4-to-v6: IPv6 embeddings of IPv4 addresses. v6-to-v4: extract the IPv4 inside IPv6 addresses. all: whatever applies.","type":"string","enum":["all","decimal","v4-to-v6","v6-to-v4"]},"nat64Prefix":{"description":"Your own NAT64 prefix (/32, /40, /48, /56, /64 or /96, RFC 6052), e.g. 2001:db8:64::/96, used to embed and to extract.","type":"string","maxLength":64}},"required":["address"],"additionalProperties":false},"IpConvertOutput":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"input":{"type":"string"},"ok":{"type":"boolean"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"hint":{"type":"string"}},"required":["code","message"],"additionalProperties":false},"inputForm":{"description":"How the input was written.","type":"string","enum":["dotted","ipv6","decimal","hex","binary"]},"version":{"type":"number","enum":[4,6]},"address":{"description":"Canonical text form (dotted quad, or RFC 5952 for IPv6).","type":"string"},"type":{"type":"object","properties":{"kind":{"type":"string"},"name":{"type":"string"},"rfc":{"type":"string"},"isPublic":{"type":"boolean"}},"required":["kind","name","isPublic"],"additionalProperties":false},"numeric":{"type":"object","properties":{"integer":{"type":"string","description":"Unsigned decimal integer (exact; up to 39 digits for IPv6)."},"hex":{"type":"string"},"hexDotted":{"type":"string"},"binary":{"type":"string"},"signed32":{"description":"IPv4 only: the value a signed 32-bit INT column stores.","type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["integer","hex","binary"],"additionalProperties":false},"ipv6Embeddings":{"description":"IPv4 inputs: every standard way the address appears inside IPv6. These are NOT addresses you can be reached on.","type":"object","properties":{"mapped":{"type":"string"},"mappedHex":{"type":"string"},"nat64WellKnown":{"type":"string"},"nat64LocalUse":{"type":"string"},"nat64Custom":{"type":"string"},"sixToFour":{"type":"string"},"compatible":{"type":"string"},"isatap":{"type":"string"}},"required":["mapped","mappedHex","nat64WellKnown","nat64LocalUse","sixToFour","compatible","isatap"],"additionalProperties":false},"embeddedIpv4":{"description":"IPv6 inputs: the IPv4 address carried inside, or type \"none\" for a native IPv6 address.","type":"object","properties":{"type":{"type":"string","enum":["mapped","compatible","nat64-well-known","nat64-local-use","nat64-custom","6to4","teredo","isatap","none"]},"ipv4":{"type":"string"},"explanation":{"type":"string"},"teredo":{"type":"object","properties":{"server":{"type":"string"},"client":{"type":"string"},"port":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"flags":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["server","client","port","flags"],"additionalProperties":false}},"required":["type","explanation"],"additionalProperties":false},"notes":{"type":"array","items":{"type":"string"}}},"required":["input","ok","notes"],"additionalProperties":false}},"totals":{"type":"object","properties":{"items":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"ok":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"failed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["items","ok","failed"],"additionalProperties":false},"truncated":{"type":"boolean"}},"required":["items","totals","truncated"],"additionalProperties":false},"IpConvertResult":{"allOf":[{"$ref":"#/components/schemas/ToolResultEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/IpConvertOutput"}}}]},"IpLocationInput":{"type":"object","properties":{"q":{"type":"string","maxLength":2048,"description":"An IPv4 or IPv6 address, a domain name, or a URL (the host is used). A domain is resolved and each of its addresses (up to 6) is located. Private and reserved addresses are answered as special-purpose, not looked up."},"registry":{"default":true,"description":"Also ask the Regional Internet Registry (RDAP) which country the address block is registered in, and compare it with the DB-IP location. One extra lookup per address, for the first three addresses.","type":"boolean"}},"required":["q"],"additionalProperties":false},"IpLocationOutput":{"type":"object","properties":{"query":{"type":"string","description":"What was looked up: the address, or the domain name."},"kind":{"type":"string","enum":["ip","domain"]},"dns":{"description":"Only for a domain: how the name resolved.","type":"object","properties":{"status":{"type":"string","enum":["ok","nxdomain","nodata"]},"cnames":{"type":"array","items":{"type":"string"},"description":"CNAME chain the name goes through, in order."},"addressCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"How many distinct addresses the name has (A and AAAA)."},"minTtl":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["status","cnames","addressCount"],"additionalProperties":false},"addresses":{"type":"array","items":{"type":"object","properties":{"ip":{"type":"string"},"version":{"anyOf":[{"type":"number","const":4},{"type":"number","const":6}]},"status":{"type":"string","enum":["located","not_in_database","special_purpose"]},"special":{"type":"object","properties":{"kind":{"type":"string"},"name":{"type":"string","description":"What kind of reserved address this is, e.g. \"Private-use\" or \"Loopback\"."},"rfc":{"type":"string"}},"required":["kind","name"],"additionalProperties":false},"location":{"type":"object","properties":{"city":{"type":"string"},"region":{"type":"string"},"country":{"type":"object","properties":{"code":{"type":"string"},"name":{"type":"string"},"euMember":{"type":"boolean"}},"required":["code","name"],"additionalProperties":false},"continent":{"type":"object","properties":{"code":{"type":"string"},"name":{"type":"string"}},"required":["code","name"],"additionalProperties":false},"latitude":{"description":"Approximate centre of the area, degrees, rounded to 2 decimals (about a kilometre). Not a street address.","type":"number"},"longitude":{"type":"number"},"precision":{"type":"string","enum":["city","region","country"],"description":"The finest level DB-IP has for this address."},"typicalRadiusKm":{"description":"A rule-of-thumb size of the area, in kilometres (50 for a city, 250 for a region, absent for a country). DB-IP publishes no accuracy figure per address, so this is a guide, not a measurement.","type":"number"}},"required":["precision"],"additionalProperties":false},"network":{"type":"object","properties":{"asn":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"organization":{"type":"string"},"range":{"type":"string","description":"The address range DB-IP's ASN record covers (CIDR). A database range, not necessarily the prefix announced in BGP."}},"required":["asn","organization","range"],"additionalProperties":false},"registry":{"type":"object","properties":{"status":{"type":"string","enum":["found","not_found","unavailable","skipped"],"description":"\"skipped\" when the registry lookup was not made (switched off, budget used up, or more addresses than we look up)."},"country":{"description":"Country the address block is registered in (ISO 3166-1 alpha-2). Where the block is registered, not where it is used.","type":"string"},"ownerCountry":{"description":"Set when the registry record has no country of its own (ARIN records do not): the country in the registrant's postal address, as written there.","type":"string"},"name":{"type":"string"},"rir":{"type":"string"},"range":{"type":"string"}},"required":["status"],"additionalProperties":false},"agreement":{"type":"object","properties":{"verdict":{"type":"string","enum":["agree","differ","single_source"],"description":"\"agree\": DB-IP and the registry name the same country. \"differ\": they name different countries. \"single_source\": only one of them has an answer."},"sources":{"type":"array","items":{"type":"object","properties":{"source":{"type":"string"},"country":{"type":"string"},"detail":{"type":"string"}},"required":["source"],"additionalProperties":false}},"summary":{"type":"string"}},"required":["verdict","sources","summary"],"additionalProperties":false},"anycast":{"description":"Set when the address is a well-known anycast service (a public DNS resolver) or sits on a CDN network: it is answered from many places at once, so the location says little about where a visitor is served.","type":"string"},"notes":{"type":"array","items":{"type":"string"}}},"required":["ip","version","status","notes"],"additionalProperties":false}},"truncated":{"type":"boolean","description":"The name has more addresses than the 6 located here."},"accuracy":{"type":"string","description":"The plain warning to show with any IP location."},"notes":{"type":"array","items":{"type":"string"}},"data":{"type":"object","properties":{"city":{"description":"The DB-IP Lite city database in use: monthly release and build time.","type":"object","properties":{"release":{"type":"string"},"builtAt":{"type":"string"}},"required":["release","builtAt"],"additionalProperties":false},"asn":{"description":"The DB-IP Lite ASN database in use.","type":"object","properties":{"release":{"type":"string"},"builtAt":{"type":"string"}},"required":["release","builtAt"],"additionalProperties":false}},"additionalProperties":false,"description":"The DB-IP Lite database releases the answer came from."},"attribution":{"type":"object","properties":{"text":{"type":"string","description":"The credit the data licence requires: show it, linked to url, wherever these results are shown."},"url":{"type":"string"},"license":{"type":"string"},"licenseUrl":{"type":"string"}},"required":["text","url","license","licenseUrl"],"additionalProperties":false}},"required":["query","kind","addresses","truncated","accuracy","notes","data","attribution"],"additionalProperties":false},"IpLocationResult":{"allOf":[{"$ref":"#/components/schemas/ToolResultEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/IpLocationOutput"}}}]},"IpRangeConvertInput":{"type":"object","properties":{"input":{"type":"string","maxLength":65536,"description":"One item per line (commas and semicolons also separate): CIDR blocks such as 10.0.0.0/24 or 2001:db8::/48, or ranges such as \"10.0.0.1 - 10.0.0.9\", \"10.0.0.5-20\", \"192.0.2.1 to 192.0.2.77\". IPv4 and IPv6, up to 1,000 items."},"mode":{"default":"auto","description":"auto detects each line; cidr-to-range expects CIDR blocks; range-to-cidr expects start-end ranges.","type":"string","enum":["auto","cidr-to-range","range-to-cidr"]},"family":{"default":"any","description":"Only accept this IP family: 4, 6 or any.","type":"string","enum":["4","6","any"]}},"required":["input"],"additionalProperties":false},"IpRangeConvertOutput":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"input":{"type":"string"},"ok":{"type":"boolean"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"hint":{"type":"string"}},"required":["code","message"],"additionalProperties":false},"kind":{"description":"What the input was: a CIDR block, a start-end range or a single address.","type":"string","enum":["cidr","range","host"]},"version":{"type":"number","enum":[4,6]},"start":{"type":"string"},"end":{"type":"string"},"count":{"description":"Exact number of addresses, as a decimal string.","type":"string"},"countExponent":{"description":"n when the count is exactly 2^n, else null.","anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"startInteger":{"type":"string"},"endInteger":{"type":"string"},"startExpanded":{"description":"IPv6 only: full 32-digit form.","type":"string"},"endExpanded":{"description":"IPv6 only: full 32-digit form.","type":"string"},"netmask":{"description":"IPv4 only, when the range is exactly one block.","type":"string"},"wildcard":{"description":"IPv4 only, when the range is exactly one block.","type":"string"},"cidrs":{"description":"The minimal exact list of CIDR blocks covering the range.","type":"array","items":{"type":"string"}},"covering":{"description":"Smallest single block containing the range and how many addresses beyond the range it would also include. Only given when the range needs several blocks.","type":"object","properties":{"cidr":{"type":"string"},"extraAddresses":{"type":"string"}},"required":["cidr","extraAddresses"],"additionalProperties":false},"hostBitsSet":{"type":"boolean"},"subnets64":{"description":"IPv6 only: how many /64 subnets the block holds.","type":"string"},"subnets56":{"description":"IPv6 only: how many /56 subnets the block holds.","type":"string"},"reverseZone":{"type":["string","null"]},"warnings":{"type":"array","items":{"type":"string"}}},"required":["input","ok","warnings"],"additionalProperties":false}},"totals":{"type":"object","properties":{"items":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"ok":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"failed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"cidrBlocks":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["items","ok","failed","cidrBlocks"],"additionalProperties":false},"truncated":{"type":"boolean","description":"True when more than 1,000 items were given and the rest were ignored."}},"required":["items","totals","truncated"],"additionalProperties":false},"IpRangeConvertResult":{"allOf":[{"$ref":"#/components/schemas/ToolResultEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/IpRangeConvertOutput"}}}]},"IpWhoisInput":{"type":"object","properties":{"q":{"type":"string","minLength":1,"maxLength":512,"description":"IPv4 or IPv6 address, or a CIDR block, e.g. 8.8.8.8, 2606:4700:4700::1111 or 1.1.1.0/24. Brackets, ports and URLs around an address are removed."},"includeRaw":{"default":false,"description":"Include the raw RDAP JSON from the Regional Internet Registry in the result. Large; off by default.","type":"boolean"}},"required":["q"],"additionalProperties":false},"IpWhoisOutput":{"type":"object","properties":{"query":{"type":"object","properties":{"kind":{"type":"string","enum":["domain","ip","autnum","nameserver","entity","tld"]},"key":{"type":"string"},"display":{"type":"string"},"input":{"type":"string"},"notices":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"],"additionalProperties":{}},"description":"What was changed to make the input usable (URL reduced to a host, IDN converted, ...)."}},"required":["kind","key","display","input","notices"],"additionalProperties":{}},"status":{"type":"string","enum":["found","not_found","special_purpose","no_rdap_service"],"description":"found: a record exists. not_found: the registry says there is none. special_purpose: reserved address space or AS number, nothing to look up. no_rdap_service: no RDAP (and for domains no WHOIS) service exists."},"source":{"type":"string","enum":["rdap","whois","none"],"description":"Where the record came from."},"availability":{"description":"Domains only. \"likely-available\" is a registry saying there is no record; premium or reserved names can still be unavailable.","type":"object","properties":{"verdict":{"type":"string","enum":["likely-available","registered","likely-available-whois","unknown"]},"caveats":{"type":"array","items":{"type":"string"}},"registerLinks":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"url":{"type":"string"},"affiliate":{"type":"boolean"}},"required":["name","url","affiliate"],"additionalProperties":{}}}},"required":["verdict","caveats","registerLinks"],"additionalProperties":{}},"registrar":{"description":"Outcome of asking the registrar after the registry. The merged data is in domain.","type":"object","properties":{"status":{"type":"string"},"url":{"type":"string"}},"required":["status"],"additionalProperties":{}},"whois":{"description":"Raw WHOIS reply, only when the TLD has no RDAP service.","type":"object","properties":{"server":{"type":"string"},"text":{"type":"string"},"notFound":{"type":"boolean"},"rateLimited":{"type":"boolean"},"referralChain":{"type":"array","items":{"type":"string"}}},"required":["server","text","notFound","rateLimited","referralChain"],"additionalProperties":{}},"error":{"type":"object","properties":{"code":{"type":"string"},"httpStatus":{"type":"number"},"title":{"type":"string"},"description":{"type":"array","items":{"type":"string"}},"retryAfter":{"type":"number"}},"required":["code"],"additionalProperties":{}},"provenance":{"type":"object","properties":{"bootstrap":{"type":"object","properties":{"kind":{"type":"string"},"entry":{"type":"string"},"source":{"type":"string"}},"required":["kind","entry","source"],"additionalProperties":{}},"serverUrl":{"type":"string"},"queryUrl":{"type":"string"},"finalUrl":{"type":"string"},"registrarUrl":{"type":"string"},"whoisServer":{"type":"string"},"trace":{"type":"array","items":{"type":"object","properties":{"step":{"type":"string"},"label":{"type":"string"},"ms":{"type":"number"},"url":{"type":"string"},"host":{"type":"string"},"status":{"type":["number","string"]},"note":{"type":"string"}},"required":["step","label","ms"],"additionalProperties":{}}},"totalMs":{"type":"number"},"fetchedAt":{"type":"string"},"cache":{"type":"string","enum":["hit","miss","stale","coalesced","bypass","hit-or-miss"]},"stale":{"description":"True when this is a stored copy served because the registry is not answering.","type":"boolean"}},"required":["trace","totalMs","fetchedAt","cache"],"additionalProperties":{},"description":"How the answer was obtained: which bootstrap entry, which servers, timings."},"raw":{"description":"Raw upstream RDAP JSON. Only with includeRaw.","type":"object","properties":{"registry":{},"registrar":{}},"additionalProperties":{}},"ip":{"type":"object","properties":{"objectClassName":{"type":"string","const":"ip network"},"handle":{"type":"string"},"startAddress":{"type":"string"},"endAddress":{"type":"string"},"ipVersion":{"type":"string","enum":["v4","v6"]},"name":{"type":"string"},"type":{"type":"string"},"country":{"type":"string"},"parentHandle":{"type":"string"},"cidrs":{"type":"array","items":{"type":"string"}},"status":{"type":"array","items":{"type":"string"}},"events":{"type":"object","properties":{"registration":{"type":"object","properties":{"action":{"type":"string"},"raw":{"type":"string"},"date":{"description":"ISO-8601 UTC.","type":"string"}},"required":["action","raw"],"additionalProperties":{}},"expiration":{"type":"object","properties":{"action":{"type":"string"},"raw":{"type":"string"},"date":{"description":"ISO-8601 UTC.","type":"string"}},"required":["action","raw"],"additionalProperties":{}},"lastChanged":{"type":"object","properties":{"action":{"type":"string"},"raw":{"type":"string"},"date":{"description":"ISO-8601 UTC.","type":"string"}},"required":["action","raw"],"additionalProperties":{}},"registrarExpiration":{"type":"object","properties":{"action":{"type":"string"},"raw":{"type":"string"},"date":{"description":"ISO-8601 UTC.","type":"string"}},"required":["action","raw"],"additionalProperties":{}},"all":{"type":"array","items":{},"description":"Every event as the registry sent it: { action, raw, date?, actor? }."}},"required":["all"],"additionalProperties":{}},"contacts":{"type":"array","items":{"type":"object","properties":{"roles":{"type":"array","items":{"type":"string"}},"name":{"type":"string"},"org":{"type":"string"},"emails":{"type":"array","items":{"type":"string"}},"isRedacted":{"type":"boolean"}},"required":["roles","emails","isRedacted"],"additionalProperties":{}}},"abuse":{"type":"object","properties":{"email":{"type":"string"},"phone":{"type":"string"}},"additionalProperties":{}},"rir":{"type":"string"},"originAutnums":{"type":"array","items":{"type":"number"}}},"required":["objectClassName","cidrs","status","events","contacts","originAutnums"],"additionalProperties":{}}},"required":["query","status","source","provenance"],"additionalProperties":{}},"IpWhoisResult":{"allOf":[{"$ref":"#/components/schemas/ToolResultEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/IpWhoisOutput"}}}]},"Ipv6FormatInput":{"type":"object","properties":{"addresses":{"type":"string","maxLength":65536,"description":"One or more IPv6 addresses, one per line (commas and spaces also separate), up to 1,000. Prefix lengths (/64), zone ids (%eth0), [brackets] with :port and URL hosts (http://[2001:db8::1]:8080/) are accepted and kept."},"style":{"default":"all","description":"compressed returns only the RFC 5952 form, expanded only the full forms, all returns everything.","type":"string","enum":["all","compressed","expanded"]}},"required":["addresses"],"additionalProperties":false},"Ipv6FormatOutput":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"input":{"type":"string"},"ok":{"type":"boolean"},"error":{"type":"object","properties":{"message":{"type":"string"},"hint":{"type":"string"},"position":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["message"],"additionalProperties":false},"result":{"description":"The input reformatted in the requested style, with any prefix, zone id, brackets, port and URL around it left intact.","type":"string"},"compressed":{"description":"RFC 5952 canonical form (IPv4-mapped addresses keep their dotted ending).","type":"string"},"compressedHex":{"description":"RFC 5952 form using hex groups only, even for IPv4-mapped addresses.","type":"string"},"expanded":{"description":"Eight 4-digit groups: 2001:0db8:0000:…","type":"string"},"uncompressed":{"description":"Eight groups with leading zeros removed and no \"::\".","type":"string"},"nibbles":{"description":"The 32 hex digits least-significant first, as used under ip6.arpa.","type":"string"},"ip6Arpa":{"type":"string"},"binary":{"type":"string"},"mixed":{"description":"Mixed notation with a dotted-quad ending, e.g. 64:ff9b::8.8.8.8.","type":"string"},"prefix":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"zone":{"type":"string"},"port":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"canonical":{"description":"True when the address text was already in canonical form.","type":"boolean"},"changes":{"description":"Why the input was not canonical.","type":"array","items":{"type":"string"}}},"required":["input","ok"],"additionalProperties":false}},"totals":{"type":"object","properties":{"items":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"ok":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"failed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["items","ok","failed"],"additionalProperties":false},"truncated":{"type":"boolean"}},"required":["items","totals","truncated"],"additionalProperties":false},"Ipv6FormatResult":{"allOf":[{"$ref":"#/components/schemas/ToolResultEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Ipv6FormatOutput"}}}]},"MacLookupInput":{"type":"object","properties":{"query":{"type":"string","maxLength":65536,"description":"One or more MAC addresses, OUIs or block prefixes, one per line (commas and spaces also separate), up to 500. Any notation: aa:bb:cc:dd:ee:ff, aa-bb-cc-dd-ee-ff, aabb.ccdd.eeff, aabbccddeeff, or just the first 6 digits (the OUI). Pasted ARP or DHCP table rows are fine: the MAC addresses in each row are found. Or a company name such as \"Raspberry Pi\" to list that company's registered blocks."},"mode":{"default":"auto","description":"auto: a single line that is not a MAC address but looks like a company name is searched as a name. mac: always read the input as addresses. vendor: always search registered company names.","type":"string","enum":["auto","mac","vendor"]}},"required":["query"],"additionalProperties":false},"MacLookupOutput":{"type":"object","properties":{"mode":{"type":"string","enum":["mac","vendor"]},"items":{"type":"array","items":{"type":"object","properties":{"input":{"type":"string"},"ok":{"type":"boolean"},"error":{"type":"object","properties":{"message":{"type":"string"},"hint":{"type":"string"}},"required":["message"],"additionalProperties":false},"kind":{"description":"mac: a full 48-bit address. eui64: a 64-bit identifier. prefix: only the first 6 to 11 hex digits (an OUI or a longer block prefix).","type":"string","enum":["mac","eui64","prefix"]},"normalized":{"description":"Upper-case colon form, e.g. 00:50:56:C0:00:08. A prefix that is not a whole number of bytes ends in a single digit.","type":"string"},"formats":{"description":"The same address written the common ways. cisco (aabb.ccdd.eeff) is given for full 48-bit addresses only.","type":"object","properties":{"colon":{"type":"string"},"hyphen":{"type":"string"},"cisco":{"type":"string"},"bare":{"type":"string"}},"required":["colon","hyphen","bare"],"additionalProperties":false},"found":{"description":"True when the prefix is in an IEEE registry.","type":"boolean"},"block":{"description":"Which registry block matched: MA-L (24-bit), MA-M (28-bit), MA-S or IAB (36-bit), or CID (24-bit company ID for locally administered use). The longest matching block wins.","type":"object","properties":{"type":{"type":"string","enum":["MA-L","MA-M","MA-S","IAB","CID"]},"bits":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"prefix":{"type":"string","description":"The matched prefix in colon form."}},"required":["type","bits","prefix"],"additionalProperties":false},"vendor":{"description":"The registered organisation. \"Private\" means the owner asked the IEEE to keep its name out of the public list.","type":"string"},"vendorPrivate":{"type":"boolean"},"vendorAddress":{"type":"string"},"country":{"description":"ISO 3166-1 alpha-2 code read from the registered address (best effort; absent when the address does not say).","type":"string"},"addressType":{"type":"string","enum":["universal-unicast","local-unicast","universal-multicast","local-multicast","broadcast"]},"firstByte":{"type":"object","properties":{"hex":{"type":"string"},"binary":{"type":"string"}},"required":["hex","binary"],"additionalProperties":false},"multicast":{"description":"The I/G bit: the address is for a group of devices.","type":"boolean"},"locallyAdministered":{"description":"The U/L bit: set by software or an admin, not assigned by a manufacturer.","type":"boolean"},"randomizedLikely":{"description":"A unicast address with the locally administered bit set that is not a known virtual machine or container prefix: the shape of the private or random Wi-Fi addresses phones and laptops use. A strong hint, not proof.","type":"boolean"},"specialUse":{"description":"A well-known address: broadcast, IPv4 or IPv6 multicast, spanning tree, LLDP, VRRP, documentation range and so on.","type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"note":{"type":"string"},"rfc":{"type":"string"}},"required":["id","name","note"],"additionalProperties":false},"vmVendor":{"description":"The hypervisor or container system whose prefix this is (VMware, Hyper-V, QEMU/KVM, VirtualBox, Xen, Parallels, Docker).","type":"string"},"notes":{"type":"array","items":{"type":"string"}}},"required":["input","ok","notes"],"additionalProperties":false}},"totals":{"type":"object","properties":{"items":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"ok":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"failed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"found":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Addresses whose prefix is in an IEEE registry."},"randomized":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"multicast":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"virtual":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["items","ok","failed","found","randomized","multicast","virtual"],"additionalProperties":false},"truncated":{"type":"boolean"},"vendorSearch":{"type":"object","properties":{"query":{"type":"string"},"totalVendors":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"totalBlocks":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"vendors":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"address":{"type":"string"},"country":{"type":"string"},"blockCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"types":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"blocks":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["MA-L","MA-M","MA-S","IAB","CID"]},"bits":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"prefix":{"type":"string"}},"required":["type","bits","prefix"],"additionalProperties":false}}},"required":["name","blockCount","types","blocks"],"additionalProperties":false}},"truncated":{"type":"boolean","description":"More companies match than are listed, or a company has more blocks than are listed."}},"required":["query","totalVendors","totalBlocks","vendors","truncated"],"additionalProperties":false},"dataset":{"type":"object","properties":{"snapshot":{"type":"string","description":"Date the bundled IEEE lists were taken (YYYY-MM-DD). The lists carry no assignment dates."},"source":{"type":"string"},"blocks":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["snapshot","source","blocks"],"additionalProperties":false}},"required":["mode","items","totals","truncated","dataset"],"additionalProperties":false},"MacLookupResult":{"allOf":[{"$ref":"#/components/schemas/ToolResultEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/MacLookupOutput"}}}]},"PasswordGenerateInput":{"type":"object","properties":{"mode":{"default":"password","description":"password: random characters. passphrase: random words from a 1,024-word list (10 bits each). pin: random digits.","type":"string","enum":["password","passphrase","pin"]},"length":{"description":"Characters in a password (4-128, default 20) or digits in a PIN (4-12, default 6). Ignored for passphrases.","type":"integer","minimum":4,"maximum":128},"words":{"description":"Words in a passphrase (3-12, default 6).","type":"integer","minimum":3,"maximum":12},"lower":{"default":true,"description":"Password: include lowercase letters.","type":"boolean"},"upper":{"default":true,"description":"Password: include uppercase letters.","type":"boolean"},"digits":{"default":true,"description":"Password: include digits.","type":"boolean"},"symbols":{"default":true,"description":"Password: include symbols (!@#$%^&*()-_=+[]{};:,.?/~).","type":"boolean"},"excludeSimilar":{"default":false,"description":"Password: leave out look-alike characters (i l L I | 1 o O 0).","type":"boolean"},"exclude":{"default":"","description":"Password: extra characters to never use.","type":"string","maxLength":64},"requireEach":{"default":true,"description":"Password: guarantee at least one character from every selected class.","type":"boolean"},"separator":{"default":"-","description":"Passphrase: text between words.","type":"string","maxLength":4},"capitalize":{"default":false,"description":"Passphrase: capitalise each word.","type":"boolean"},"includeNumber":{"default":false,"description":"Passphrase: add one random digit to one random word.","type":"boolean"},"count":{"default":1,"description":"How many to generate (1-50).","type":"integer","minimum":1,"maximum":50}},"additionalProperties":false},"PasswordGenerateOutput":{"type":"object","properties":{"mode":{"type":"string","enum":["password","passphrase","pin"]},"passwords":{"type":"array","items":{"type":"string"},"description":"The generated values. Fresh and random on every call."},"entropyBits":{"type":"number","description":"Entropy of the generator for each value, in bits (rounded to 0.1)."},"strength":{"type":"string","enum":["weak","fair","strong","very-strong"]},"characters":{"description":"Length of each value in characters (passwords and PINs).","type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"poolSize":{"description":"Number of distinct characters drawn from (passwords).","type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"wordCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"wordListSize":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"warnings":{"type":"array","items":{"type":"string"}}},"required":["mode","passwords","entropyBits","strength","warnings"],"additionalProperties":false},"PasswordGenerateResult":{"allOf":[{"$ref":"#/components/schemas/ToolResultEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/PasswordGenerateOutput"}}}]},"PunycodeConvertInput":{"type":"object","properties":{"domains":{"type":"string","maxLength":65536,"description":"One or more domain names, URLs or e-mail addresses, one per line (commas and spaces also separate), up to 500. Unicode names (bücher.de, 例え.jp, пример.рф) or Punycode (xn--bcher-kva.de). Only the domain part of a URL or e-mail address is converted."}},"required":["domains"],"additionalProperties":false},"PunycodeConvertOutput":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"input":{"type":"string"},"ok":{"type":"boolean"},"error":{"type":"object","properties":{"code":{"type":"string","enum":["EMPTY","TOO_LONG","EMPTY_LABEL","LABEL_TOO_LONG","NAME_TOO_LONG","INVALID_CHARACTERS","INVALID_PUNYCODE","INVALID_DOMAIN","INVALID_HYPHEN","LOOKS_LIKE_IP"]},"message":{"type":"string"},"label":{"type":"string"}},"required":["code","message"],"additionalProperties":false},"ascii":{"description":"Lowercase A-label (xn--) form, safe for DNS, WHOIS and URLs.","type":"string"},"unicode":{"description":"U-label form for display.","type":"string"},"isIdn":{"type":"boolean"},"asciiLength":{"description":"Length of the whole A-label name; the limit is 253.","type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"labels":{"type":"array","items":{"type":"object","properties":{"unicode":{"type":"string"},"ascii":{"type":"string"},"octets":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Length of the A-label in octets; the limit is 63."},"isIdn":{"type":"boolean"},"scripts":{"type":"array","items":{"type":"string"}}},"required":["unicode","ascii","octets","isIdn","scripts"],"additionalProperties":false}},"extractedFrom":{"description":"Set when the domain was cut out of a URL or e-mail address.","type":"string","enum":["url","email"]},"transitional":{"description":"What older IDNA2003 transitional processing would produce, given only when it differs (ß, ς, ZWJ/ZWNJ).","type":"object","properties":{"ascii":{"type":"string"},"unicode":{"type":"string"}},"required":["ascii","unicode"],"additionalProperties":false},"warnings":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string","enum":["MIXED_SCRIPT","CONFUSABLE","EMOJI","COMPAT_MAPPED","TRANSITIONAL_DIFFERS","UNDERSCORE"]},"message":{"type":"string"},"label":{"type":"string"}},"required":["code","message"],"additionalProperties":false}}},"required":["input","ok","warnings"],"additionalProperties":false}},"totals":{"type":"object","properties":{"items":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"ok":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"failed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"idn":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"withWarnings":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["items","ok","failed","idn","withWarnings"],"additionalProperties":false},"truncated":{"type":"boolean"}},"required":["items","totals","truncated"],"additionalProperties":false},"PunycodeConvertResult":{"allOf":[{"$ref":"#/components/schemas/ToolResultEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/PunycodeConvertOutput"}}}]},"ReverseDnsInput":{"type":"object","properties":{"ip":{"type":"string","maxLength":253,"description":"A public IPv4 or IPv6 address, e.g. 8.8.8.8 or 2001:4860:4860::8888. A full in-addr.arpa / ip6.arpa name or a URL containing an address is reduced to the address. Private and reserved addresses are refused."},"forwardConfirm":{"default":true,"description":"Also resolve each returned host name (up to 5) and check that it points back to the same address (forward-confirmed reverse DNS, what mail servers and bot verification rely on).","type":"boolean"}},"required":["ip"],"additionalProperties":false},"ReverseDnsOutput":{"type":"object","properties":{"ip":{"type":"string"},"version":{"anyOf":[{"type":"number","const":4},{"type":"number","const":6}]},"arpa":{"type":"string","description":"The reverse name that was queried."},"status":{"type":"string","enum":["found","none","failed"],"description":"found = at least one PTR record, none = the address has no PTR record, failed = the resolver returned SERVFAIL or REFUSED."},"rcode":{"type":"string","enum":["NOERROR","NXDOMAIN","SERVFAIL","REFUSED","FORMERR","NOTIMP","TIMEOUT","NETWORK"]},"hostnames":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"ttl":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["name","ttl"],"additionalProperties":false}},"forwardConfirm":{"type":"object","properties":{"status":{"type":"string","enum":["confirmed","partial","failed","unverified","skipped","none"],"description":"confirmed = every checked name resolves back to the address, partial = some do, failed = none do, unverified = the forward lookups got no answer, skipped = not requested, none = there is no PTR name to check."},"checked":{"type":"array","items":{"type":"object","properties":{"hostname":{"type":"string"},"addresses":{"type":"array","items":{"type":"string"},"description":"Addresses of the same family the host name resolves to."},"matches":{"type":"boolean","description":"The address is among them."},"rcode":{"type":"string","enum":["NOERROR","NXDOMAIN","SERVFAIL","REFUSED","FORMERR","NOTIMP","TIMEOUT","NETWORK"]}},"required":["hostname","addresses","matches","rcode"],"additionalProperties":false}}},"required":["status","checked"],"additionalProperties":false},"resolver":{"type":"string"},"ms":{"type":"number"},"minTtl":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"notes":{"type":"array","items":{"type":"string"}}},"required":["ip","version","arpa","status","rcode","hostnames","forwardConfirm","resolver","ms","notes"],"additionalProperties":false},"ReverseDnsResult":{"allOf":[{"$ref":"#/components/schemas/ToolResultEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ReverseDnsOutput"}}}]},"SecurityHeadersInput":{"type":"object","properties":{"url":{"type":"string","maxLength":2048,"description":"URL or host to check, e.g. https://example.com/ or example.com (https is tried first, then http). Only public http(s) addresses on ports 80, 443, 8080 and 8443 are fetched; private, loopback and internal addresses are refused."},"followRedirects":{"default":true,"description":"Follow redirects (up to 10 hops, each checked again) and grade the final response, or stop at the first response. A redirect response is not graded.","type":"boolean"},"platform":{"default":"header","description":"Format of the copy-paste fix snippets: header (a plain header line), nginx, apache, caddy, cloudflare, vercel, netlify, nextjs or express.","type":"string","enum":["header","nginx","apache","caddy","cloudflare","vercel","netlify","nextjs","express"]}},"required":["url"],"additionalProperties":false},"SecurityHeadersOutput":{"type":"object","properties":{"url":{"type":"string","description":"The URL that was requested (canonical form)."},"finalUrl":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Status of the last response."},"statusText":{"type":"string"},"https":{"type":"boolean","description":"The final response came over HTTPS."},"platform":{"type":"string","enum":["header","nginx","apache","caddy","cloudflare","vercel","netlify","nextjs","express"]},"hops":{"type":"array","items":{"type":"object","properties":{"url":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"ms":{"type":"number"}},"required":["url","status","ms"],"additionalProperties":false}},"redirects":{"type":"object","properties":{"count":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"loop":{"type":"boolean"},"httpsUpgrade":{"type":"boolean"},"downgrade":{"type":"boolean"},"crossDomain":{"type":"boolean"},"chain":{"type":"array","items":{"type":"object","properties":{"from":{"type":"string"},"to":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["from","to","status"],"additionalProperties":false}}},"required":["count","loop","httpsUpgrade","downgrade","crossDomain","chain"],"additionalProperties":false},"totalMs":{"type":"number"},"grade":{"type":"string","description":"A+ to F, or n/a when the last response is a redirect (its headers belong to the page it points to)."},"score":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"0-100: points earned by the nine headers, minus penalties, capped at 59 over plain HTTP."},"scoring":{"type":"object","properties":{"earned":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Points earned by the nine headers (out of 100)."},"penalty":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Points taken off for leaked versions, harmful deprecated headers, a bad CORS pair and conflicting repeats (at most 20)."},"cap":{"type":"object","properties":{"reason":{"type":"string"},"maxScore":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["reason","maxScore"],"additionalProperties":false}},"required":["earned","penalty"],"additionalProperties":false},"checks":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","enum":["csp","hsts","frame-protection","content-type-options","referrer-policy","permissions-policy","coop","coep","corp"]},"header":{"type":"string"},"present":{"type":"boolean","description":"The header (or, for frame protection, X-Frame-Options or frame-ancestors) is sent and enforced."},"value":{"description":"What the server sent, clipped.","type":"string"},"rating":{"type":"string","enum":["good","ok","weak","missing"]},"weight":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Points this header can earn; the nine weights add up to 100."},"points":{"type":"number","description":"Points earned: weight x 1 (good), 0.6 (ok), 0.25 (weak) or 0 (missing)."},"what":{"type":"string","description":"What the header is."},"why":{"type":"string","description":"Why it matters."},"message":{"type":"string","description":"What this response does."},"fix":{"description":"Present when the rating is not good and a header line would improve it.","type":"object","properties":{"header":{"type":"string","description":"The header line to send, e.g. \"X-Content-Type-Options: nosniff\"."},"name":{"type":"string"},"value":{"type":"string"},"snippet":{"type":"string","description":"The same header written for the chosen platform."}},"required":["header","name","value","snippet"],"additionalProperties":false}},"required":["id","header","present","rating","weight","points","what","why","message"],"additionalProperties":false}},"extras":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"header":{"type":"string"},"severity":{"type":"string","enum":["warning","info"]},"penalty":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Points this finding took off the score."},"message":{"type":"string"},"fix":{"type":"string"}},"required":["id","header","severity","penalty","message"],"additionalProperties":false},"description":"Warnings beyond the nine headers: leaked versions, deprecated or harmful headers, CORS and repeated headers."},"duplicates":{"type":"array","items":{"type":"object","properties":{"header":{"type":"string"},"values":{"type":"array","items":{"type":"string"}},"conflicting":{"type":"boolean"},"message":{"type":"string"}},"required":["header","values","conflicting","message"],"additionalProperties":false},"description":"Headers sent more than once, with their values."},"csp":{"type":"object","properties":{"mode":{"type":"string","enum":["enforced","report-only","none"]},"policyCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"directives":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"sources":{"type":"array","items":{"type":"string"}}},"required":["name","sources"],"additionalProperties":false}},"findings":{"type":"array","items":{"type":"object","properties":{"severity":{"type":"string","enum":["high","medium","low","info"]},"code":{"type":"string"},"message":{"type":"string"},"fix":{"type":"string"}},"required":["severity","code","message"],"additionalProperties":false}}},"required":["mode","policyCount","directives","findings"],"additionalProperties":false},"cookies":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"secure":{"type":"boolean"},"httpOnly":{"type":"boolean"},"sameSite":{"type":"string"},"path":{"type":"string"},"domain":{"type":"string"},"persistent":{"type":"boolean"},"issues":{"type":"array","items":{"type":"string"}}},"required":["name","secure","httpOnly","persistent","issues"],"additionalProperties":false},"description":"Cookies set by the final response: names and flags only, never values. Not part of the score."},"server":{"type":"object","properties":{"software":{"type":"string"},"version":{"type":"string"},"poweredBy":{"type":"string"},"cdn":{"type":"string"},"versionDisclosed":{"type":"boolean"}},"required":["versionDisclosed"],"additionalProperties":false},"headers":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"value":{"type":"string"}},"required":["name","value"],"additionalProperties":false},"description":"Every response header line of the final response, in order (Set-Cookie left out)."},"issues":{"type":"array","items":{"type":"object","properties":{"severity":{"type":"string","enum":["error","warning","info"]},"code":{"type":"string"},"message":{"type":"string"}},"required":["severity","code","message"],"additionalProperties":false}},"notes":{"type":"array","items":{"type":"string"}}},"required":["url","finalUrl","status","https","platform","hops","redirects","totalMs","grade","score","scoring","checks","extras","duplicates","csp","cookies","server","headers","issues","notes"],"additionalProperties":false},"SecurityHeadersResult":{"allOf":[{"$ref":"#/components/schemas/ToolResultEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/SecurityHeadersOutput"}}}]},"SpfCheckInput":{"type":"object","properties":{"domain":{"type":"string","maxLength":253,"description":"Domain whose SPF record to check, e.g. example.com. A URL or e-mail address is reduced to its domain; Unicode names are converted to Punycode."}},"required":["domain"],"additionalProperties":false},"SpfCheckOutput":{"type":"object","properties":{"domain":{"type":"string"},"status":{"type":"string","enum":["ok","warning","error","missing","nxdomain","dns-error"],"description":"ok = valid, warning = valid with warnings, error = receivers will return a permanent error (permerror), missing = no SPF record, nxdomain = the domain does not exist, dns-error = the resolver returned SERVFAIL or REFUSED."},"valid":{"type":"boolean","description":"A record exists and a receiver can evaluate it (no permerror conditions)."},"record":{"description":"The SPF record text (TXT strings joined).","type":"string"},"records":{"type":"array","items":{"type":"string"},"description":"Every TXT record that starts with v=spf1 (more than one is an error)."},"terms":{"type":"array","items":{"type":"string"},"description":"The record's terms, normalised."},"length":{"description":"Record length in bytes.","type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"policy":{"type":"object","properties":{"all":{"description":"Final mechanism, e.g. -all.","type":"string"},"result":{"type":"string","enum":["pass","fail","softfail","neutral"]},"redirect":{"type":"string"},"summary":{"type":"string"}},"required":["summary"],"additionalProperties":false},"lookups":{"type":"object","properties":{"count":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"DNS-lookup terms in the whole tree (worst case: every term is visited)."},"limit":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"exceeded":{"type":"boolean"},"atLeast":{"type":"boolean","description":"The walk was capped, so count is a lower bound."}},"required":["count","limit","exceeded","atLeast"],"additionalProperties":false},"voidLookups":{"type":"object","properties":{"count":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"limit":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"exceeded":{"type":"boolean"}},"required":["count","limit","exceeded"],"additionalProperties":false},"authorized":{"type":"object","properties":{"ip4":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"ip6":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["ip4","ip6"],"additionalProperties":false,"description":"Number of ip4 / ip6 mechanisms across the tree."},"tree":{"type":"array","items":{"type":"object","properties":{"domain":{"type":"string"},"via":{"type":"string","enum":["root","include","redirect"],"description":"How the record was reached."},"depth":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"parent":{"description":"Domain of the record that referenced this one.","type":"string"},"found":{"type":"boolean","description":"An SPF record was found and evaluated."},"record":{"type":"string"},"all":{"description":"The \"all\" mechanism of this record, e.g. ~all.","type":"string"},"lookups":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"DNS-lookup terms in this record itself."},"voidLookups":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"ip4":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"ip4 mechanisms in this record."},"ip6":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"ttl":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"error":{"type":"string","enum":["nxdomain","no-spf","temperror","loop","skipped"]}},"required":["domain","via","depth","found","lookups","voidLookups","ip4","ip6"],"additionalProperties":false},"description":"Every record visited, depth first."},"issues":{"type":"array","items":{"type":"object","properties":{"severity":{"type":"string","enum":["error","warning","info"]},"code":{"type":"string"},"message":{"type":"string"},"domain":{"type":"string"},"term":{"type":"string"}},"required":["severity","code","message"],"additionalProperties":false}},"notes":{"type":"array","items":{"type":"string"}},"dnsQueries":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"capped":{"type":"boolean","description":"A query, lookup or depth cap stopped the walk."},"incomplete":{"type":"boolean","description":"The deadline passed before every DNS query finished."},"ttl":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["domain","status","valid","records","terms","lookups","voidLookups","authorized","tree","issues","notes","dnsQueries","capped","incomplete"],"additionalProperties":false},"SpfCheckResult":{"allOf":[{"$ref":"#/components/schemas/ToolResultEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/SpfCheckOutput"}}}]},"SpfGenerateInput":{"type":"object","properties":{"domain":{"description":"Your domain, e.g. example.com. Optional: used for the zone-file line and publishing notes. URLs, e-mail addresses and Unicode names are reduced to the ASCII domain.","type":"string","maxLength":253},"providers":{"description":"Mail services that send as your domain; each adds its documented include. Known ids: amazon-ses, brevo, cloudflare-email-routing, constant-contact, fastmail, godaddy, google-workspace, mailchimp, mailgun, mandrill, microsoft-365, postmark, proton-mail, salesforce, sendgrid, sparkpost, zendesk, zoho-mail.","maxItems":20,"type":"array","items":{"type":"string","enum":["amazon-ses","brevo","cloudflare-email-routing","constant-contact","fastmail","godaddy","google-workspace","mailchimp","mailgun","mandrill","microsoft-365","postmark","proton-mail","salesforce","sendgrid","sparkpost","zendesk","zoho-mail"]}},"includes":{"description":"Extra domains to include (include:<domain>) for services not in the provider list.","maxItems":20,"type":"array","items":{"type":"string","maxLength":253}},"ip4":{"description":"Your own IPv4 addresses or networks, e.g. 192.0.2.10 or 203.0.113.0/24.","maxItems":50,"type":"array","items":{"type":"string","maxLength":64}},"ip6":{"description":"Your own IPv6 addresses or networks, e.g. 2001:db8::/32.","maxItems":50,"type":"array","items":{"type":"string","maxLength":64}},"includeMx":{"default":false,"description":"Authorize the servers in your MX records (mx).","type":"boolean"},"includeA":{"default":false,"description":"Authorize the A/AAAA address of your domain (a).","type":"boolean"},"redirect":{"description":"Delegate the whole policy to another domain (redirect=domain) instead of ending with an \"all\" qualifier.","type":"string","maxLength":253},"all":{"default":"~all","description":"What receivers should do with mail from other servers: ~all softfail (recommended while testing), -all fail (strictest), ?all neutral (no protection).","type":"string","enum":["~all","-all","?all"]}},"additionalProperties":false},"SpfGenerateOutput":{"type":"object","properties":{"domain":{"type":"string"},"host":{"type":"string","description":"TXT record name: \"@\" (the domain itself) when no domain was given, else the domain."},"record":{"type":"string","description":"The complete SPF record value."},"length":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Record length in bytes."},"chunks":{"type":"array","items":{"type":"string"},"description":"The record split into DNS character-strings of at most 255 bytes (one entry when it fits)."},"zoneLine":{"type":"string","description":"A ready-to-paste zone-file line."},"terms":{"type":"array","items":{"type":"string"}},"lookups":{"type":"object","properties":{"direct":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"DNS-lookup terms in this record (include, a, mx, ptr, exists, redirect)."},"knownNested":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Extra lookups the included services are known to add."},"total":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"limit":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"estimated":{"type":"boolean","description":"True when some included service's own lookups are unknown, so the real total may be higher."}},"required":["direct","knownNested","total","limit","estimated"],"additionalProperties":false},"providers":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"include":{"type":"string"}},"required":["id","name","include"],"additionalProperties":false}},"valid":{"type":"boolean"},"issues":{"type":"array","items":{"type":"object","properties":{"severity":{"type":"string","enum":["error","warning","info"]},"code":{"type":"string"},"message":{"type":"string"},"term":{"type":"string"}},"required":["severity","code","message"],"additionalProperties":false}},"notes":{"type":"array","items":{"type":"string"}}},"required":["host","record","length","chunks","zoneLine","terms","lookups","providers","valid","issues","notes"],"additionalProperties":false},"SpfGenerateResult":{"allOf":[{"$ref":"#/components/schemas/ToolResultEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/SpfGenerateOutput"}}}]},"SslCheckInput":{"type":"object","properties":{"host":{"type":"string","maxLength":2048,"description":"Domain name or public IP address to connect to, e.g. example.com. A URL or host:port is reduced to its host (and port). Private, loopback and internal addresses are refused."},"port":{"default":443,"description":"TCP port. Allowed: 443, 465, 587, 636, 853, 993, 995, 8443 (587 is SMTP with STARTTLS). A port written in the host overrides this.","type":"integer","minimum":1,"maximum":65535}},"required":["host"],"additionalProperties":false},"SslCheckOutput":{"type":"object","properties":{"host":{"type":"string"},"port":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"ip":{"type":"string","description":"Address that was connected to."},"verdict":{"type":"string","enum":["valid","expiring","expired","not-yet-valid","self-signed","untrusted","hostname-mismatch","outdated-tls"],"description":"valid = trusted, matches the host and not close to expiry; expiring = valid but 30 days or less remain; outdated-tls = the server refused TLS 1.2 and 1.3 and only speaks TLS 1.0 or 1.1, which browsers block (its certificate is read but its chain is not checked for trust)."},"valid":{"type":"boolean","description":"A browser would accept this certificate for this host right now."},"expiresAt":{"type":"string"},"daysToExpiry":{"description":"Whole days left; negative when expired.","type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"issuedAt":{"type":"string"},"lifetimeDays":{"description":"Total validity period of the leaf certificate.","type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"subject":{"description":"Common name (or organization) of the leaf certificate.","type":"string"},"issuer":{"description":"Common name (or organization) of the issuing CA.","type":"string"},"protocol":{"description":"Negotiated TLS version, e.g. TLSv1.3. TLSv1 or TLSv1.1 means the server refused TLS 1.2 and 1.3 (verdict outdated-tls).","type":"string"},"cipher":{"type":"string"},"alpn":{"type":"string"},"authorized":{"type":"boolean","description":"The certificate chain verified against the Mozilla root list that ships with LookupOwl's Node.js runtime, not an operating system store (Node's verdict, including dates and host name). Always false when the server only speaks TLS 1.0 or 1.1: its chain is read but not checked."},"authorizationError":{"description":"Why verification failed (an OpenSSL code such as CERT_HAS_EXPIRED). LEGACY_TLS_NOT_VERIFIED means the chain was read over TLS 1.0 or 1.1 and not checked.","type":"string"},"hostnameMatch":{"type":"boolean"},"ocspStapled":{"type":"boolean"},"chain":{"type":"array","items":{"type":"object","properties":{"subject":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}},"issuer":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}},"san":{"type":"array","items":{"type":"string"},"description":"DNS names the certificate is valid for."},"validFrom":{"type":"string"},"validTo":{"type":"string"},"serialNumber":{"type":"string"},"fingerprint256":{"type":"string"},"keyType":{"type":"string"},"keyBits":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"signatureAlgorithm":{"type":"string"},"isCA":{"type":"boolean"},"selfSigned":{"type":"boolean"},"trustAnchor":{"description":"A self-signed root that is in our trust store: it may have been added to the chain by us and not sent by the server.","type":"boolean"}},"required":["subject","issuer","san","validFrom","validTo","serialNumber","fingerprint256"],"additionalProperties":false},"description":"The certificate chain, leaf first. The server sent every entry except possibly a final root marked trustAnchor, which our trust store may have supplied."},"issues":{"type":"array","items":{"type":"object","properties":{"severity":{"type":"string","enum":["error","warning","info"]},"code":{"type":"string"},"message":{"type":"string"},"fix":{"type":"string"}},"required":["severity","code","message"],"additionalProperties":false}},"checkedAt":{"type":"string"},"ms":{"type":"number"}},"required":["host","port","ip","verdict","valid","authorized","hostnameMatch","chain","issues","checkedAt","ms"],"additionalProperties":false},"SslCheckResult":{"allOf":[{"$ref":"#/components/schemas/ToolResultEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/SslCheckOutput"}}}]},"SubnetCalculateInput":{"type":"object","properties":{"cidr":{"type":"string","maxLength":128,"description":"IPv4 or IPv6 network in any common notation: CIDR (10.0.0.0/22, 2001:db8::/48), address + netmask (10.0.0.1 255.255.252.0), address + wildcard (10.0.0.1 0.0.3.255), a start-end range that is exactly one block, or a single address."},"splitPrefix":{"description":"Also split the network into subnets of this prefix length (longer than the network prefix). Rows are returned 256 at a time.","type":"integer","minimum":0,"maximum":128},"cloud":{"default":"none","description":"Subtract the addresses a cloud provider reserves per subnet (IPv4 only): aws and azure keep 5, gcp keeps 4.","type":"string","enum":["none","aws","azure","gcp"]},"cursor":{"default":0,"description":"Offset into the split list for paging; pass the previous nextCursor.","type":"integer","minimum":0,"maximum":9007199254740991}},"required":["cidr"],"additionalProperties":false},"SubnetCalculateOutput":{"type":"object","properties":{"version":{"type":"number","enum":[4,6]},"cidr":{"type":"string","description":"Canonical network in CIDR form."},"network":{"type":"string"},"prefix":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"form":{"type":"string","enum":["cidr","mask","wildcard","range","host"],"description":"How the input was written."},"address":{"type":"string","description":"The address as typed (may have host bits set)."},"hostBitsSet":{"type":"boolean"},"netmask":{"type":"string"},"wildcard":{"description":"IPv4 only.","type":"string"},"broadcast":{"description":"IPv4 only, and absent for /31 and /32.","type":"string"},"firstAddress":{"type":"string"},"lastAddress":{"type":"string"},"firstUsable":{"type":"string"},"lastUsable":{"type":"string"},"totalAddresses":{"type":"string","description":"Exact count as a decimal string (can exceed 2^53)."},"hostBits":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Total addresses = 2^hostBits."},"usableAddresses":{"type":"string"},"usableRule":{"type":"string","enum":["standard","point-to-point","single-host","ipv6-subnet"]},"addressType":{"type":"object","properties":{"kind":{"type":"string","description":"Machine-readable type: global, private, shared, loopback, link-local, documentation, benchmark, multicast, reserved, unspecified, broadcast, unique-local, ipv4-mapped, nat64, teredo, 6to4, mixed…"},"name":{"type":"string","description":"Human label, e.g. \"Private-Use\"."},"rfc":{"type":"string"},"block":{"description":"The IANA special-purpose block that matched.","type":"string"},"isPublic":{"type":"boolean","description":"True for ordinary globally routable unicast space."}},"required":["kind","name","isPublic"],"additionalProperties":false},"containsSpecialBlocks":{"type":"array","items":{"type":"object","properties":{"cidr":{"type":"string"},"kind":{"type":"string"},"name":{"type":"string"},"rfc":{"type":"string"}},"required":["cidr","kind","name"],"additionalProperties":false}},"ipClass":{"description":"Historic IPv4 class; obsolete since CIDR (1993) and shown for reference only.","type":"string","enum":["A","B","C","D","E"]},"binary":{"type":"object","properties":{"network":{"type":"string"},"netmask":{"type":"string"}},"required":["network","netmask"],"additionalProperties":false},"hex":{"type":"object","properties":{"network":{"type":"string"},"netmask":{"type":"string"}},"required":["network","netmask"],"additionalProperties":false},"integer":{"type":"object","properties":{"network":{"type":"string"},"last":{"type":"string"}},"required":["network","last"],"additionalProperties":false},"reverseZone":{"description":"in-addr.arpa / ip6.arpa zone, or null when the prefix is not on an octet/nibble boundary.","type":["string","null"]},"embedded":{"description":"IPv4 networks only: the same block inside IPv6 transition prefixes.","type":"object","properties":{"ipv4Mapped":{"type":"string"},"sixToFour":{"type":"string"},"nat64":{"type":"string"}},"required":["ipv4Mapped","sixToFour","nat64"],"additionalProperties":false},"cloud":{"type":"object","properties":{"mode":{"type":"string","enum":["aws","azure","gcp"]},"reserved":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"usableAddresses":{"type":"string"},"firstUsable":{"type":"string"},"lastUsable":{"type":"string"},"note":{"type":"string"},"warnings":{"type":"array","items":{"type":"string"}}},"required":["mode","reserved","usableAddresses","note","warnings"],"additionalProperties":false},"split":{"type":"object","properties":{"prefix":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"count":{"type":"string","description":"Exact number of subnets, as a decimal string."},"offset":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"nextCursor":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"subnets":{"type":"array","items":{"type":"object","properties":{"cidr":{"type":"string"},"firstUsable":{"type":"string"},"lastUsable":{"type":"string"},"usableAddresses":{"type":"string"}},"required":["cidr","usableAddresses"],"additionalProperties":false}}},"required":["prefix","count","offset","nextCursor","subnets"],"additionalProperties":false},"notes":{"type":"array","items":{"type":"string"}},"warnings":{"type":"array","items":{"type":"string"}}},"required":["version","cidr","network","prefix","form","address","hostBitsSet","netmask","firstAddress","lastAddress","totalAddresses","hostBits","usableAddresses","usableRule","addressType","binary","hex","integer","reverseZone","notes","warnings"],"additionalProperties":false},"SubnetCalculateResult":{"allOf":[{"$ref":"#/components/schemas/ToolResultEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/SubnetCalculateOutput"}}}]},"WebsiteHostingInput":{"type":"object","properties":{"target":{"type":"string","maxLength":2048,"description":"A domain name or a website address, e.g. example.com or https://www.example.com/page. Only the host is used. IP addresses are not accepted here (use ip_location for those)."},"probe":{"default":true,"description":"Allow one request to the site (HEAD, over https) to read response headers that give away CDNs and platforms. It is only made when the DNS and network data have not already identified the host. Switch off to use DNS and network data alone.","type":"boolean"},"includeAbuse":{"default":true,"description":"Also look up the abuse contact of the network that serves the site (one registry lookup).","type":"boolean"}},"required":["target"],"additionalProperties":false},"WebsiteHostingOutput":{"type":"object","properties":{"host":{"type":"string","description":"The host that was checked (lower-case, A-label)."},"domain":{"type":"string","description":"The registrable domain whose nameservers and mail records were read."},"dns":{"type":"object","properties":{"status":{"type":"string","enum":["ok","nxdomain","nodata"],"description":"\"nxdomain\": the name does not exist. \"nodata\": it exists but has no A or AAAA record."},"cnames":{"type":"array","items":{"type":"string"},"description":"CNAME chain from the host, in order."},"minTtl":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["status","cnames"],"additionalProperties":false},"verdict":{"type":"object","properties":{"kind":{"type":"string","enum":["cdn","platform","host","cloud","unknown","none"],"description":"cdn: served through a CDN or proxy. platform: runs on a hosting platform or site builder. host or cloud: on a hosting company or cloud network. unknown: the network is not one we recognise (its owner is still given). none: the name has no website address."},"summary":{"type":"string","description":"One plain sentence."},"provider":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"kind":{"type":"string","enum":["cdn","platform","cloud","host","dns","mail"],"description":"cdn: CDN or reverse proxy (hides the origin). platform: the whole site runs there. cloud: rents servers. host: a web hosting company. dns: DNS hosting. mail: email provider."}},"required":["id","name","kind"],"additionalProperties":false},"originHidden":{"type":"boolean","description":"A CDN or proxy answers for the site, so the server that stores it cannot be seen from outside."},"confidence":{"type":"string","enum":["high","medium","low"]},"others":{"type":"array","items":{"type":"string"},"description":"Other providers seen on the web side (a CDN in front of a platform, or a second CDN)."}},"required":["kind","summary","originHidden","confidence","others"],"additionalProperties":false},"web":{"type":"array","items":{"type":"object","properties":{"ip":{"type":"string"},"version":{"anyOf":[{"type":"number","const":4},{"type":"number","const":6}]},"special":{"description":"Set when the address is private or reserved (so it cannot be a public host).","type":"string"},"asn":{"type":"object","properties":{"number":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"organization":{"type":"string"},"range":{"type":"string"}},"required":["number","organization","range"],"additionalProperties":false},"country":{"description":"Where DB-IP locates the address. Approximate; a CDN address says little about where the site really runs.","type":"object","properties":{"code":{"type":"string"},"name":{"type":"string"}},"required":["code","name"],"additionalProperties":false},"provider":{"description":"The provider this address belongs to, when it is one we know.","type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"kind":{"type":"string","enum":["cdn","platform","cloud","host","dns","mail"],"description":"cdn: CDN or reverse proxy (hides the origin). platform: the whole site runs there. cloud: rents servers. host: a web hosting company. dns: DNS hosting. mail: email provider."}},"required":["id","name","kind"],"additionalProperties":false},"evidence":{"type":"array","items":{"type":"string"}}},"required":["ip","version","evidence"],"additionalProperties":false}},"providers":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"kind":{"type":"string","enum":["cdn","platform","cloud","host","dns","mail"],"description":"cdn: CDN or reverse proxy (hides the origin). platform: the whole site runs there. cloud: rents servers. host: a web hosting company. dns: DNS hosting. mail: email provider."},"evidence":{"type":"array","items":{"type":"string"},"description":"What pointed at this provider: a CNAME, an IP range, an AS number or a response header."}},"required":["id","name","kind","evidence"],"additionalProperties":false},"description":"Every web-side provider found, with the evidence for each."},"headers":{"type":"object","properties":{"status":{"type":"string","enum":["used","skipped","not_needed","failed","off"],"description":"\"used\": one HEAD request was made. \"not_needed\": DNS and network data already identified the host. \"skipped\": no request was made (budget, no address). \"failed\": the site did not answer. \"off\": switched off."},"url":{"type":"string"},"httpStatus":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"server":{"description":"The Server header, when the site sends one.","type":"string"},"note":{"type":"string"}},"required":["status"],"additionalProperties":false},"dnsHosting":{"type":"object","properties":{"status":{"type":"string","enum":["found","none","unavailable"]},"nameservers":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"provider":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"kind":{"type":"string","enum":["cdn","platform","cloud","host","dns","mail"],"description":"cdn: CDN or reverse proxy (hides the origin). platform: the whole site runs there. cloud: rents servers. host: a web hosting company. dns: DNS hosting. mail: email provider."}},"required":["id","name","kind"],"additionalProperties":false},"pattern":{"type":"string"}},"required":["name"],"additionalProperties":false}},"providers":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"kind":{"type":"string","enum":["cdn","platform","cloud","host","dns","mail"],"description":"cdn: CDN or reverse proxy (hides the origin). platform: the whole site runs there. cloud: rents servers. host: a web hosting company. dns: DNS hosting. mail: email provider."}},"required":["id","name","kind"],"additionalProperties":false}},"summary":{"type":"string"}},"required":["status","nameservers","providers","summary"],"additionalProperties":false},"email":{"type":"object","properties":{"status":{"type":"string","enum":["found","none","null_mx","unavailable"]},"mx":{"type":"array","items":{"type":"object","properties":{"preference":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"exchange":{"type":"string"},"provider":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"kind":{"type":"string","enum":["cdn","platform","cloud","host","dns","mail"],"description":"cdn: CDN or reverse proxy (hides the origin). platform: the whole site runs there. cloud: rents servers. host: a web hosting company. dns: DNS hosting. mail: email provider."}},"required":["id","name","kind"],"additionalProperties":false},"pattern":{"type":"string"}},"required":["preference","exchange"],"additionalProperties":false}},"providers":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"kind":{"type":"string","enum":["cdn","platform","cloud","host","dns","mail"],"description":"cdn: CDN or reverse proxy (hides the origin). platform: the whole site runs there. cloud: rents servers. host: a web hosting company. dns: DNS hosting. mail: email provider."}},"required":["id","name","kind"],"additionalProperties":false}},"summary":{"type":"string"}},"required":["status","mx","providers","summary"],"additionalProperties":false},"abuse":{"description":"Who to report abuse to for the network that serves the site: the registry's abuse mailbox, plus the provider's report page when known.","type":"object","properties":{"ip":{"type":"string"},"network":{"type":"string"},"email":{"type":"string"},"reportUrl":{"description":"The provider's own abuse report page, when it publishes one.","type":"string"},"provider":{"type":"string"}},"required":["ip"],"additionalProperties":false},"notes":{"type":"array","items":{"type":"string"}},"data":{"type":"object","properties":{"city":{"description":"The DB-IP Lite city database in use: monthly release and build time.","type":"object","properties":{"release":{"type":"string"},"builtAt":{"type":"string"}},"required":["release","builtAt"],"additionalProperties":false},"asn":{"description":"The DB-IP Lite ASN database in use.","type":"object","properties":{"release":{"type":"string"},"builtAt":{"type":"string"}},"required":["release","builtAt"],"additionalProperties":false}},"additionalProperties":false},"attribution":{"type":"object","properties":{"text":{"type":"string","description":"The credit the data licence requires: show it, linked to url, wherever these results are shown."},"url":{"type":"string"},"license":{"type":"string"},"licenseUrl":{"type":"string"}},"required":["text","url","license","licenseUrl"],"additionalProperties":false,"description":"Network owners and countries come from DB-IP Lite; show this credit wherever you show them."}},"required":["host","domain","dns","verdict","web","providers","headers","dnsHosting","email","notes","data","attribution"],"additionalProperties":false},"WebsiteHostingResult":{"allOf":[{"$ref":"#/components/schemas/ToolResultEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/WebsiteHostingOutput"}}}]},"WhatIsMyIpInput":{"type":"object","properties":{"details":{"default":true,"description":"Also look up the reverse DNS name and the registered network (name, range, country) of the address. Each lookup is given about two seconds and is simply left out when it does not answer.","type":"boolean"}},"additionalProperties":false},"WhatIsMyIpOutput":{"type":"object","properties":{"ip":{"type":"string","description":"The caller's IP address as this server sees it."},"version":{"anyOf":[{"type":"number","const":4},{"type":"number","const":6}]},"ipv4Mapped":{"description":"The address arrived as an IPv4-mapped IPv6 address (::ffff:a.b.c.d) and was converted to IPv4.","type":"boolean"},"isPublic":{"type":"boolean","description":"false for private, loopback, link-local and other non-routable addresses: the server is not seeing your public address (a proxy or local network is in between)."},"special":{"type":"object","properties":{"kind":{"type":"string"},"name":{"type":"string"},"rfc":{"type":"string"}},"required":["kind","name"],"additionalProperties":false},"reverseDns":{"type":"object","properties":{"status":{"type":"string","enum":["found","none","failed","timeout"]},"hostnames":{"type":"array","items":{"type":"string"}}},"required":["status","hostnames"],"additionalProperties":false},"network":{"type":"object","properties":{"status":{"type":"string","enum":["found","none","unavailable"]},"name":{"type":"string"},"handle":{"type":"string"},"cidr":{"type":"string"},"range":{"description":"First and last address of the registered block.","type":"string"},"country":{"type":"string"},"rir":{"description":"Regional Internet Registry, e.g. ARIN or RIPE NCC.","type":"string"},"type":{"type":"string"}},"required":["status"],"additionalProperties":false},"notes":{"type":"array","items":{"type":"string"}}},"required":["ip","version","isPublic","notes"],"additionalProperties":false},"WhatIsMyIpResult":{"allOf":[{"$ref":"#/components/schemas/ToolResultEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/WhatIsMyIpOutput"}}}]},"WhoisLookupInput":{"type":"object","properties":{"q":{"type":"string","minLength":1,"maxLength":512,"description":"Domain name to look up, e.g. example.com. A URL or e-mail address is reduced to its registrable domain; Unicode names are converted to Punycode."},"followRegistrar":{"default":true,"description":"Also ask the registrar's own RDAP server when the registry points to it. Adds registrar-side contacts and expiry date; costs one more upstream request.","type":"boolean"},"includeRaw":{"default":false,"description":"Include the raw RDAP JSON from the registry (and registrar) in the result. Large; off by default.","type":"boolean"}},"required":["q"],"additionalProperties":false},"WhoisLookupOutput":{"type":"object","properties":{"query":{"type":"object","properties":{"kind":{"type":"string","enum":["domain","ip","autnum","nameserver","entity","tld"]},"key":{"type":"string"},"display":{"type":"string"},"input":{"type":"string"},"notices":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"],"additionalProperties":{}},"description":"What was changed to make the input usable (URL reduced to a host, IDN converted, ...)."}},"required":["kind","key","display","input","notices"],"additionalProperties":{}},"status":{"type":"string","enum":["found","not_found","special_purpose","no_rdap_service"],"description":"found: a record exists. not_found: the registry says there is none. special_purpose: reserved address space or AS number, nothing to look up. no_rdap_service: no RDAP (and for domains no WHOIS) service exists."},"source":{"type":"string","enum":["rdap","whois","none"],"description":"Where the record came from."},"availability":{"description":"Domains only. \"likely-available\" is a registry saying there is no record; premium or reserved names can still be unavailable.","type":"object","properties":{"verdict":{"type":"string","enum":["likely-available","registered","likely-available-whois","unknown"]},"caveats":{"type":"array","items":{"type":"string"}},"registerLinks":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"url":{"type":"string"},"affiliate":{"type":"boolean"}},"required":["name","url","affiliate"],"additionalProperties":{}}}},"required":["verdict","caveats","registerLinks"],"additionalProperties":{}},"registrar":{"description":"Outcome of asking the registrar after the registry. The merged data is in domain.","type":"object","properties":{"status":{"type":"string"},"url":{"type":"string"}},"required":["status"],"additionalProperties":{}},"whois":{"description":"Raw WHOIS reply, only when the TLD has no RDAP service.","type":"object","properties":{"server":{"type":"string"},"text":{"type":"string"},"notFound":{"type":"boolean"},"rateLimited":{"type":"boolean"},"referralChain":{"type":"array","items":{"type":"string"}}},"required":["server","text","notFound","rateLimited","referralChain"],"additionalProperties":{}},"error":{"type":"object","properties":{"code":{"type":"string"},"httpStatus":{"type":"number"},"title":{"type":"string"},"description":{"type":"array","items":{"type":"string"}},"retryAfter":{"type":"number"}},"required":["code"],"additionalProperties":{}},"provenance":{"type":"object","properties":{"bootstrap":{"type":"object","properties":{"kind":{"type":"string"},"entry":{"type":"string"},"source":{"type":"string"}},"required":["kind","entry","source"],"additionalProperties":{}},"serverUrl":{"type":"string"},"queryUrl":{"type":"string"},"finalUrl":{"type":"string"},"registrarUrl":{"type":"string"},"whoisServer":{"type":"string"},"trace":{"type":"array","items":{"type":"object","properties":{"step":{"type":"string"},"label":{"type":"string"},"ms":{"type":"number"},"url":{"type":"string"},"host":{"type":"string"},"status":{"type":["number","string"]},"note":{"type":"string"}},"required":["step","label","ms"],"additionalProperties":{}}},"totalMs":{"type":"number"},"fetchedAt":{"type":"string"},"cache":{"type":"string","enum":["hit","miss","stale","coalesced","bypass","hit-or-miss"]},"stale":{"description":"True when this is a stored copy served because the registry is not answering.","type":"boolean"}},"required":["trace","totalMs","fetchedAt","cache"],"additionalProperties":{},"description":"How the answer was obtained: which bootstrap entry, which servers, timings."},"raw":{"description":"Raw upstream RDAP JSON. Only with includeRaw.","type":"object","properties":{"registry":{},"registrar":{}},"additionalProperties":{}},"domain":{"type":"object","properties":{"objectClassName":{"type":"string","const":"domain"},"ldhName":{"type":"string"},"unicodeName":{"type":"string"},"handle":{"type":"string"},"statuses":{"type":"array","items":{"type":"object","properties":{"raw":{"type":"string"},"rdap":{"type":"string"},"epp":{"type":"string"},"label":{"type":"string"},"description":{"type":"string"},"category":{"type":"string"},"severity":{"type":"string"},"slug":{"type":"string"}},"required":["raw","rdap","label","description","category","severity"],"additionalProperties":{}}},"events":{"type":"object","properties":{"registration":{"type":"object","properties":{"action":{"type":"string"},"raw":{"type":"string"},"date":{"description":"ISO-8601 UTC.","type":"string"}},"required":["action","raw"],"additionalProperties":{}},"expiration":{"type":"object","properties":{"action":{"type":"string"},"raw":{"type":"string"},"date":{"description":"ISO-8601 UTC.","type":"string"}},"required":["action","raw"],"additionalProperties":{}},"lastChanged":{"type":"object","properties":{"action":{"type":"string"},"raw":{"type":"string"},"date":{"description":"ISO-8601 UTC.","type":"string"}},"required":["action","raw"],"additionalProperties":{}},"registrarExpiration":{"type":"object","properties":{"action":{"type":"string"},"raw":{"type":"string"},"date":{"description":"ISO-8601 UTC.","type":"string"}},"required":["action","raw"],"additionalProperties":{}},"all":{"type":"array","items":{},"description":"Every event as the registry sent it: { action, raw, date?, actor? }."}},"required":["all"],"additionalProperties":{}},"nameservers":{"type":"array","items":{"type":"object","properties":{"ldhName":{"type":"string"},"ipv4":{"type":"array","items":{"type":"string"}},"ipv6":{"type":"array","items":{"type":"string"}}},"required":["ldhName","ipv4","ipv6"],"additionalProperties":{}}},"dnssec":{"type":"object","properties":{"signed":{"type":["boolean","null"]}},"required":["signed"],"additionalProperties":{}},"registrar":{"type":"object","properties":{"name":{"type":"string"},"ianaId":{"type":"string"},"url":{"type":"string"},"abuse":{"type":"object","properties":{"email":{"type":"string"},"phone":{"type":"string"}},"additionalProperties":{}}},"additionalProperties":{}},"contacts":{"type":"array","items":{"type":"object","properties":{"roles":{"type":"array","items":{"type":"string"}},"name":{"type":"string"},"org":{"type":"string"},"emails":{"type":"array","items":{"type":"string"}},"isRedacted":{"type":"boolean"}},"required":["roles","emails","isRedacted"],"additionalProperties":{}}},"lifecycle":{"type":"object","properties":{"stage":{"type":"string"},"badges":{"type":"array","items":{"type":"string"}},"severity":{"type":"string"},"label":{"type":"string"},"summary":{"type":"string"},"ageDays":{"type":"number"},"expiresInDays":{"type":"number"},"earliestExpiry":{"type":"string"},"isLocked":{"type":"boolean"},"isOnHold":{"type":"boolean"},"isNew":{"type":"boolean"}},"required":["stage","badges","severity","label","summary","isLocked","isOnHold","isNew"],"additionalProperties":{}},"discrepancies":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string"},"registry":{"type":"string"},"registrar":{"type":"string"}},"required":["field","registry","registrar"],"additionalProperties":{}}},"port43":{"type":"string"}},"required":["objectClassName","ldhName","unicodeName","statuses","events","nameservers","dnssec","contacts","lifecycle","discrepancies"],"additionalProperties":{}}},"required":["query","status","source","provenance"],"additionalProperties":{}},"WhoisLookupResult":{"allOf":[{"$ref":"#/components/schemas/ToolResultEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/WhoisLookupOutput"}}}]}},"responses":{"BadRequest":{"description":"The input was not valid.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"NotFound":{"description":"Unknown tool or endpoint.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"Unprocessable":{"description":"The input is valid but not supported.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"RateLimited":{"description":"Rate limit reached. Retry after the time in `Retry-After`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"UpstreamError":{"description":"An upstream registry or server failed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"Unavailable":{"description":"The service is busy or the result could not be produced right now.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"Timeout":{"description":"The lookup did not finish in time.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}}