API and agentsAPI reference
Operations
Spatial and data operations. Each produces a durable dataset with recorded provenance; the catalog describes the verbs this instance offers.
8 operations on 5 paths.
/api/operations
GETList the operations this instance offers
Sign-in Session cookie or Bearer tokenMCP tool list_operations
The instance-wide operation catalog, shared by every authenticated account: each verb's id, group, the input geometry it accepts, and its parameters. Read this to discover what may be passed to the run endpoint.
Responses
200
Success.
application/json401403503default
Error with a machine-readable code and human message.
application/json405
method_not_allowed: the method is unsupported for this path.
application/jsonAllowHeaderExactly the documented methods for this path.
stringalways
GET, HEAD, OPTIONS
HEADRead response headers
Sign-in Session cookie or Bearer tokenAnswers 200, 401, 403, 405, 503, defaultAllow
GET, HEAD, OPTIONSAutomatic HEAD uses GET with no response body.
Also on this path: OPTIONS under System.
/api/operations/run
POSTRun an operation
Sign-in Session cookie or Bearer tokenMCP tool run_operation
At most 16,777,216 wire bytes; a larger body is refused with request_body_too_large before JSON parsing. Created resources belong to the authenticated account. Submitted owner identities cannot assign or transfer ownership. Standalone run records and subject histories are private to their initiating account, including for administrators. Standalone jobs retain their initiating owner before any output exists, after failure and after output deletion; contained jobs follow their workflow, read by everyone who reaches it and cancelled by their initiator or the workflow's owner. Unreached and missing run identities return not_found before cancellation or private content reads. Subject grouping, history pruning and output-name conflicts are account-local. Workers recheck account activity before preparation and at publication; an inactive owner's unfinished job fails with authentication_required and keeps no new output, and an input another account owns that is no longer within the runner's reach when the output commits refuses it with sql_error naming the input as written. Accepts one operation and answers 202 with a run, before the work is done; poll the run's own resource for its outcome. An accepted run outlives the request that started it. Closing the connection does not stop it.
What is refused here, and what is reported on the run, is a fixed line. Refused immediately, minting no run: a malformed body, an unknown operation, SQL that is not an accepted read-only SELECT, an output name already taken, and a full queue. Reported on the run instead: SQL that parses but fails to bind or execute, a name taken between acceptance and commit, the engine memory budget, the execution budget, and a server stopped mid-run.
Set dryRun to ask what the operation would produce without writing anything; a dry run is synchronous and mints no run.
A parameter that names a dataset takes the caller's own dataset by its bare name, and another person's dataset the caller reaches by its qualified name, <sql name>.<name>; a dataset out of reach is refused exactly as one that does not exist.
Give writtenIn when the parameters were written in a map's home or a workflow (a result previewed there and saved as a dataset, a tool previewing a layer's SQL): they are carried into the caller's own console, where a run reads its names, and the output is the caller's own dataset either way. Each dataset reference keeps the dataset it meant where it was written: a plain name of a dataset the destination's SQL home does not own, or whose name an output there takes, becomes <sql name>.<dataset>; an already qualified name stays as written; a workflow's own output becomes the dataset the caller's latest successful run of it made. Only those references change; the rest of the text is kept as written, and nothing where it came from is touched. A reference that cannot be carried (a dataset outside the caller's reach, an output the caller has not produced, a computed table name that would have to change) refuses the request with sql_error naming it, and nothing is written.
Only one read-only SELECT over named datasets is accepted. File readers, file-relation shorthand and engine path or definition discovery are refused before binding with sql_rejected, including nested SQL and computed targets. File-referencing PROJ coordinate definitions are also refused before native projection use, including computed or per-row values; EPSG identifiers and inline definitions without files remain supported. Unknown tables receive the same sql_error whether hidden or nonexistent, without catalogue suggestions. Engine errors do not expose filesystem paths or internal statements; input positions are retained when available. Existing saved SQL is retained unchanged; affected saved and published queries fail. sql_step keeps the result of a read-only SELECT as a dataset: the escape hatch inside any recipe, and the way to save a query you already trust. A result with no geometry is an ordinary dataset, not a failure.
Measurements are ground metres. A buffer's radius and a measured length are metres on the earth, at the latitude the data occupies, never degrees or metres on a map projection. They are measured in a transverse Mercator centred on the data's own extent, every input counted, and the output's provenance records it. Data too wide for that to hold within 1 % everywhere, or crossing the antimeridian, is refused for a distance with measurement_crs_unavailable, naming its width and extent; an area over the same data succeeds, because every area is measured in a global equal-area projection. An input whose coordinate system was assumed rather than declared is measured anyway and the answer says so, on the dry run, on the accepted run, and on the output.
Request body
At most 16,777,216 bytes (16 MiB); a larger body is refused with request_body_too_large.
application/json
object
operationstringrequiredAn operation id from the catalog.
parametersobjectrequiredThe operation's own parameters, as the catalog describes them.
subjectstringGroups this run with others in history, so 'when did this last succeed' has an answer across re-runs. Omitted, the run is its own subject.
dryRunbooleanReport what the run would produce and write nothing.
writtenInWrittenInWhere
parameterswere written, when not the caller's own console; they are carried into it.
Responses
200
What the run would produce; nothing written.
application/json202
Accepted; poll the run for its outcome.
application/json401403404413503default
Error with a machine-readable code and human message.
application/json405
method_not_allowed: the method is unsupported for this path.
application/jsonAllowHeaderExactly the documented methods for this path.
stringalways
OPTIONS, POST
Example
Save a query's result as the dataset big_cities
Needs a token and the dataset world_cities. The run is accepted at once and writes big_cities when it finishes; read its outcome from the run.
curl
curl -s http://localhost:3000/api/operations/run \ -H "Authorization: Bearer <YOUR_TOKEN>" \ -H "Content-Type: application/json" \ -d '{"operation": "sql_step", "parameters": {"sql": "SELECT name, country, population, geometry FROM world_cities WHERE population > 10000000", "name": "big_cities"}}'JavaScript
const response = await fetch("http://localhost:3000/api/operations/run", { method: "POST", headers: { Authorization: "Bearer <YOUR_TOKEN>", "Content-Type": "application/json", }, body: JSON.stringify({ operation: "sql_step", parameters: { sql: "SELECT name, country, population, geometry FROM world_cities WHERE population > 10000000", name: "big_cities", }, }),});console.log(JSON.stringify(await response.json(), null, 2));Answers 202 application/json
{ "run": { "id": "e4a7c2b9-1f3d-4e6a-9c85-7b0d2f4a6e13", "operation": "sql_step", "state": "queued", "subject": { "kind": "run", "id": "e4a7c2b9-1f3d-4e6a-9c85-7b0d2f4a6e13" }, "parameters": { "sql": "SELECT name, country, population, geometry FROM world_cities WHERE population > 10000000", "name": "big_cities" }, "acceptedAt": "2026-10-20T09:00:01.494Z" }}Also on this path: OPTIONS under System.
/api/operations/runs
GETList operation runs
Sign-in Session cookie or Bearer tokenMCP tool list_operation_runs
Standalone run records and subject histories are private to their initiating account, including for administrators. Standalone jobs retain their initiating owner before any output exists, after failure and after output deletion; contained jobs follow their workflow, read by everyone who reaches it and cancelled by their initiator or the workflow's owner. Unreached and missing run identities return not_found before cancellation or private content reads. Subject grouping, history pruning and output-name conflicts are account-local. Workers recheck account activity before preparation and at publication; an inactive owner's unfinished job fails with authentication_required and keeps no new output, and an input another account owns that is no longer within the runner's reach when the output commits refuses it with sql_error naming the input as written. Run history, newest first. Narrow to one subject to answer 'when did this last succeed'. A failed run never erases the successful one before it, so both are kept. History is bounded per subject, and a subject's most recent success is preserved even when the depth would otherwise drop it.
Parameters
subjectQueryOnly runs sharing this subject identity.
string
limitQueryMost runs to return; newest first.
integer
Responses
200
Success.
application/json401403404503default
Error with a machine-readable code and human message.
application/json405
method_not_allowed: the method is unsupported for this path.
application/jsonAllowHeaderExactly the documented methods for this path.
stringalways
GET, HEAD, OPTIONS
HEADRead response headers
Sign-in Session cookie or Bearer tokenAnswers 200, 401, 403, 404, 405, 503, defaultAllow
GET, HEAD, OPTIONSAutomatic HEAD uses GET with no response body.
Also on this path: OPTIONS under System.
/api/operations/runs/{id}
GETRead an operation run
Sign-in Session cookie or Bearer tokenMCP tool get_operation_run
Standalone run records and subject histories are private to their initiating account, including for administrators. Standalone jobs retain their initiating owner before any output exists, after failure and after output deletion; contained jobs follow their workflow, read by everyone who reaches it and cancelled by their initiator or the workflow's owner. Unreached and missing run identities return not_found before cancellation or private content reads. Subject grouping, history pruning and output-name conflicts are account-local. Workers recheck account activity before preparation and at publication; an inactive owner's unfinished job fails with authentication_required and keeps no new output, and an input another account owns that is no longer within the runner's reach when the output commits refuses it with sql_error naming the input as written. What a caller polls after the run endpoint accepted their operation. A succeeded run names its output dataset; a failed one carries a coded error. There is no completion percentage: a run reports when it started, and elapsed time follows from that.
Parameters
idPathrequiredRun id.
string
Responses
200
Success.
application/json401403404503default
Error with a machine-readable code and human message.
application/json405
method_not_allowed: the method is unsupported for this path.
application/jsonAllowHeaderExactly the documented methods for this path.
stringalways
GET, HEAD, OPTIONS
Example
Read the run that saved big_cities, once it finished
Needs a token and the run saving big_cities started. Until it finishes, its state is queued, then running: read it again until it is succeeded, failed or cancelled. A succeeded run names its dataset under output.
curl
curl -s http://localhost:3000/api/operations/runs/e4a7c2b9-1f3d-4e6a-9c85-7b0d2f4a6e13 \ -H "Authorization: Bearer <YOUR_TOKEN>"JavaScript
const response = await fetch("http://localhost:3000/api/operations/runs/e4a7c2b9-1f3d-4e6a-9c85-7b0d2f4a6e13", { headers: { Authorization: "Bearer <YOUR_TOKEN>" },});console.log(JSON.stringify(await response.json(), null, 2));Answers 200 application/json
{ "run": { "id": "e4a7c2b9-1f3d-4e6a-9c85-7b0d2f4a6e13", "operation": "sql_step", "state": "succeeded", "subject": { "kind": "run", "id": "e4a7c2b9-1f3d-4e6a-9c85-7b0d2f4a6e13" }, "parameters": { "sql": "SELECT name, country, population, geometry FROM world_cities WHERE population > 10000000", "name": "big_cities" }, "acceptedAt": "2026-10-20T09:00:01.494Z", "startedAt": "2026-10-20T09:00:01.495Z", "finishedAt": "2026-10-20T09:00:01.503Z", "output": { "id": "c2e8f4a1-6b3d-4f97-a5c0-1d2e3f4a5b6c", "name": "big_cities" } }}HEADRead response headers
Sign-in Session cookie or Bearer tokenAnswers 200, 401, 403, 404, 405, 503, defaultAllow
GET, HEAD, OPTIONSAutomatic HEAD uses GET with no response body.
Also on this path: OPTIONS under System.
/api/operations/runs/{id}/cancel
POSTCancel an operation run
Sign-in Session cookie or Bearer tokenMCP tool cancel_operation_run
Standalone run records and subject histories are private to their initiating account, including for administrators. Standalone jobs retain their initiating owner before any output exists, after failure and after output deletion; contained jobs follow their workflow, read by everyone who reaches it and cancelled by their initiator or the workflow's owner. Unreached and missing run identities return not_found before cancellation or private content reads. Subject grouping, history pruning and output-name conflicts are account-local. Workers recheck account activity before preparation and at publication; an inactive owner's unfinished job fails with authentication_required and keeps no new output, and an input another account owns that is no longer within the runner's reach when the output commits refuses it with sql_error naming the input as written. Stops a run for real: a queued one never starts, and a running one is interrupted in the engine rather than only in the record. A cancelled run leaves no dataset and no stranded file behind. Cancelling a run that has already finished is not an error. It answers the run unchanged, because 'make sure this is not running' is already true.
Parameters
idPathrequiredRun id.
string
Responses
200
Success.
application/json401403404503default
Error with a machine-readable code and human message.
application/json405
method_not_allowed: the method is unsupported for this path.
application/jsonAllowHeaderExactly the documented methods for this path.
stringalways
OPTIONS, POST
Also on this path: OPTIONS under System.
7439201b