{"openapi":"3.1.0","jsonSchemaDialect":"https://json-schema.org/draft/2020-12/schema","info":{"title":"IPFrog Public API","version":"1.0.0","summary":"Stateless, privacy-first network information and diagnostics.","description":"The canonical contract for IPFrog v1. All JSON properties use snake_case and all\ntimestamps use RFC 3339 UTC. `data` contains the operation result; request-specific\nand volatile fields live in `meta` so declarative clients can ignore them.\n\nIPFrog does not provide accounts, API keys, stored monitors, scheduled monitoring,\nor server-side speed tests. Monitoring is client-driven polling. Speed tests execute\non the client and results are not persisted by IPFrog.\n","contact":{"name":"IPFrog","url":"https://ipfrog.com"},"license":{"name":"Proprietary"}},"servers":[{"url":"https://api.ipfrog.com","description":"Production API"},{"url":"http://127.0.0.1:8787","description":"Local Nuxt development server"}],"security":[],"x-ipfrog-http-conventions":{"cors":"Public endpoints allow any origin without credentials. OPTIONS returns 204 with allowed methods and headers.","methods":"Known paths reject unsupported methods with RFC 9457 status 405 and an Allow header.","errors":"All application errors use application/problem+json and stable machine-readable codes."},"tags":[{"name":"IP"},{"name":"DNS"},{"name":"Latency"},{"name":"Speed tests"},{"name":"Analytics"},{"name":"Operations"}],"paths":{"/v1/ip":{"get":{"tags":["IP"],"operationId":"discoverCallerIp","summary":"Discover the caller's public connection","description":"Returns connection-observed data. Cloudflare headers and request metadata are trusted\nonly in a verified Cloudflare runtime. This response is request-specific and is never cached.\n","x-ipfrog-stability":"connection_observed","responses":{"200":{"description":"Caller connection information.","headers":{"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"X-Request-ID":{"$ref":"#/components/headers/RequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallerIpResponse"},"examples":{"caller":{"value":{"data":{"address":"203.0.113.7","ip_version":"ipv4","reverse_hostname":"host.example.net","network":{"asn":64500,"organization":"Example Network"},"location":{"city":"Chicago","region":"Illinois","country":"United States","country_code":"US","postal_code":null,"timezone":"America/Chicago","latitude":41.8781,"longitude":-87.6298},"connection":{"cloudflare_colo":"ORD","http_protocol":"HTTP/2","tls_version":"TLSv1.3"},"data_provenance":"observed_connection"},"meta":{"api_version":"v1","request_id":"550e8400-e29b-41d4-a716-446655440000","requested_at":"2026-07-16T12:00:00.000Z"}}}}}}},"405":{"$ref":"#/components/responses/MethodNotAllowed"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}}},"/v1/dns/resolve":{"get":{"tags":["DNS"],"operationId":"resolveDnsRecords","summary":"Resolve an allowlisted DNS record type","description":"Resolves only A, AAAA, CNAME, MX, NS, TXT, and PTR records using IPFrog's fixed resolver.\nPTR accepts a normal IP address and converts it to a reverse name server-side. Answer count,\nTXT size, total response size, and upstream duration are bounded. This is not a DNS proxy.\n","parameters":[{"$ref":"#/components/parameters/DnsName"},{"$ref":"#/components/parameters/DnsType"}],"responses":{"200":{"description":"Typed DNS answers. Empty answers are valid for negative responses.","headers":{"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"X-Request-ID":{"$ref":"#/components/headers/RequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DnsResponse"},"examples":{"a_record":{"value":{"data":{"query":{"name":"example.com","type":"A"},"response_code":"no_error","answers":[{"name":"example.com","type":"A","ttl_seconds":300,"address":"93.184.216.34"}]},"meta":{"api_version":"v1","request_id":"550e8400-e29b-41d4-a716-446655440000","requested_at":"2026-07-16T12:00:00.000Z"}}}}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"405":{"$ref":"#/components/responses/MethodNotAllowed"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/BadGateway"},"503":{"$ref":"#/components/responses/ServiceUnavailable"},"504":{"$ref":"#/components/responses/GatewayTimeout"}}}},"/v1/latency/regions":{"get":{"tags":["Latency"],"operationId":"listLatencyRegions","summary":"List stable regional probe identifiers","description":"Availability is deployment-dependent. The identifiers and names are stable API data.","responses":{"200":{"description":"Regional probe catalog.","headers":{"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"X-Request-ID":{"$ref":"#/components/headers/RequestId"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegionsResponse"}}}},"405":{"$ref":"#/components/responses/MethodNotAllowed"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v1/latency/regions/{region}/probe":{"get":{"tags":["Latency"],"operationId":"probeLatencyRegion","summary":"Measure Cloudflare edge-to-regional-probe RTT","description":"Reports a volatile Cloudflare edge-to-regional Durable Object round trip. It is not the\nuser's network latency. Clients measure client-to-API and total elapsed time themselves.\nProbe measurements are never cached.\n","x-ipfrog-stability":"volatile_measurement","parameters":[{"$ref":"#/components/parameters/Region"}],"responses":{"200":{"description":"Edge-to-region measurement with explicit null client-side metrics.","headers":{"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"X-Request-ID":{"$ref":"#/components/headers/RequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LatencyProbeResponse"}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"405":{"$ref":"#/components/responses/MethodNotAllowed"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}}},"/v1/speed-test/configuration":{"get":{"tags":["Speed tests"],"operationId":"getSpeedTestConfiguration","summary":"Get client-side speed-test configuration","description":"Returns measurement modes, metric units, limits, and analytics schema for official clients.\nIPFrog never executes this test in the Worker and never persists results.\n","responses":{"200":{"description":"Versioned client-side measurement configuration.","headers":{"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"X-Request-ID":{"$ref":"#/components/headers/RequestId"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SpeedTestConfigurationResponse"}}}},"405":{"$ref":"#/components/responses/MethodNotAllowed"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/v1/events":{"post":{"tags":["Analytics"],"operationId":"createAnalyticsEvent","summary":"Submit a privacy-safe speed-test analytics event","description":"Accepts only documented events and properties. Unknown properties are discarded. Public IP,\ncoordinates, User-Agent, hostname, DNS contents, and persistent identifiers\nare prohibited. Analytics delivery failure does not change this operation's accepted response.\n","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnalyticsEventRequest"},"examples":{"completed":{"value":{"event":"speed_test_completed","event_id":"550e8400-e29b-41d4-a716-446655440000","properties":{"source":"cli","mode":"full","duration_ms":14000,"download_mbps":242.5,"upload_mbps":31.2,"latency_ms":22.4,"jitter_ms":3.1}}}}}}},"responses":{"202":{"description":"Event accepted; delivery is best-effort and non-blocking.","headers":{"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"X-Request-ID":{"$ref":"#/components/headers/RequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnalyticsAcceptedResponse"}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"405":{"$ref":"#/components/responses/MethodNotAllowed"},"413":{"$ref":"#/components/responses/ContentTooLarge"},"415":{"$ref":"#/components/responses/UnsupportedMediaType"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/health":{"get":{"tags":["Operations"],"operationId":"getApiHealth","summary":"Get sanitized API health","description":"Reports API process health and version. DNS upstreams are deliberately not called;\nupstream health is reported as `not_checked` so health traffic cannot consume provider quotas.\n","responses":{"200":{"description":"Sanitized service health.","headers":{"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"X-Request-ID":{"$ref":"#/components/headers/RequestId"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthResponse"}}}},"405":{"$ref":"#/components/responses/MethodNotAllowed"},"500":{"$ref":"#/components/responses/InternalError"}}}}},"components":{"parameters":{"DnsName":{"name":"name","in":"query","required":true,"description":"DNS name, or a normal IPv4/IPv6 address for PTR.","schema":{"type":"string","minLength":1,"maxLength":253},"example":"example.com"},"DnsType":{"name":"type","in":"query","required":true,"schema":{"type":"string","enum":["A","AAAA","CNAME","MX","NS","TXT","PTR"]},"example":"A"},"Region":{"name":"region","in":"path","required":true,"schema":{"type":"string","enum":["wnam","enam","weur","eeur","apac-ne","apac-se","oc"]},"example":"wnam"}},"headers":{"CacheControl":{"description":"Explicit cache policy for the operation and result sensitivity.","schema":{"type":"string"}},"RequestId":{"description":"Request correlation identifier; volatile and not part of stable result data.","schema":{"type":"string","format":"uuid"}},"RateLimitLimit":{"description":"Configured request limit for this operation's window.","schema":{"type":"integer","minimum":1}},"RateLimitRemaining":{"description":"Remaining requests when the active limiter can report it; omitted otherwise.","schema":{"type":"integer","minimum":0}},"RateLimitReset":{"description":"Seconds until the current distributed rate-limit window resets.","schema":{"type":"integer","minimum":1}},"RetryAfter":{"description":"Seconds to wait before retrying a rate-limited request.","schema":{"type":"integer","minimum":1}}},"responses":{"InvalidRequest":{"description":"Invalid or unsupported input.","headers":{"X-Request-ID":{"$ref":"#/components/headers/RequestId"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"ContentTooLarge":{"description":"Request content exceeded the documented bound.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"UnsupportedMediaType":{"description":"Request body is not JSON.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"RateLimited":{"description":"Per-source operation limit exceeded.","headers":{"X-Request-ID":{"$ref":"#/components/headers/RequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://api.ipfrog.com/problems/rate_limit_exceeded","title":"Too many requests","status":429,"detail":"The operation rate limit has been exceeded.","code":"rate_limit_exceeded","request_id":"550e8400-e29b-41d4-a716-446655440000"}}}},"MethodNotAllowed":{"description":"The path exists but the HTTP method is unsupported. The Allow header lists supported methods.","headers":{"Allow":{"description":"Supported methods for the path, including OPTIONS and HEAD where applicable.","schema":{"type":"string"}},"X-Request-ID":{"$ref":"#/components/headers/RequestId"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"BadGateway":{"description":"A bounded upstream response was invalid or too large.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"GatewayTimeout":{"description":"A required upstream did not respond before its deadline.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"InternalError":{"description":"Generic internal failure; no stack trace or infrastructure details are exposed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"ServiceUnavailable":{"description":"Bounded upstream operation or regional probe is temporarily unavailable.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}},"schemas":{"ResponseMetadata":{"type":"object","additionalProperties":false,"required":["api_version","request_id","requested_at"],"properties":{"api_version":{"type":"string","const":"v1","description":"Stable API major version."},"request_id":{"type":"string","format":"uuid","description":"Request-specific and volatile."},"requested_at":{"type":"string","format":"date-time","description":"Request-specific RFC 3339 UTC timestamp."}}},"NetworkInformation":{"type":"object","additionalProperties":false,"required":["asn","organization"],"properties":{"asn":{"type":["integer","null"],"minimum":0,"maximum":4294967295,"description":"Provider-dependent or connection-observed autonomous system number."},"organization":{"type":["string","null"],"maxLength":160,"description":"Provider-dependent network organization name."}}},"LocationInformation":{"type":"object","additionalProperties":false,"required":["city","region","country","country_code","postal_code","timezone","latitude","longitude"],"description":"Approximate and provider-dependent. Null means unavailable; it never means \"unknown\" text.","properties":{"city":{"type":["string","null"],"maxLength":100},"region":{"type":["string","null"],"maxLength":100},"country":{"type":["string","null"],"maxLength":100},"country_code":{"type":["string","null"],"pattern":"^[A-Z]{2}$"},"postal_code":{"type":["string","null"],"maxLength":32},"timezone":{"type":["string","null"],"maxLength":64},"latitude":{"type":["number","null"],"minimum":-90,"maximum":90},"longitude":{"type":["number","null"],"minimum":-180,"maximum":180}}},"ConnectionInformation":{"type":"object","additionalProperties":false,"required":["cloudflare_colo","http_protocol","tls_version"],"description":"Observed from the current caller connection.","properties":{"cloudflare_colo":{"type":["string","null"],"pattern":"^[A-Z]{3}$"},"http_protocol":{"type":["string","null"],"maxLength":24},"tls_version":{"type":["string","null"],"maxLength":24}}},"CallerIpData":{"type":"object","additionalProperties":false,"required":["address","ip_version","reverse_hostname","network","location","connection","data_provenance"],"properties":{"address":{"type":"string","minLength":2,"maxLength":45},"ip_version":{"type":"string","enum":["ipv4","ipv6"]},"reverse_hostname":{"type":["string","null"],"maxLength":253},"network":{"$ref":"#/components/schemas/NetworkInformation"},"location":{"$ref":"#/components/schemas/LocationInformation"},"connection":{"$ref":"#/components/schemas/ConnectionInformation"},"data_provenance":{"type":"string","const":"observed_connection"}}},"CallerIpResponse":{"type":"object","additionalProperties":false,"required":["data","meta"],"properties":{"data":{"$ref":"#/components/schemas/CallerIpData"},"meta":{"$ref":"#/components/schemas/ResponseMetadata"}}},"DnsQuery":{"type":"object","additionalProperties":false,"required":["name","type"],"properties":{"name":{"type":"string","maxLength":253,"description":"Canonical DNS query name; PTR contains the derived reverse name."},"type":{"type":"string","enum":["A","AAAA","CNAME","MX","NS","TXT","PTR"]}}},"DnsAddressAnswer":{"type":"object","additionalProperties":false,"required":["name","type","ttl_seconds","address"],"properties":{"name":{"type":"string","maxLength":253},"type":{"type":"string","enum":["A","AAAA"]},"ttl_seconds":{"type":"integer","minimum":0,"maximum":86400},"address":{"type":"string","maxLength":45}}},"DnsTargetAnswer":{"type":"object","additionalProperties":false,"required":["name","type","ttl_seconds","target"],"properties":{"name":{"type":"string","maxLength":253},"type":{"type":"string","enum":["CNAME","NS","PTR"]},"ttl_seconds":{"type":"integer","minimum":0,"maximum":86400},"target":{"type":"string","maxLength":253}}},"DnsMxAnswer":{"type":"object","additionalProperties":false,"required":["name","type","ttl_seconds","preference","exchange"],"properties":{"name":{"type":"string","maxLength":253},"type":{"type":"string","const":"MX"},"ttl_seconds":{"type":"integer","minimum":0,"maximum":86400},"preference":{"type":"integer","minimum":0,"maximum":65535},"exchange":{"type":"string","maxLength":253}}},"DnsTxtAnswer":{"type":"object","additionalProperties":false,"required":["name","type","ttl_seconds","value"],"properties":{"name":{"type":"string","maxLength":253},"type":{"type":"string","const":"TXT"},"ttl_seconds":{"type":"integer","minimum":0,"maximum":86400},"value":{"type":"string","maxLength":2048}}},"DnsAnswer":{"oneOf":[{"$ref":"#/components/schemas/DnsAddressAnswer"},{"$ref":"#/components/schemas/DnsTargetAnswer"},{"$ref":"#/components/schemas/DnsMxAnswer"},{"$ref":"#/components/schemas/DnsTxtAnswer"}]},"DnsData":{"type":"object","additionalProperties":false,"required":["query","response_code","answers"],"properties":{"query":{"$ref":"#/components/schemas/DnsQuery"},"response_code":{"type":"string","enum":["no_error","name_error","refused","server_failure","other"]},"answers":{"type":"array","maxItems":50,"items":{"$ref":"#/components/schemas/DnsAnswer"}}}},"DnsResponse":{"type":"object","additionalProperties":false,"required":["data","meta"],"properties":{"data":{"$ref":"#/components/schemas/DnsData"},"meta":{"$ref":"#/components/schemas/ResponseMetadata"}}},"Region":{"type":"object","additionalProperties":false,"required":["id","name","available"],"properties":{"id":{"type":"string","enum":["wnam","enam","weur","eeur","apac-ne","apac-se","oc"]},"name":{"type":"string","maxLength":100},"available":{"type":"boolean"}}},"RegionsResponse":{"type":"object","additionalProperties":false,"required":["data","meta"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["regions"],"properties":{"regions":{"type":"array","items":{"$ref":"#/components/schemas/Region"}}}},"meta":{"$ref":"#/components/schemas/ResponseMetadata"}}},"LatencyProbeResponse":{"type":"object","additionalProperties":false,"required":["data","meta"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["region","edge_to_region_rtt_ms","client_to_api_rtt_ms","client_observed_total_rtt_ms","measurement_scope"],"properties":{"region":{"type":"string","enum":["wnam","enam","weur","eeur","apac-ne","apac-se","oc"]},"edge_to_region_rtt_ms":{"type":"number","minimum":0,"description":"Volatile server-observed RTT in milliseconds."},"client_to_api_rtt_ms":{"type":"null","description":"Always null; the client must measure this value."},"client_observed_total_rtt_ms":{"type":"null","description":"Always null; the client must measure total elapsed time."},"measurement_scope":{"type":"string","const":"cloudflare_edge_to_regional_probe"}}},"meta":{"$ref":"#/components/schemas/ResponseMetadata"}}},"SpeedTestMeasurement":{"type":"object","additionalProperties":false,"required":["type"],"properties":{"type":{"type":"string","enum":["latency","download","upload"]},"packet_count":{"type":"integer","minimum":1},"bytes_per_request":{"type":"integer","minimum":1},"request_count":{"type":"integer","minimum":1}}},"SpeedTestMode":{"type":"object","additionalProperties":false,"required":["id","description","measurements"],"properties":{"id":{"type":"string","enum":["light","full"]},"description":{"type":"string"},"measurements":{"type":"array","minItems":1,"items":{"$ref":"#/components/schemas/SpeedTestMeasurement"}}}},"SpeedTestConfigurationResponse":{"type":"object","additionalProperties":false,"required":["data","meta"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["configuration_version","execution","engine","results_persisted_by_ipfrog","metric_units","limits","modes","analytics"],"properties":{"configuration_version":{"type":"integer","const":1},"execution":{"type":"string","const":"client"},"engine":{"type":"string","const":"@cloudflare/speedtest"},"results_persisted_by_ipfrog":{"type":"boolean","const":false},"metric_units":{"type":"object","additionalProperties":{"type":"string"}},"limits":{"type":"object","additionalProperties":{"type":"integer"}},"modes":{"type":"array","items":{"$ref":"#/components/schemas/SpeedTestMode"}},"analytics":{"type":"object","additionalProperties":false,"required":["schema_version","events","event_id","endpoint"],"properties":{"schema_version":{"type":"integer","const":1},"events":{"type":"array","items":{"$ref":"#/components/schemas/AnalyticsEventName"}},"event_id":{"type":"string","const":"random_uuid_per_test"},"endpoint":{"type":"string","const":"/v1/events"}}}}},"meta":{"$ref":"#/components/schemas/ResponseMetadata"}}},"AnalyticsEventName":{"type":"string","enum":["speed_test_started","speed_test_completed","speed_test_failed","speed_test_shared"]},"AnalyticsProperties":{"type":"object","additionalProperties":false,"required":["source"],"properties":{"source":{"type":"string","enum":["web","cli","terraform","desktop","mobile","api"]},"mode":{"type":"string","enum":["light","full"]},"duration_ms":{"type":"number","minimum":0,"maximum":3600000},"download_mbps":{"type":"number","minimum":0,"maximum":1000000},"upload_mbps":{"type":"number","minimum":0,"maximum":1000000},"latency_ms":{"type":"number","minimum":0,"maximum":600000},"jitter_ms":{"type":"number","minimum":0,"maximum":600000},"streaming_quality":{"type":"string","enum":["bad","poor","average","good","great","pending"]},"gaming_quality":{"type":"string","enum":["bad","poor","average","good","great","pending"]},"video_call_quality":{"type":"string","enum":["bad","poor","average","good","great","pending"]},"failure_reason":{"type":"string","enum":["engine_error","engine_load_error","network_error","cancelled","timeout"]},"tool_version":{"type":"string","maxLength":40}}},"AnalyticsEventRequest":{"type":"object","additionalProperties":false,"required":["event","event_id","properties"],"properties":{"event":{"$ref":"#/components/schemas/AnalyticsEventName"},"event_id":{"type":"string","format":"uuid","description":"Random per-test UUID; never a persistent identity."},"properties":{"$ref":"#/components/schemas/AnalyticsProperties"}}},"AnalyticsAcceptedResponse":{"type":"object","additionalProperties":false,"required":["data","meta"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["accepted"],"properties":{"accepted":{"type":"boolean","const":true}}},"meta":{"$ref":"#/components/schemas/ResponseMetadata"}}},"HealthResponse":{"type":"object","additionalProperties":false,"required":["data","meta"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["status","api_version","upstream_provider_health"],"properties":{"status":{"type":"string","const":"ok"},"api_version":{"type":"string","const":"v1"},"upstream_provider_health":{"type":"string","const":"not_checked"}}},"meta":{"$ref":"#/components/schemas/ResponseMetadata"}}},"Problem":{"type":"object","additionalProperties":false,"required":["type","title","status","detail","code","request_id"],"description":"RFC 9457 Problem Details with stable IPFrog extensions.","properties":{"type":{"type":"string","format":"uri"},"title":{"type":"string","maxLength":100},"status":{"type":"integer","minimum":400,"maximum":599},"detail":{"type":"string","maxLength":500},"code":{"type":"string","pattern":"^[a-z][a-z0-9_]*$","description":"Stable machine-readable error code."},"request_id":{"type":"string","format":"uuid"}}}}}}