x402 Directory

geoprimitives · Marine Depth

Give it a latitude and longitude and it answers with what the nautical chart says about the water there: the depth range of the charted depth area containing the position, the nearest charted sounding and how far away it is, and the chart's own zone of confidence for that area. Parameters go in the query string: this is a GET, there is no body. NOT FOR NAVIGATION, stated first because it is a condition of using the source. This is derived from NOAA Electronic Navigational Charts and redistributed; it is not an official NOAA ENC and does not meet federal chart carriage regulations under 33 CFR 164 or SOLAS chapter V, which only charts from NOAA or a certified NOAA ENC distributor do. Every response repeats this under `disclaimer`. NOAA and NOAA ENC are registered trademarks of NOAA, which does not endorse this service. COVERAGE is 65 NOAA ENC cells of usage bands 3, 4 and 5 over five working areas of southeast and southcentral Alaska: Sitka Sound; Kasaan Bay and Clarence Strait; Metlakatla, Ketchikan and Revillagigedo Channel; Juneau, Gastineau Channel and Lynn Canal; and Cordova with eastern Prince William Sound. It is not statewide, it is not the whole coast, and the small-scale cells that would make it look wider were deliberately left out. The coverage check reads the coordinate, so it runs in the handler after payment rather than in front of the 402: a position off the charts is quoted like any other and then refused with outside_coverage. A refusal does not settle and nothing is charged, but it costs a signature and a round trip, so check the coverage first. Every response repeats it under `coverage`. NOTHING IS INTERPOLATED, and that is the difference between this and GET /v1/elevation. Terrain is a continuous surface and sampling it between pixels is legitimate; a chart is a set of assertions a hydrographer made, and averaging two of them invents a depth nobody surveyed. So `depthAreaMinimum` is DRVAL1 of the charted depth area the position falls inside, the

How to call it

curl -i -X GET https://api.geoprimitives.dev/v1/marine/depth

# It answers 402 Payment Required, with the price and where to pay.
# Pay with any x402 client, then send the same request again.

Uptime, grade and call counts come from other directories, not from us. A blank means nobody has measured it. It does not mean it is safe.

More from api.geoprimitives.dev

geoprimitives · H3 Index

geoprimitives · api.geoprimitives.dev

Index points to H3 cells. Send "points" as [longitude, latitude] positions in EPSG:4326 and get each one's containing H3 cell at one or several resolutions, optionally with the cell's centre and its closed boundary ring. Use it to bucket points into a fixed hexagonal grid so datasets that share no keys can be joined, aggregated or deduplicated on cell id. This route indexes positions and nothing else. It does not accept polygons: a body carrying "geojson" is refused rather than served, and because "points" is required here that refusal costs you nothing -- it happens before a price is quoted. To cover a Polygon or MultiPolygon with the cells that tile it, POST /v1/h3/polyfill instead. That is a separate route at a higher price because it is a materially more expensive job: measured on this runtime, indexing one point takes about 0.003 ms and returns 168 bytes, while the cheapest possible polyfill takes about 1.5 ms -- the cell count has to be estimated before any cell is generated -- and a polyfill at its cell cap is about 200 ms and 1.8 MB. This route is priced with POST /v1/transform, which does the same class of per-position work, and below POST /v1/h3/polyfill. Every call needs exactly one of "resolution" or "resolutions". Input is EPSG:4326, longitude then latitude; out-of-range values are refused rather than normalised, because H3 will happily index a latitude of 950 and answer with a real, wrong cell. Limits: 10000 points, 4 resolutions per call, and a 1 MiB request body.

$0.005 Base

geoprimitives · Geometry Area

geoprimitives · api.geoprimitives.dev

Measure how much ground a polygon covers, in square metres and square kilometres, with holes subtracted and every part of a MultiPolygon summed. Use it after POST /v1/geometry/intersect to size an overlap, or on a boundary you already hold. Points and lines contribute zero rather than an error, so a mixed collection is safe to send. Not turf's area, which applies the spherical-excess formula to geodetic latitudes on a 6371008.8 m sphere and comes out 0.45% high at the equator and 0.85% low at 80 deg latitude. This maps latitude to authalic latitude on the WGS 84 authalic sphere first, landing within 5e-3% of GeographicLib's geodesic area on parcel-scale rings and converging to 1e-6% as ring edges are densified. Ring edges are treated as straight in longitude/latitude, per RFC 7946 and turf; a geodesic-edge area differs on long slanted edges, by 1.9% on a 1.7-degree triangle. Winding order is ignored: ring 0 is the exterior and the rest are holes. Input is EPSG:4326 only. Limits: 100000 positions across the whole document, 1 MiB request body.

$0.01 Base

geoprimitives · Geometry Buffer

geoprimitives · api.geoprimitives.dev

Buffer a geometry by a distance in metres and get the offset polygon back. Use it for service areas, setbacks, and proximity envelopes you will later test with POST /v1/pip. Accepts any geometry -- point, line, polygon, or a collection of them, each buffered about its own centre latitude -- and answers with a Feature, or a FeatureCollection when you sent several. A buffer that collapses (a negative distance larger than the shape, or any negative distance on a point or a line) answers geojson:null with empty:true, which is an answer and not an error. Geodesic-aware: turf buffers in an azimuthal equidistant plane scaled by a sphere, which is a systematic -0.56% error at the equator running to +0.44% at 80 deg latitude, and this endpoint cancels that by scaling the distance to the Gaussian radius of curvature at the feature's own centre latitude. Measured against GeographicLib the result is then within +/-0.34% of the requested distance at the equator, +/-0.08% at 60 deg, +/-0.04% at 70 deg and +/-0.01% at 80 deg; the residual is the ellipsoid's north-south versus east-west curvature, which no single sphere can represent, and it shrinks towards the poles. Between vertices the polygon edge cuts a further 1 - cos(pi/(4*steps)) inside the true offset curve, 0.054% at the default steps=24. Input is EPSG:4326 only. Limits: 2000 positions across the whole document, 1 MiB request body, distance within +/-1000000 m, steps 1 to 128.

$0.01 Base

geoprimitives · Geometry Simplify

geoprimitives · api.geoprimitives.dev

Drop vertices from a geometry while keeping its shape. Use it to cut a boundary down before a call whose cost is vertex-driven -- POST /v1/pip caps on points times polygon vertices, and POST /v1/geometry/buffer and the overlay ops cap at 2000 positions -- and to shrink what you store or draw. The response reports outputVertices next to inputVertices, so the saving is measurable before you spend again. The algorithm is Douglas-Peucker. Send toleranceMeters for a ground tolerance applied isotropically: both axes are scaled to metres at the input's centre latitude first, so at 70 deg N the simplification is not three times as aggressive east-west as north-south, which a raw degree tolerance makes it. Send tolerance instead for the raw degree tolerance if you want turf's behaviour unchanged. Retained vertices come back exactly as sent rather than round-tripped through the scaling. Not topology-preserving: adjacent polygons simplified separately can gap or overlap along a shared edge. Input is EPSG:4326 only. Limits: 100000 positions across the whole document, 1 MiB request body.

$0.01 Base

geoprimitives · Timezone

geoprimitives · api.geoprimitives.dev

Give it a longitude and latitude and it answers with the IANA timezone identifier (America/New_York), the UTC offset in force there right now, whether daylight saving is currently in effect and by how much, the local wall-clock time, and the zone's standard offset. Pass an optional ISO 8601 `at` instant to ask about any moment between 1900 and 2100 instead of now, which is what you want when scheduling something months out across a DST boundary. Parameters go in the query string: this is a GET, there is no body. Two halves, with different vintages, and the difference matters. The offset and the DST rules come from the runtime's own timezone database and are current: a rule change reaches this endpoint when Cloudflare updates ICU, with no redeploy here. The *boundaries* come from tz_world (efele.net), CC0 1.0 and derived from VMAP0, a public-domain US government product. That map was frozen at tzdb 2016d in May 2016, and this catalog sells public-domain and permissively-licensed data only, which is why it is used rather than the current OpenStreetMap-derived alternative. What the vintage costs, measured against IANA's own coordinates for all 312 zones in zone1970.tab rather than estimated: 293 agree. Of the 19 that do not, 7 are Antarctic research stations, which this map does not cover at all and which fall back to the open-water rule; 7 more return a different identifier for the identical offset and DST all year (Australia/Brisbane for Australia/Lindeman, America/Regina for America/Swift_Current, and five like them), so the time is right and only the name is old. That leaves four regions where the answer is up to one hour wrong because the zone was split after 2016: Chilean Magallanes and Aysen (answered as America/Santiago rather than America/Punta_Arenas or America/Coyhaique), the Mexican border municipalities around Ciudad Juarez, Saratov Oblast in Russia, and the weeks each spring when Asia/Hebron and Asia/Jerusalem change on different dates. If you query insid

$0.005 Base

geoprimitives · Geojson Repair

geoprimitives · api.geoprimitives.dev

Repair GeoJSON and get the fixed document back with a log of every alteration: rings rewound to RFC 7946 winding order, consecutive duplicate vertices dropped, unclosed rings closed, and polygon nesting fixed (mis-ordered exterior rings, holes that fall outside their exterior, MultiPolygon members that are really holes). Reach for it when POST /v1/geojson/validate reported errors, or when /v1/geometry, /v1/h3/polyfill or /v1/pip refused your document -- unclosed rings are the usual reason, and this is the cheapest way to clear them. Conservative by design: it only rewrites the classes above, and anything else it found is returned in unrepaired rather than guessed at, so it will not invent geometry or move a coordinate. Idempotent -- a conformant document comes back untouched with changed:false, so a second call costs money and changes nothing. Your input object is never mutated. Coordinate values are preserved exactly; nothing is rounded or reprojected. Limit: 1 MiB request body.

$0.01 Base