API Documentation & Live Sandbox
JSON over HTTP, keyless, open — zero authentication required. Call any endpoint directly from JavaScript, Python, .NET, Node.js, or SQL.
Interactive API Sandbox
checking…Select an endpoint, adjust the parameters, and execute a live request against this deployment. Nothing is mocked and nothing is stored.
Conventions & Rules
- Cells are strings, always. Never parse a cell identifier into a JavaScript
Number— indices exceedNumber.MAX_SAFE_INTEGER. - Every response carries
grid_version, and every HTTP response includes anX-Terra-Grid-Versionheader. Always verify matching grid versions before joining datasets. - Coordinates are KSA-GRF17. Input latitude/longitude coordinates must be in Saudi Arabia's official datum.
- Error format: Standard JSON errors
{"error": {"code": "...", "message": "..."}}with appropriate HTTP status codes.
Error Reference
| Code | HTTP Status | Description |
|---|---|---|
| out_of_extent | 422 | Coordinate falls outside the grid rectangle extent. |
| bad_resolution | 400 | Resolution out of valid range (0–14). |
| bad_check_character | 400 | Terra Grid Code failed checksum validation. |
| bad_cell | 400 | String is not a valid Terra Index String (TIS). |
| too_many | 400 | Polyfill request exceeds maximum cell count safety limit. |
Endpoints Reference
Service
Grid identity, coverage extent, base resolution, and resolution ladder array.
curl https://terra.example.sa/v1/health
Complete resolution facts for all 15 levels: cell area, flat-to-flat width, corner-to-corner diameter, and Kingdom cell counts.
Pass optional bbox=south,west,north,east and zoom query params for viewport specific estimates.
curl "https://terra.example.sa/v1/stats/resolution?bbox=24.60,46.60,24.80,46.85&zoom=13"
Cells
Bulk index up to 10,000 coordinates in a single request. Individual failures are reported per row in the results array without failing the batch.
curl -X POST https://terra.example.sa/v1/index \
-H "Content-Type: application/json" \
-d '{
"res": 8,
"points": [
{"id": "ORD-1", "lat": 24.6877, "lon": 46.7219},
{"id": "ORD-2", "lat": 21.4858, "lon": 39.1925}
]
}'
Get centre coordinate, 6 vertex boundary polygon, area in hectares, Grid Code, and full ancestor chain up to Res 0.
curl https://terra.example.sa/v1/cell/t108858156b1ffff8
The ancestor of a cell. One level up by default; pass res for any coarser level. A Terra index carries its own ancestry in its bits, so this is arithmetic rather than a lookup.
curl "https://terra.example.sa/v1/cell/t108858156b1ffff8/parent?res=6"
The seven cells one level down, or 7n for a deeper res. A request above the batch limit is refused rather than answered with a truncated list.
curl https://terra.example.sa/v1/cell/t108858156b1ffff8/children
Returns all cells within k steps (3k² + 3k + 1 cells). Replaces spatial radius queries with exact B-tree set lookups: WHERE terra_cell = ANY(...).
curl "https://terra.example.sa/v1/cell/t108858156b1ffff8/disk?k=2"
Only the cells exactly k steps out — the 6k boundary of the disk, without its interior.
curl "https://terra.example.sa/v1/cell/t108858156b1ffff8/ring?k=2"
Steps between two cells — not metres — with an approximate metre equivalent beside them. Both cells must share a resolution.
curl "https://terra.example.sa/v1/distance?a=t108858156b1ffff8&b=t108858156b20ffff8"
Validate a Grid Code someone typed by hand and resolve it to a cell. A bad check character is a 400 and is never auto-corrected: the nearest valid code is a different place on the ground.
curl https://terra.example.sa/v1/grid-code/T08-11C1ATR5
Areas & map data
Returns all covering hexagonal cells for a bounding box or GeoJSON Polygon. Assigned via center-containment.
curl -X POST https://terra.example.sa/v1/polyfill \
-H "Content-Type: application/json" \
-d '{"res": 8, "bbox": [24.680, 46.700, 24.690, 46.710]}'
Hexagons covering a viewport, as GeoJSON. Resolution follows the map's zoom unless one is named. Past the draw limit it returns a count instead of geometry, so the client can say "zoom in" rather than wait on a fill nothing can render.
curl "https://terra.example.sa/v1/map/hex?bbox=24.60,46.60,24.80,46.85&zoom=13&clip=1"
One fixed tile of the grid, as GeoJSON. A cell belongs to the tile its centre falls in, so tiling a viewport neither drops a cell nor draws one twice. The answer is a constant of the grid and the boundary, so it is cached for a year — pass v=<map_version> and a boundary change re-fetches. Shapes are cut to the Kingdom: cells the border crosses come back as only their inside part, tagged clipped with inside_ha.
curl "https://terra.example.sa/v1/map/tile?res=8&x=2336&y=1234&clip=1"
The Saudi outline, simplified, for drawing beneath the grid. Land alone by default; zone=territory adds the EEZ as a second feature so the coast can be drawn solid and the sea boundary dashed, and zone=marine returns the EEZ by itself.
curl "https://terra.example.sa/v1/map/ksa.geojson?zone=territory"
Places
Find a province or governorate by name, in Arabic or English, and get the bounding box a map needs to frame it.
id is the same code the administrative endpoints use, so a result can be applied straight back as a map filter.
A place whose source archive holds no boundary is left out rather than returned without a box.
curl "https://terra.example.sa/v1/places?q=makkah&kind=governorate&limit=5"
The outline itself, as a GeoJSON Feature — the half of the pair POST /v1/polyfill was missing,
since it turns a polygon into cells and a caller asking for the cells of a province had to already hold the province.
Rings are the source rings: rounded to the requested precision, never simplified.
curl "https://terra.example.sa/v1/places/province/07/geometry?precision=5"
Administrative regions
The 13 provinces or the 149 governorates, with both names and the province each governorate belongs to. The relation is verified geometrically rather than trusted from the attribute table.
curl "https://terra.example.sa/v1/admin/regions?level=governorate"
The administrative context of a cell, aggregated over its Res 8 descendants: the primary region, a purity share, the unassigned share for ground in no unit at all, and the full mix. A distribution, never a bare id.
curl https://terra.example.sa/v1/cell/t10444b01fffffff8/admin
The province and governorate ids for a cell and nothing else. Padded text keys — "02", "0207" — so the response drops straight into a foreign key column with no mapping step.
curl https://terra.example.sa/v1/cell/t10854284ea9ffff8/ids
The same lookup for up to 10,000 cells or points at once. A bad cell is reported in its own row rather than failing the batch, so one corrupt record does not reject 9,999 good ones.
curl -X POST https://terra.example.sa/v1/cells/ids \
-H "Content-Type: application/json" \
-d '{"cells": ["t10854284ea9ffff8", "t108858156b1ffff8"]}'
Bulk cell → region with names, shaped like POST /v1/index so the same client code fits. Accepts cells or raw points.
curl -X POST https://terra.example.sa/v1/admin/lookup \
-H "Content-Type: application/json" \
-d '{"res": 8, "points": [{"id": "ORD-1", "lat": 24.68, "lon": 46.72}]}'
Version and size of the downloadable assignment table. Check this first: if admin_version matches what you stored last time, the boundaries have not moved and there is nothing to do — which is the normal case.
curl https://terra.example.sa/v1/admin/cover/manifest
One page of the cover. Rows are arrays rather than objects, because the keys would otherwise be two thirds of the payload repeated two million times. cell_id is a signed 64-bit integer and exceeds Number.MAX_SAFE_INTEGER — a JavaScript client must not parse these.
curl "https://terra.example.sa/v1/admin/cover?page=0"
The table, the ancestor function and the statement that uses them, as SQL you can run as-is. Turns a per-row API call into one indexed join in your own database.
curl https://terra.example.sa/v1/admin/cover/schema.sql
Borders
Is a coordinate inside the Kingdom, and if so on land or at sea? The check the grid itself does not do: the grid extent is a rectangle covering the Kingdom plus a GCC buffer, so Doha, Kuwait City and Amman all index without error.
curl "https://terra.example.sa/v1/in-ksa?lat=24.6877&lon=46.7219"