{"openapi":"3.1.0","info":{"title":"geo","version":"0.2.0","description":"Pure-library spatial math and timezone lookup. Distance, bearing, polygons, point-in-polygon, timezone-by-coords. No external API calls — all computed in-Worker.","x-guidance":"Coordinates are decimal degrees: lat in [-90, 90], lng in [-180, 180]. Distances are in meters unless otherwise stated. Polygons follow GeoJSON Position order [lng, lat] (NOT [lat, lng]) per RFC 7946.","x-sibling-services":[{"url":"https://convert.boring-api.com","title":"Document & data conversion","description":"HTML/Markdown/PDF/DOCX, JSON/YAML/XML/CSV/TSV, hash, base64 — pure-library conversions.","status":"planned"}],"x-discovery-url":"https://boring-api.com/services","x-base-url":"https://geo.boring-api.com"},"servers":[{"url":"https://geo.boring-api.com"}],"paths":{"/distance":{"post":{"summary":"Great-circle distance between two points (meters).","description":"","x-payment-info":{"price":{"mode":"fixed","currency":"USDC","amount":"0.0005"},"protocols":["x402"],"network":"base","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","payTo":"0x9509D8b069417E8a1d76b4Ab585df01BE00cbbA8"},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"meters":{"type":"number"},"kilometers":{"type":"number"},"method":{"type":"string","enum":["haversine"]}}}}}},"402":{"description":"Payment required (x402 challenge)","content":{"application/json":{"schema":{"type":"object","properties":{"x402Version":{"type":"integer"},"accepts":{"type":"array"},"error":{"type":["string","null"]}}}}}}},"x-related-endpoints":[{"rel":"batch","path":"/distance-matrix","title":"Compute distances for many origin/destination pairs at once"},{"rel":"alternative","path":"/bearing","title":"Initial bearing from A to B (degrees)"},{"rel":"next-step","path":"/destination","title":"Compute the point at a given bearing+distance from origin"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["from","to"],"properties":{"from":{"type":"object","required":["lat","lng"],"properties":{"lat":{"type":"number","minimum":-90,"maximum":90},"lng":{"type":"number","minimum":-180,"maximum":180}}},"to":{"type":"object","required":["lat","lng"],"properties":{"lat":{"type":"number","minimum":-90,"maximum":90},"lng":{"type":"number","minimum":-180,"maximum":180}}}}}}}}}},"/distance-matrix":{"post":{"summary":"Distance matrix for N origins × M destinations.","description":"","x-payment-info":{"price":{"mode":"fixed","currency":"USDC","amount":"0.002"},"protocols":["x402"],"network":"base","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","payTo":"0x9509D8b069417E8a1d76b4Ab585df01BE00cbbA8"},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"meters":{"type":"array","items":{"type":"array","items":{"type":"number"}}}}}}}},"402":{"description":"Payment required (x402 challenge)","content":{"application/json":{"schema":{"type":"object","properties":{"x402Version":{"type":"integer"},"accepts":{"type":"array"},"error":{"type":["string","null"]}}}}}}},"x-related-endpoints":[{"rel":"alternative","path":"/distance","title":"Single-pair distance (cheaper for one-off)"},{"rel":"related","path":"/nearest","title":"Find nearest candidate to a single origin"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["origins","destinations"],"properties":{"origins":{"type":"array","maxItems":25,"items":{"type":"object","required":["lat","lng"],"properties":{"lat":{"type":"number","minimum":-90,"maximum":90},"lng":{"type":"number","minimum":-180,"maximum":180}}}},"destinations":{"type":"array","maxItems":25,"items":{"type":"object","required":["lat","lng"],"properties":{"lat":{"type":"number","minimum":-90,"maximum":90},"lng":{"type":"number","minimum":-180,"maximum":180}}}}}}}}}}},"/bbox":{"post":{"summary":"Bounding box of a circle around a point.","description":"","x-payment-info":{"price":{"mode":"fixed","currency":"USDC","amount":"0.0005"},"protocols":["x402"],"network":"base","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","payTo":"0x9509D8b069417E8a1d76b4Ab585df01BE00cbbA8"},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"minLat":{"type":"number"},"minLng":{"type":"number"},"maxLat":{"type":"number"},"maxLng":{"type":"number"}}}}}},"402":{"description":"Payment required (x402 challenge)","content":{"application/json":{"schema":{"type":"object","properties":{"x402Version":{"type":"integer"},"accepts":{"type":"array"},"error":{"type":["string","null"]}}}}}}},"x-related-endpoints":[{"rel":"related","path":"/destination","title":"Compute a point at a bearing+distance"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["center","radiusMeters"],"properties":{"center":{"type":"object","required":["lat","lng"],"properties":{"lat":{"type":"number","minimum":-90,"maximum":90},"lng":{"type":"number","minimum":-180,"maximum":180}}},"radiusMeters":{"type":"number","minimum":0}}}}}}}},"/point-in-polygon":{"post":{"summary":"Test whether a point is inside a polygon (GeoJSON).","description":"","x-payment-info":{"price":{"mode":"fixed","currency":"USDC","amount":"0.0005"},"protocols":["x402"],"network":"base","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","payTo":"0x9509D8b069417E8a1d76b4Ab585df01BE00cbbA8"},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"inside":{"type":"boolean"}}}}}},"402":{"description":"Payment required (x402 challenge)","content":{"application/json":{"schema":{"type":"object","properties":{"x402Version":{"type":"integer"},"accepts":{"type":"array"},"error":{"type":["string","null"]}}}}}}},"x-related-endpoints":[{"rel":"related","path":"/polygon-area","title":"Compute the area of a polygon (m²)"},{"rel":"related","path":"/polygon-centroid","title":"Compute the centroid of a polygon"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["point","polygon"],"properties":{"point":{"type":"object","required":["lat","lng"],"properties":{"lat":{"type":"number","minimum":-90,"maximum":90},"lng":{"type":"number","minimum":-180,"maximum":180}}},"polygon":{"type":"object","description":"GeoJSON Polygon or MultiPolygon Feature/Geometry"}}}}}}}},"/polygon-area":{"post":{"summary":"Compute the area of a GeoJSON polygon in square meters.","description":"","x-payment-info":{"price":{"mode":"fixed","currency":"USDC","amount":"0.0005"},"protocols":["x402"],"network":"base","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","payTo":"0x9509D8b069417E8a1d76b4Ab585df01BE00cbbA8"},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"squareMeters":{"type":"number"},"squareKilometers":{"type":"number"}}}}}},"402":{"description":"Payment required (x402 challenge)","content":{"application/json":{"schema":{"type":"object","properties":{"x402Version":{"type":"integer"},"accepts":{"type":"array"},"error":{"type":["string","null"]}}}}}}},"x-related-endpoints":[{"rel":"related","path":"/polygon-centroid","title":"Centroid of the same polygon"},{"rel":"related","path":"/point-in-polygon","title":"Membership test for a point"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["polygon"],"properties":{"polygon":{"type":"object","description":"GeoJSON Polygon Feature/Geometry"}}}}}}}},"/polygon-centroid":{"post":{"summary":"Compute the centroid (center of mass) of a GeoJSON polygon.","description":"","x-payment-info":{"price":{"mode":"fixed","currency":"USDC","amount":"0.0005"},"protocols":["x402"],"network":"base","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","payTo":"0x9509D8b069417E8a1d76b4Ab585df01BE00cbbA8"},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"lat":{"type":"number"},"lng":{"type":"number"}}}}}},"402":{"description":"Payment required (x402 challenge)","content":{"application/json":{"schema":{"type":"object","properties":{"x402Version":{"type":"integer"},"accepts":{"type":"array"},"error":{"type":["string","null"]}}}}}}},"x-related-endpoints":[{"rel":"related","path":"/polygon-area","title":"Area of the same polygon"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["polygon"],"properties":{"polygon":{"type":"object"}}}}}}}},"/nearest":{"post":{"summary":"Find the nearest candidate point to an origin.","description":"","x-payment-info":{"price":{"mode":"fixed","currency":"USDC","amount":"0.001"},"protocols":["x402"],"network":"base","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","payTo":"0x9509D8b069417E8a1d76b4Ab585df01BE00cbbA8"},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"index":{"type":"integer"},"point":{"type":"object","required":["lat","lng"],"properties":{"lat":{"type":"number","minimum":-90,"maximum":90},"lng":{"type":"number","minimum":-180,"maximum":180}}},"meters":{"type":"number"}}}}}},"402":{"description":"Payment required (x402 challenge)","content":{"application/json":{"schema":{"type":"object","properties":{"x402Version":{"type":"integer"},"accepts":{"type":"array"},"error":{"type":["string","null"]}}}}}}},"x-related-endpoints":[{"rel":"batch","path":"/distance-matrix","title":"Full N×M distance matrix instead of nearest only"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["origin","candidates"],"properties":{"origin":{"type":"object","required":["lat","lng"],"properties":{"lat":{"type":"number","minimum":-90,"maximum":90},"lng":{"type":"number","minimum":-180,"maximum":180}}},"candidates":{"type":"array","maxItems":5000,"items":{"type":"object","required":["lat","lng"],"properties":{"lat":{"type":"number","minimum":-90,"maximum":90},"lng":{"type":"number","minimum":-180,"maximum":180}}}}}}}}}}},"/bearing":{"post":{"summary":"Initial bearing from A to B in degrees (0=N, 90=E).","description":"","x-payment-info":{"price":{"mode":"fixed","currency":"USDC","amount":"0.0005"},"protocols":["x402"],"network":"base","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","payTo":"0x9509D8b069417E8a1d76b4Ab585df01BE00cbbA8"},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"degrees":{"type":"number"}}}}}},"402":{"description":"Payment required (x402 challenge)","content":{"application/json":{"schema":{"type":"object","properties":{"x402Version":{"type":"integer"},"accepts":{"type":"array"},"error":{"type":["string","null"]}}}}}}},"x-related-endpoints":[{"rel":"related","path":"/destination","title":"Inverse: compute B from A given bearing and distance"},{"rel":"related","path":"/distance","title":"Distance between the same two points"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["from","to"],"properties":{"from":{"type":"object","required":["lat","lng"],"properties":{"lat":{"type":"number","minimum":-90,"maximum":90},"lng":{"type":"number","minimum":-180,"maximum":180}}},"to":{"type":"object","required":["lat","lng"],"properties":{"lat":{"type":"number","minimum":-90,"maximum":90},"lng":{"type":"number","minimum":-180,"maximum":180}}}}}}}}}},"/destination":{"post":{"summary":"Point reached by traveling distance+bearing from origin.","description":"","x-payment-info":{"price":{"mode":"fixed","currency":"USDC","amount":"0.0005"},"protocols":["x402"],"network":"base","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","payTo":"0x9509D8b069417E8a1d76b4Ab585df01BE00cbbA8"},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"lat":{"type":"number"},"lng":{"type":"number"}}}}}},"402":{"description":"Payment required (x402 challenge)","content":{"application/json":{"schema":{"type":"object","properties":{"x402Version":{"type":"integer"},"accepts":{"type":"array"},"error":{"type":["string","null"]}}}}}}},"x-related-endpoints":[{"rel":"related","path":"/bearing","title":"Inverse: compute bearing from A to B"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["origin","bearingDegrees","distanceMeters"],"properties":{"origin":{"type":"object","required":["lat","lng"],"properties":{"lat":{"type":"number","minimum":-90,"maximum":90},"lng":{"type":"number","minimum":-180,"maximum":180}}},"bearingDegrees":{"type":"number"},"distanceMeters":{"type":"number"}}}}}}}},"/timezone":{"get":{"summary":"IANA timezone for a coordinate (e.g. America/New_York).","description":"Query: ?lat=<deg>&lng=<deg>. Returns the IANA tz database name. Bundled tz-lookup data; no external API.","x-payment-info":{"price":{"mode":"fixed","currency":"USDC","amount":"0.0005"},"protocols":["x402"],"network":"base","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","payTo":"0x9509D8b069417E8a1d76b4Ab585df01BE00cbbA8"},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"tz":{"type":"string","example":"America/New_York"},"lat":{"type":"number"},"lng":{"type":"number"}}}}}},"402":{"description":"Payment required (x402 challenge)","content":{"application/json":{"schema":{"type":"object","properties":{"x402Version":{"type":"integer"},"accepts":{"type":"array"},"error":{"type":["string","null"]}}}}}}},"x-related-endpoints":[{"rel":"related","url":"https://convert.boring-api.com/json-to-yaml","title":"Convert your timezone-keyed config from JSON to YAML"}]}}}}