{"openapi":"3.1.0","info":{"title":"RegionHop API","version":"1.0.0","summary":"Send API requests from another location.","description":"The consumer API contract. JSON endpoints are described as operations. The transparent URL-prefix proxy is documented under x-regionhop-proxy and https://regionhop.com/docs#proxy because its embedded absolute URL cannot be faithfully serialized as an OpenAPI path parameter. Catalog mutations/discovery tickets and account-origin session endpoints are outside this consumer contract; see the operations reference. Contract version is separate from deployment revision and package version. Unknown response fields must be ignored; location availability is dynamic. No target URLs, headers or bodies are persisted."},"servers":[{"url":"https://regionhop.com","description":"Production API origin. Account sessions use a separate origin."}],"externalDocs":{"description":"API reference, compatibility policy and release changes","url":"https://regionhop.com/docs#contract"},"tags":[{"name":"Requests"},{"name":"Catalog"},{"name":"Account data"},{"name":"Public"}],"security":[{"PersonalKey":[]},{"AdministratorKey":[]}],"paths":{"/probe":{"post":{"operationId":"probe","tags":["Requests"],"summary":"Send one regional request and capture a report","description":"Consumes one admitted account request, including validation failures after quota admission. No automatic retries or redirects. GET/HEAD target requests omit payload. Explicitly sending the same request to several locations sends it several times.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProbeRequest"},"examples":{"region":{"summary":"GET with a best-effort hint","value":{"url":"https://httpbingo.org/get","region":"weur","method":"GET"}},"colo":{"summary":"POST with strict observed colo selection","value":{"url":"https://httpbingo.org/anything","colo":"CDG","payload":{"hello":"world"}}}}}}},"responses":{"200":{"description":"Completed probe report. Inspect response.status and error.","headers":{"X-RegionHop-Limit-Minute":{"$ref":"#/components/headers/X-RegionHop-Limit-Minute"},"X-RegionHop-Remaining-Minute":{"$ref":"#/components/headers/X-RegionHop-Remaining-Minute"},"X-RegionHop-Reset-Minute":{"$ref":"#/components/headers/X-RegionHop-Reset-Minute"},"X-RegionHop-Limit-Day":{"$ref":"#/components/headers/X-RegionHop-Limit-Day"},"X-RegionHop-Remaining-Day":{"$ref":"#/components/headers/X-RegionHop-Remaining-Day"},"X-RegionHop-Reset-Day":{"$ref":"#/components/headers/X-RegionHop-Reset-Day"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProbeReport"}}}},"400":{"description":"Invalid request or recursive hop.","headers":{"X-RegionHop-Limit-Minute":{"$ref":"#/components/headers/X-RegionHop-Limit-Minute"},"X-RegionHop-Remaining-Minute":{"$ref":"#/components/headers/X-RegionHop-Remaining-Minute"},"X-RegionHop-Reset-Minute":{"$ref":"#/components/headers/X-RegionHop-Reset-Minute"},"X-RegionHop-Limit-Day":{"$ref":"#/components/headers/X-RegionHop-Limit-Day"},"X-RegionHop-Remaining-Day":{"$ref":"#/components/headers/X-RegionHop-Remaining-Day"},"X-RegionHop-Reset-Day":{"$ref":"#/components/headers/X-RegionHop-Reset-Day"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, expired, revoked, or invalid credential.","headers":{"X-RegionHop-Limit-Minute":{"$ref":"#/components/headers/X-RegionHop-Limit-Minute"},"X-RegionHop-Remaining-Minute":{"$ref":"#/components/headers/X-RegionHop-Remaining-Minute"},"X-RegionHop-Reset-Minute":{"$ref":"#/components/headers/X-RegionHop-Reset-Minute"},"X-RegionHop-Limit-Day":{"$ref":"#/components/headers/X-RegionHop-Limit-Day"},"X-RegionHop-Remaining-Day":{"$ref":"#/components/headers/X-RegionHop-Remaining-Day"},"X-RegionHop-Reset-Day":{"$ref":"#/components/headers/X-RegionHop-Reset-Day"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Target denied by allowlist, or credential lacks access.","headers":{"X-RegionHop-Limit-Minute":{"$ref":"#/components/headers/X-RegionHop-Limit-Minute"},"X-RegionHop-Remaining-Minute":{"$ref":"#/components/headers/X-RegionHop-Remaining-Minute"},"X-RegionHop-Reset-Minute":{"$ref":"#/components/headers/X-RegionHop-Reset-Minute"},"X-RegionHop-Limit-Day":{"$ref":"#/components/headers/X-RegionHop-Limit-Day"},"X-RegionHop-Remaining-Day":{"$ref":"#/components/headers/X-RegionHop-Remaining-Day"},"X-RegionHop-Reset-Day":{"$ref":"#/components/headers/X-RegionHop-Reset-Day"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Wrong method; Allow: POST. Authentication and quota checks run first.","headers":{"Allow":{"schema":{"const":"POST"}}},"content":{"text/plain":{"schema":{"type":"string"}}}},"413":{"description":"Request envelope exceeds 1 MiB.","headers":{"X-RegionHop-Limit-Minute":{"$ref":"#/components/headers/X-RegionHop-Limit-Minute"},"X-RegionHop-Remaining-Minute":{"$ref":"#/components/headers/X-RegionHop-Remaining-Minute"},"X-RegionHop-Reset-Minute":{"$ref":"#/components/headers/X-RegionHop-Reset-Minute"},"X-RegionHop-Limit-Day":{"$ref":"#/components/headers/X-RegionHop-Limit-Day"},"X-RegionHop-Remaining-Day":{"$ref":"#/components/headers/X-RegionHop-Remaining-Day"},"X-RegionHop-Reset-Day":{"$ref":"#/components/headers/X-RegionHop-Reset-Day"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Expected Content-Type: application/json.","headers":{"X-RegionHop-Limit-Minute":{"$ref":"#/components/headers/X-RegionHop-Limit-Minute"},"X-RegionHop-Remaining-Minute":{"$ref":"#/components/headers/X-RegionHop-Remaining-Minute"},"X-RegionHop-Reset-Minute":{"$ref":"#/components/headers/X-RegionHop-Reset-Minute"},"X-RegionHop-Limit-Day":{"$ref":"#/components/headers/X-RegionHop-Limit-Day"},"X-RegionHop-Remaining-Day":{"$ref":"#/components/headers/X-RegionHop-Remaining-Day"},"X-RegionHop-Reset-Day":{"$ref":"#/components/headers/X-RegionHop-Reset-Day"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Account quota exhausted. No target request was dispatched.","headers":{"X-RegionHop-Limit-Minute":{"$ref":"#/components/headers/X-RegionHop-Limit-Minute"},"X-RegionHop-Remaining-Minute":{"$ref":"#/components/headers/X-RegionHop-Remaining-Minute"},"X-RegionHop-Reset-Minute":{"$ref":"#/components/headers/X-RegionHop-Reset-Minute"},"X-RegionHop-Limit-Day":{"$ref":"#/components/headers/X-RegionHop-Limit-Day"},"X-RegionHop-Remaining-Day":{"$ref":"#/components/headers/X-RegionHop-Remaining-Day"},"X-RegionHop-Reset-Day":{"$ref":"#/components/headers/X-RegionHop-Reset-Day"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Service or dispatch failure. The target may have received the request; no retry was attempted.","headers":{"X-RegionHop-Limit-Minute":{"$ref":"#/components/headers/X-RegionHop-Limit-Minute"},"X-RegionHop-Remaining-Minute":{"$ref":"#/components/headers/X-RegionHop-Remaining-Minute"},"X-RegionHop-Reset-Minute":{"$ref":"#/components/headers/X-RegionHop-Reset-Minute"},"X-RegionHop-Limit-Day":{"$ref":"#/components/headers/X-RegionHop-Limit-Day"},"X-RegionHop-Remaining-Day":{"$ref":"#/components/headers/X-RegionHop-Remaining-Day"},"X-RegionHop-Reset-Day":{"$ref":"#/components/headers/X-RegionHop-Reset-Day"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Authentication unconfigured or requested destination/location unavailable.","headers":{"X-RegionHop-Limit-Minute":{"$ref":"#/components/headers/X-RegionHop-Limit-Minute"},"X-RegionHop-Remaining-Minute":{"$ref":"#/components/headers/X-RegionHop-Remaining-Minute"},"X-RegionHop-Reset-Minute":{"$ref":"#/components/headers/X-RegionHop-Reset-Minute"},"X-RegionHop-Limit-Day":{"$ref":"#/components/headers/X-RegionHop-Limit-Day"},"X-RegionHop-Remaining-Day":{"$ref":"#/components/headers/X-RegionHop-Remaining-Day"},"X-RegionHop-Reset-Day":{"$ref":"#/components/headers/X-RegionHop-Reset-Day"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/nodes":{"get":{"operationId":"listNodes","tags":["Catalog"],"summary":"List registered nodes and observed colos","description":"Read-only. Does not create nodes or trigger checks. Personal-key reads consume quota. Observations may be stale; strict routes verify before dispatch. Node IDs and colo membership are dynamic, not a fixed enum.","responses":{"200":{"description":"Current authenticated catalog.","headers":{"X-RegionHop-Limit-Minute":{"$ref":"#/components/headers/X-RegionHop-Limit-Minute"},"X-RegionHop-Remaining-Minute":{"$ref":"#/components/headers/X-RegionHop-Remaining-Minute"},"X-RegionHop-Reset-Minute":{"$ref":"#/components/headers/X-RegionHop-Reset-Minute"},"X-RegionHop-Limit-Day":{"$ref":"#/components/headers/X-RegionHop-Limit-Day"},"X-RegionHop-Remaining-Day":{"$ref":"#/components/headers/X-RegionHop-Remaining-Day"},"X-RegionHop-Reset-Day":{"$ref":"#/components/headers/X-RegionHop-Reset-Day"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Catalog"}}}},"400":{"description":"Invalid request or recursive hop.","headers":{"X-RegionHop-Limit-Minute":{"$ref":"#/components/headers/X-RegionHop-Limit-Minute"},"X-RegionHop-Remaining-Minute":{"$ref":"#/components/headers/X-RegionHop-Remaining-Minute"},"X-RegionHop-Reset-Minute":{"$ref":"#/components/headers/X-RegionHop-Reset-Minute"},"X-RegionHop-Limit-Day":{"$ref":"#/components/headers/X-RegionHop-Limit-Day"},"X-RegionHop-Remaining-Day":{"$ref":"#/components/headers/X-RegionHop-Remaining-Day"},"X-RegionHop-Reset-Day":{"$ref":"#/components/headers/X-RegionHop-Reset-Day"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, expired, revoked, or invalid credential.","headers":{"X-RegionHop-Limit-Minute":{"$ref":"#/components/headers/X-RegionHop-Limit-Minute"},"X-RegionHop-Remaining-Minute":{"$ref":"#/components/headers/X-RegionHop-Remaining-Minute"},"X-RegionHop-Reset-Minute":{"$ref":"#/components/headers/X-RegionHop-Reset-Minute"},"X-RegionHop-Limit-Day":{"$ref":"#/components/headers/X-RegionHop-Limit-Day"},"X-RegionHop-Remaining-Day":{"$ref":"#/components/headers/X-RegionHop-Remaining-Day"},"X-RegionHop-Reset-Day":{"$ref":"#/components/headers/X-RegionHop-Reset-Day"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Account quota exhausted. No target request was dispatched.","headers":{"X-RegionHop-Limit-Minute":{"$ref":"#/components/headers/X-RegionHop-Limit-Minute"},"X-RegionHop-Remaining-Minute":{"$ref":"#/components/headers/X-RegionHop-Remaining-Minute"},"X-RegionHop-Reset-Minute":{"$ref":"#/components/headers/X-RegionHop-Reset-Minute"},"X-RegionHop-Limit-Day":{"$ref":"#/components/headers/X-RegionHop-Limit-Day"},"X-RegionHop-Remaining-Day":{"$ref":"#/components/headers/X-RegionHop-Remaining-Day"},"X-RegionHop-Reset-Day":{"$ref":"#/components/headers/X-RegionHop-Reset-Day"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Service or dispatch failure. The target may have received the request; no retry was attempted.","headers":{"X-RegionHop-Limit-Minute":{"$ref":"#/components/headers/X-RegionHop-Limit-Minute"},"X-RegionHop-Remaining-Minute":{"$ref":"#/components/headers/X-RegionHop-Remaining-Minute"},"X-RegionHop-Reset-Minute":{"$ref":"#/components/headers/X-RegionHop-Reset-Minute"},"X-RegionHop-Limit-Day":{"$ref":"#/components/headers/X-RegionHop-Limit-Day"},"X-RegionHop-Remaining-Day":{"$ref":"#/components/headers/X-RegionHop-Remaining-Day"},"X-RegionHop-Reset-Day":{"$ref":"#/components/headers/X-RegionHop-Reset-Day"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Authentication unconfigured or requested destination/location unavailable.","headers":{"X-RegionHop-Limit-Minute":{"$ref":"#/components/headers/X-RegionHop-Limit-Minute"},"X-RegionHop-Remaining-Minute":{"$ref":"#/components/headers/X-RegionHop-Remaining-Minute"},"X-RegionHop-Reset-Minute":{"$ref":"#/components/headers/X-RegionHop-Reset-Minute"},"X-RegionHop-Limit-Day":{"$ref":"#/components/headers/X-RegionHop-Limit-Day"},"X-RegionHop-Remaining-Day":{"$ref":"#/components/headers/X-RegionHop-Remaining-Day"},"X-RegionHop-Reset-Day":{"$ref":"#/components/headers/X-RegionHop-Reset-Day"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/regions":{"get":{"operationId":"listRegions","tags":["Catalog"],"summary":"List supported best-effort region hints","description":"Personal-key reads consume quota. Hints are not guarantees of target egress.","responses":{"200":{"description":"Hint names and placement caveat.","headers":{"X-RegionHop-Limit-Minute":{"$ref":"#/components/headers/X-RegionHop-Limit-Minute"},"X-RegionHop-Remaining-Minute":{"$ref":"#/components/headers/X-RegionHop-Remaining-Minute"},"X-RegionHop-Reset-Minute":{"$ref":"#/components/headers/X-RegionHop-Reset-Minute"},"X-RegionHop-Limit-Day":{"$ref":"#/components/headers/X-RegionHop-Limit-Day"},"X-RegionHop-Remaining-Day":{"$ref":"#/components/headers/X-RegionHop-Remaining-Day"},"X-RegionHop-Reset-Day":{"$ref":"#/components/headers/X-RegionHop-Reset-Day"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Regions"}}}},"400":{"description":"Invalid request or recursive hop.","headers":{"X-RegionHop-Limit-Minute":{"$ref":"#/components/headers/X-RegionHop-Limit-Minute"},"X-RegionHop-Remaining-Minute":{"$ref":"#/components/headers/X-RegionHop-Remaining-Minute"},"X-RegionHop-Reset-Minute":{"$ref":"#/components/headers/X-RegionHop-Reset-Minute"},"X-RegionHop-Limit-Day":{"$ref":"#/components/headers/X-RegionHop-Limit-Day"},"X-RegionHop-Remaining-Day":{"$ref":"#/components/headers/X-RegionHop-Remaining-Day"},"X-RegionHop-Reset-Day":{"$ref":"#/components/headers/X-RegionHop-Reset-Day"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, expired, revoked, or invalid credential.","headers":{"X-RegionHop-Limit-Minute":{"$ref":"#/components/headers/X-RegionHop-Limit-Minute"},"X-RegionHop-Remaining-Minute":{"$ref":"#/components/headers/X-RegionHop-Remaining-Minute"},"X-RegionHop-Reset-Minute":{"$ref":"#/components/headers/X-RegionHop-Reset-Minute"},"X-RegionHop-Limit-Day":{"$ref":"#/components/headers/X-RegionHop-Limit-Day"},"X-RegionHop-Remaining-Day":{"$ref":"#/components/headers/X-RegionHop-Remaining-Day"},"X-RegionHop-Reset-Day":{"$ref":"#/components/headers/X-RegionHop-Reset-Day"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Account quota exhausted. No target request was dispatched.","headers":{"X-RegionHop-Limit-Minute":{"$ref":"#/components/headers/X-RegionHop-Limit-Minute"},"X-RegionHop-Remaining-Minute":{"$ref":"#/components/headers/X-RegionHop-Remaining-Minute"},"X-RegionHop-Reset-Minute":{"$ref":"#/components/headers/X-RegionHop-Reset-Minute"},"X-RegionHop-Limit-Day":{"$ref":"#/components/headers/X-RegionHop-Limit-Day"},"X-RegionHop-Remaining-Day":{"$ref":"#/components/headers/X-RegionHop-Remaining-Day"},"X-RegionHop-Reset-Day":{"$ref":"#/components/headers/X-RegionHop-Reset-Day"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Service or dispatch failure. The target may have received the request; no retry was attempted.","headers":{"X-RegionHop-Limit-Minute":{"$ref":"#/components/headers/X-RegionHop-Limit-Minute"},"X-RegionHop-Remaining-Minute":{"$ref":"#/components/headers/X-RegionHop-Remaining-Minute"},"X-RegionHop-Reset-Minute":{"$ref":"#/components/headers/X-RegionHop-Reset-Minute"},"X-RegionHop-Limit-Day":{"$ref":"#/components/headers/X-RegionHop-Limit-Day"},"X-RegionHop-Remaining-Day":{"$ref":"#/components/headers/X-RegionHop-Remaining-Day"},"X-RegionHop-Reset-Day":{"$ref":"#/components/headers/X-RegionHop-Reset-Day"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Authentication unconfigured or requested destination/location unavailable.","headers":{"X-RegionHop-Limit-Minute":{"$ref":"#/components/headers/X-RegionHop-Limit-Minute"},"X-RegionHop-Remaining-Minute":{"$ref":"#/components/headers/X-RegionHop-Remaining-Minute"},"X-RegionHop-Reset-Minute":{"$ref":"#/components/headers/X-RegionHop-Reset-Minute"},"X-RegionHop-Limit-Day":{"$ref":"#/components/headers/X-RegionHop-Limit-Day"},"X-RegionHop-Remaining-Day":{"$ref":"#/components/headers/X-RegionHop-Remaining-Day"},"X-RegionHop-Reset-Day":{"$ref":"#/components/headers/X-RegionHop-Reset-Day"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/usage":{"get":{"operationId":"getUsage","tags":["Account data"],"summary":"Read account allowance","description":"Does not consume quota. All personal keys and playground requests share fixed minute and UTC day windows. Current starter limits are 120/minute and 10,000/day; read the returned limits. Administrator keys return only {unmetered:true}, without quota headers.","responses":{"200":{"description":"Personal account usage or administrator unmetered marker.","headers":{"X-RegionHop-Limit-Minute":{"$ref":"#/components/headers/X-RegionHop-Limit-Minute"},"X-RegionHop-Remaining-Minute":{"$ref":"#/components/headers/X-RegionHop-Remaining-Minute"},"X-RegionHop-Reset-Minute":{"$ref":"#/components/headers/X-RegionHop-Reset-Minute"},"X-RegionHop-Limit-Day":{"$ref":"#/components/headers/X-RegionHop-Limit-Day"},"X-RegionHop-Remaining-Day":{"$ref":"#/components/headers/X-RegionHop-Remaining-Day"},"X-RegionHop-Reset-Day":{"$ref":"#/components/headers/X-RegionHop-Reset-Day"}},"content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/Usage"},{"$ref":"#/components/schemas/UnmeteredUsage"}]}}}},"400":{"description":"Invalid request or recursive hop.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, expired, revoked, or invalid credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Service or dispatch failure. The target may have received the request; no retry was attempted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Authentication unconfigured or requested destination/location unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/stats":{"get":{"operationId":"getStats","tags":["Account data"],"summary":"Read seven-day account aggregates","security":[{"PersonalKey":[]}],"description":"Does not consume quota and does not add quota headers. Administrator keys receive 403. Hourly aggregates cover admitted proxy/probe/playground attempts only, with asynchronous recording and no backfill. No URLs, headers, bodies, or individual request history. Includes the current partial hour. Proxy stream failures after headers are not captured. Latency averages include measured target-header samples only.","parameters":[{"name":"hours","in":"query","description":"Accepted query strings are exactly 24 or 168.","schema":{"type":"integer","enum":[24,168],"default":24}}],"responses":{"200":{"description":"Account-scoped hourly aggregates.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Stats"}}}},"400":{"description":"Invalid request or recursive hop.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, expired, revoked, or invalid credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Target denied by allowlist, or credential lacks access.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Service or dispatch failure. The target may have received the request; no retry was attempted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Authentication unconfigured or requested destination/location unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/health":{"get":{"operationId":"getLiveness","tags":["Public"],"summary":"Read Worker liveness and deployed revision","security":[],"description":"Does not test accounts, nodes, or end-to-end routing. version is null without revision metadata.","responses":{"200":{"description":"Worker is responding.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Liveness"}}}}}}},"/status.json":{"get":{"operationId":"getCatalogHealth","tags":["Public"],"summary":"Read public catalog health","security":[],"description":"Read-only; does not trigger checks. Hourly sweeps, stale after 90 minutes, at most 24 hours of recorded history. No node IDs or traffic details. The status endpoint shares the API Worker and is not independent outage monitoring.","responses":{"200":{"description":"Aggregate catalog health, including unknown or stale states.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicHealth"}}}},"503":{"description":"Status data temporarily unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"head":{"operationId":"headCatalogHealth","tags":["Public"],"summary":"Read catalog health response headers","security":[],"responses":{"200":{"description":"Same status and headers as GET, without a body."},"503":{"description":"Status data unavailable; no body."}}}},"/openapi.json":{"get":{"operationId":"getOpenApi","tags":["Public"],"summary":"Download this OpenAPI contract","security":[],"responses":{"200":{"description":"OpenAPI 3.1 document.","content":{"application/json":{"schema":{"type":"object"}}}}}},"head":{"operationId":"headOpenApi","tags":["Public"],"summary":"Read contract response headers","security":[],"responses":{"200":{"description":"Same headers as GET, without a body."}}}}},"components":{"securitySchemes":{"PersonalKey":{"type":"http","scheme":"bearer","description":"Personal key created at https://account.regionhop.com. Required for account statistics."},"AdministratorKey":{"type":"http","scheme":"bearer","description":"Legacy administrator credential. Unmetered; cannot read personal account statistics. Do not share."},"ProxyKey":{"type":"apiKey","in":"header","name":"X-RegionHop-Key","description":"Personal or administrator credential for the URL-prefix proxy only. Target Authorization stays separate."}},"schemas":{"Region":{"type":"string","enum":["wnam","enam","weur","eeur","apac","apac-ne","apac-se","oc","sam","afr","me"],"description":"Best-effort creation hint, not a placement guarantee. Several hints can resolve to one colo."},"Colo":{"type":"string","pattern":"^[A-Z]{3}$","examples":["CDG"]},"NodeId":{"type":"string","pattern":"^[a-f0-9]{64}$"},"Error":{"type":"object","properties":{"error":{"type":"string","description":"Human-readable explanation; wording is not a stable identifier."}},"required":["error"]},"ProbeError":{"type":"object","properties":{"code":{"type":"string","examples":["COLO_MISMATCH","LOCATION_UNAVAILABLE","UPSTREAM_TIMEOUT","UPSTREAM_FETCH_FAILED"],"description":"Machine-readable code. Clients must handle unfamiliar codes."},"message":{"type":"string"}},"required":["code","message"]},"Location":{"type":"object","properties":{"colo":{"anyOf":[{"$ref":"#/components/schemas/Colo"},{"type":"null"}]},"source":{"const":"cloudflare-trace"},"observedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"error":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["colo","source","observedAt","error"]},"ProbeRequest":{"type":"object","properties":{"url":{"type":"string","format":"uri","pattern":"^https?://","description":"Absolute HTTP(S) URL with a public DNS hostname. No URL credentials, IP literals, local names, or this service origin. An optional deployment allowlist can restrict targets. Fragments are discarded. Runtime hostname/header checks also apply."},"region":{"$ref":"#/components/schemas/Region"},"colo":{"$ref":"#/components/schemas/Colo"},"node":{"$ref":"#/components/schemas/NodeId"},"method":{"type":"string","pattern":"^(?:[gG][eE][tT]|[hH][eE][aA][dD]|[pP][oO][sS][tT]|[pP][uU][tT]|[pP][aA][tT][cC][hH]|[dD][eE][lL][eE][tT][eE]|[oO][pP][tT][iI][oO][nN][sS])$","default":"POST","description":"Case-insensitive HTTP method: GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS."},"headers":{"type":"object","additionalProperties":{"type":"string"},"description":"Target headers only. Target Authorization is supported. Host, Content-Length, connection, proxy, forwarding, cf-* and RegionHop headers are runtime-managed and rejected. Header names and values must be valid HTTP headers."},"payload":{"description":"Any JSON value, including null. Strings are sent verbatim; other values are JSON encoded. Omit for GET/HEAD. Content-Type defaults to text/plain;charset=UTF-8 for strings and application/json otherwise."},"timeoutMs":{"type":"integer","minimum":100,"maximum":30000,"default":15000,"description":"Covers target fetch and capture. A timeout does not establish that the target did not process the request."},"maxResponseBytes":{"type":"integer","minimum":1,"maximum":5242880,"default":1048576}},"required":["url"],"oneOf":[{"required":["region"],"not":{"anyOf":[{"required":["colo"]},{"required":["node"]}]}},{"required":["colo"],"not":{"anyOf":[{"required":["region"]},{"required":["node"]}]}},{"required":["node"],"not":{"anyOf":[{"required":["region"]},{"required":["colo"]}]}}],"allOf":[{"if":{"properties":{"method":{"pattern":"^(?:[gG][eE][tT]|[hH][eE][aA][dD])$"}},"required":["method"]},"then":{"not":{"required":["payload"]}}}],"description":"Exactly one selector is required. Unknown properties are currently ignored. The entire JSON envelope is limited to 1 MiB. JSON Schema validation is not a substitute for runtime destination and header validation."},"CapturedResponse":{"type":"object","properties":{"status":{"type":"integer","minimum":200,"maximum":599},"statusText":{"type":"string"},"ok":{"type":"boolean"},"headers":{"type":"object","additionalProperties":{"type":"string"}},"body":{},"bodyEncoding":{"type":"string","enum":["json","text","base64"]},"bytes":{"type":"integer","minimum":0},"truncated":{"type":"boolean"}},"required":["status","statusText","ok","headers","body","bodyEncoding","bytes","truncated"]},"ProbeReport":{"type":"object","properties":{"region":{"$ref":"#/components/schemas/Region"},"objectId":{"$ref":"#/components/schemas/NodeId"},"startedAt":{"type":"string","format":"date-time"},"requestedColo":{"$ref":"#/components/schemas/Colo"},"ingressColo":{"anyOf":[{"type":"string"},{"type":"null"}]},"location":{"$ref":"#/components/schemas/Location"},"timings":{"type":"object","properties":{"headersMs":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}]},"durationMs":{"type":"number","minimum":0},"dispatchMs":{"type":"number","minimum":0}},"required":["headersMs","durationMs","dispatchMs"]},"response":{"anyOf":[{"$ref":"#/components/schemas/CapturedResponse"},{"type":"null"}]},"error":{"anyOf":[{"$ref":"#/components/schemas/ProbeError"},{"type":"null"}]}},"required":["objectId","startedAt","ingressColo","location","timings","response","error"],"oneOf":[{"properties":{"response":{"$ref":"#/components/schemas/CapturedResponse"},"error":{"type":"null"}}},{"properties":{"response":{"type":"null"},"error":{"$ref":"#/components/schemas/ProbeError"}}}],"description":"HTTP 200 is a completed report, not target success. Target 4xx/5xx appear in response.status. A strict observation mismatch or unavailable trace returns error with response:null and no target dispatch. Catalog selection failures instead return an HTTP error. Region is omitted for unhinted nodes. Location is a separate trace observation, not proof of target egress. headersMs measures target headers; durationMs measures capture; dispatchMs also includes location verification and RPC. Timings exclude the client trip. Captured headers are diagnostics, not decoding instructions for the JSON envelope."},"Node":{"type":"object","properties":{"id":{"$ref":"#/components/schemas/NodeId"},"hint":{"anyOf":[{"$ref":"#/components/schemas/Region"},{"type":"null"}]},"creationIngressColo":{"anyOf":[{"type":"string"},{"type":"null"}]},"registeredAt":{"type":"string","format":"date-time"},"checkedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"location":{"anyOf":[{"$ref":"#/components/schemas/Location"},{"type":"null"}]},"lastKnownColo":{"anyOf":[{"$ref":"#/components/schemas/Colo"},{"type":"null"}]},"status":{"type":"string","enum":["unchecked","unavailable","stale","observed"]}},"required":["id","hint","registeredAt","checkedAt","location","lastKnownColo","status"]},"Catalog":{"type":"object","properties":{"nodes":{"type":"array","items":{"$ref":"#/components/schemas/Node"}},"colos":{"type":"array","items":{"$ref":"#/components/schemas/Colo"},"uniqueItems":true},"placement":{"type":"string"}},"required":["nodes","colos","placement"]},"Regions":{"type":"object","properties":{"regions":{"type":"object","additionalProperties":{"type":"string"}},"placement":{"type":"string"}},"required":["regions","placement"]},"UsageWindow":{"type":"object","properties":{"used":{"type":"integer","minimum":0},"remaining":{"type":"integer","minimum":0},"limit":{"type":"integer","minimum":0},"resetAt":{"type":"string","format":"date-time"}},"required":["used","remaining","limit","resetAt"]},"Usage":{"type":"object","properties":{"asOf":{"type":"string","format":"date-time"},"minute":{"$ref":"#/components/schemas/UsageWindow"},"day":{"$ref":"#/components/schemas/UsageWindow"}},"required":["asOf","minute","day"]},"UnmeteredUsage":{"type":"object","properties":{"unmetered":{"const":true}},"required":["unmetered"]},"StatsTotals":{"type":"object","properties":{"requests":{"type":"integer","minimum":0},"target2xx":{"type":"integer","minimum":0},"target3xx":{"type":"integer","minimum":0},"target4xx":{"type":"integer","minimum":0},"target5xx":{"type":"integer","minimum":0},"regionhopErrors":{"type":"integer","minimum":0},"timedRequests":{"type":"integer","minimum":0},"averageHeadersMs":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}]}},"required":["requests","target2xx","target3xx","target4xx","target5xx","regionhopErrors","timedRequests","averageHeadersMs"]},"Stats":{"type":"object","properties":{"hours":{"type":"integer","enum":[24,168]},"asOf":{"type":"string","format":"date-time"},"from":{"type":"string","format":"date-time"},"trackingSince":{"type":"string","format":"date-time"},"summary":{"allOf":[{"$ref":"#/components/schemas/StatsTotals"},{"type":"object","properties":{"observedColos":{"type":"integer","minimum":0}},"required":["observedColos"]}]},"timeline":{"type":"array","items":{"allOf":[{"$ref":"#/components/schemas/StatsTotals"},{"type":"object","properties":{"at":{"type":"string","format":"date-time"}},"required":["at"]}]}},"colos":{"type":"array","items":{"allOf":[{"$ref":"#/components/schemas/StatsTotals"},{"type":"object","properties":{"colo":{"type":"string","pattern":"^(?:[A-Z]{3}|unknown)$"}},"required":["colo"]}]}},"modes":{"type":"array","items":{"allOf":[{"$ref":"#/components/schemas/StatsTotals"},{"type":"object","properties":{"mode":{"type":"string","enum":["proxy","probe","playground"]}},"required":["mode"]}]}}},"required":["hours","asOf","from","trackingSince","summary","timeline","colos","modes"]},"HealthState":{"type":"string","enum":["healthy","degraded","unavailable","unknown","stale"]},"ColoHealth":{"type":"object","properties":{"colo":{"$ref":"#/components/schemas/Colo"},"status":{"$ref":"#/components/schemas/HealthState"},"nodes":{"type":"integer","minimum":0},"healthyNodes":{"type":"integer","minimum":0},"failedNodes":{"type":"integer","minimum":0},"changedNodes":{"type":"integer","minimum":0},"checkMs":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}]}},"required":["colo","status","nodes","healthyNodes","failedNodes","changedNodes","checkMs"]},"HealthHistory":{"type":"object","properties":{"at":{"type":"string","format":"date-time"},"status":{"$ref":"#/components/schemas/HealthState"},"states":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/HealthState"}}},"required":["at","states"]},"PublicHealth":{"type":"object","properties":{"status":{"$ref":"#/components/schemas/HealthState"},"generatedAt":{"type":"string","format":"date-time"},"checkedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"startedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"source":{"enum":["scheduled","manual",null]},"checking":{"type":"boolean"},"checkIntervalSeconds":{"type":"integer","minimum":0},"staleAfterSeconds":{"type":"integer","minimum":0},"nodes":{"type":"integer","minimum":0},"unlocatedNodes":{"type":"integer","minimum":0},"availableColos":{"type":"integer","minimum":0},"colos":{"type":"array","items":{"$ref":"#/components/schemas/ColoHealth"}},"history":{"type":"array","items":{"$ref":"#/components/schemas/HealthHistory"}},"scope":{"type":"string"}},"required":["status","generatedAt","checkedAt","startedAt","source","checking","checkIntervalSeconds","staleAfterSeconds","nodes","unlocatedNodes","availableColos","colos","history","scope"]},"Liveness":{"type":"object","properties":{"ok":{"const":true},"version":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["ok","version"]}},"headers":{"X-RegionHop-Limit-Minute":{"description":"Allowed requests in this fixed window. Present when personal-account usage is available; absent on administrator requests, /stats, and failures before quota evaluation.","schema":{"type":"integer","minimum":0}},"X-RegionHop-Remaining-Minute":{"description":"Remaining admitted requests in this window. Present when personal-account usage is available; absent on administrator requests, /stats, and failures before quota evaluation.","schema":{"type":"integer","minimum":0}},"X-RegionHop-Reset-Minute":{"description":"Window reset as Unix seconds. Present when personal-account usage is available; absent on administrator requests, /stats, and failures before quota evaluation.","schema":{"type":"integer","minimum":0}},"X-RegionHop-Limit-Day":{"description":"Allowed requests in this fixed window. Present when personal-account usage is available; absent on administrator requests, /stats, and failures before quota evaluation.","schema":{"type":"integer","minimum":0}},"X-RegionHop-Remaining-Day":{"description":"Remaining admitted requests in this window. Present when personal-account usage is available; absent on administrator requests, /stats, and failures before quota evaluation.","schema":{"type":"integer","minimum":0}},"X-RegionHop-Reset-Day":{"description":"Window reset as Unix seconds. Present when personal-account usage is available; absent on administrator requests, /stats, and failures before quota evaluation.","schema":{"type":"integer","minimum":0}},"Retry-After":{"description":"Seconds until the exhausted account windows reset. A target 429 in proxy mode is still the target response.","schema":{"type":"integer","minimum":1}},"X-RegionHop-Region":{"description":"Node creation hint; omitted for unhinted nodes.","schema":{"$ref":"#/components/schemas/Region"}},"X-RegionHop-Colo":{"description":"Observed outbound trace colo when available.","schema":{"$ref":"#/components/schemas/Colo"}},"X-RegionHop-Node":{"description":"Selected node ID, when dispatch reached it.","schema":{"$ref":"#/components/schemas/NodeId"}},"X-RegionHop-Observed-At":{"description":"Successful trace observation time.","schema":{"type":"string","format":"date-time"}},"X-RegionHop-Requested-Colo":{"description":"Expected colo for strict colo or node selection.","schema":{"$ref":"#/components/schemas/Colo"}},"X-RegionHop-Ingress-Colo":{"description":"Client ingress colo, when provided by Cloudflare.","schema":{"type":"string"}},"X-RegionHop-Headers-Ms":{"description":"Target fetch through response headers. Present for a target response.","schema":{"type":"number","minimum":0}},"X-RegionHop-Dispatch-Ms":{"description":"Worker-to-node time through response headers including trace and RPC, when available.","schema":{"type":"number","minimum":0}},"X-RegionHop-Upstream-Status":{"description":"Target status, equal to the HTTP response status.","schema":{"type":"integer","minimum":200,"maximum":599}},"X-RegionHop-Error":{"description":"Present only for RegionHop failures. Never indicates a target 4xx/5xx. Known codes include INVALID_REQUEST, RECURSIVE_REQUEST, NOT_CONFIGURED, UNAUTHORIZED, FORBIDDEN, RATE_LIMITED, DESTINATION_UNAVAILABLE, LOCATION_UNAVAILABLE, COLO_MISMATCH, DISPATCH_FAILED, UPSTREAM_TIMEOUT, UPSTREAM_FETCH_FAILED. Handle unknown codes.","schema":{"type":"string"}}}},"x-regionhop-proxy":{"urlTemplate":"https://regionhop.com/{destination}/{absoluteTargetUrl}","alternativeUrlTemplate":"https://regionhop.com/{destination}/{urlEncodedKey}/{absoluteTargetUrl}","description":"Concatenate the prefix with the complete HTTP(S) target URL as-is. Do not encode the target as one path segment. All query parameters belong to the target. Fragments are not transmitted. Destination is a region hint, uppercase colo, or node-{64-character-lowercase-hex-id}. A path key takes precedence over X-RegionHop-Key. URL keys can leak into client logs; prefer the header. OpenAPI path parameters cannot represent this embedded URL without changing its reserved characters, so no misleading generated-client operation is exposed.","methods":["GET","HEAD","POST","PUT","PATCH","DELETE","OPTIONS"],"security":[{"ProxyKey":[]}],"request":"Original method, application headers and body bytes, up to 1 MiB. Target Authorization is preserved unless it is a RegionHop credential. RegionHop credentials, managed/forwarding/connection headers and Referer are stripped. Host and Content-Length are runtime-managed. Adds X-RegionHop-Region when hinted, X-RegionHop-Colo when observed, and X-RegionHop-Node to the target request. Strict selection verifies a fresh trace before sending.","response":"Original target status, application headers and streamed bytes, without JSON wrapping. Multiple Set-Cookie values remain separate; HEAD/204/304 are bodyless. Hop-by-hop headers are removed; X-RegionHop-* is reserved for trusted service metadata. HTTP framing/compression may be runtime-managed. Cookie domains/paths and CORS are not rewritten. Redirects are returned unchanged and never followed; a client following an absolute Location leaves RegionHop. No CONNECT or WebSocket support.","limits":"15-second deadline for target headers. No RegionHop response-body capture limit or body-reading deadline; platform limits apply. Failures after response headers terminate the stream and cannot change its status. No automatic retries or fallback to another colo.","errors":"RegionHop failures use text/plain with X-RegionHop-Error, and no body on HEAD: 400 invalid/recursive request, 401 unauthorized, 403 denied target, 409 observed-colo mismatch, 413 oversized body, 429 quota exhausted, 502 dispatch/connection failure, 503 configuration/destination/location unavailable, 504 target-header timeout. Target 4xx/5xx remain target responses without X-RegionHop-Error. A dispatch failure or timeout can occur after the target received the request.","responseHeaders":{"X-RegionHop-Region":{"$ref":"#/components/headers/X-RegionHop-Region"},"X-RegionHop-Colo":{"$ref":"#/components/headers/X-RegionHop-Colo"},"X-RegionHop-Node":{"$ref":"#/components/headers/X-RegionHop-Node"},"X-RegionHop-Observed-At":{"$ref":"#/components/headers/X-RegionHop-Observed-At"},"X-RegionHop-Requested-Colo":{"$ref":"#/components/headers/X-RegionHop-Requested-Colo"},"X-RegionHop-Ingress-Colo":{"$ref":"#/components/headers/X-RegionHop-Ingress-Colo"},"X-RegionHop-Headers-Ms":{"$ref":"#/components/headers/X-RegionHop-Headers-Ms"},"X-RegionHop-Dispatch-Ms":{"$ref":"#/components/headers/X-RegionHop-Dispatch-Ms"},"X-RegionHop-Upstream-Status":{"$ref":"#/components/headers/X-RegionHop-Upstream-Status"},"X-RegionHop-Error":{"$ref":"#/components/headers/X-RegionHop-Error"},"X-RegionHop-Limit-Minute":{"$ref":"#/components/headers/X-RegionHop-Limit-Minute"},"X-RegionHop-Remaining-Minute":{"$ref":"#/components/headers/X-RegionHop-Remaining-Minute"},"X-RegionHop-Reset-Minute":{"$ref":"#/components/headers/X-RegionHop-Reset-Minute"},"X-RegionHop-Limit-Day":{"$ref":"#/components/headers/X-RegionHop-Limit-Day"},"X-RegionHop-Remaining-Day":{"$ref":"#/components/headers/X-RegionHop-Remaining-Day"},"X-RegionHop-Reset-Day":{"$ref":"#/components/headers/X-RegionHop-Reset-Day"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}}}}