# HTTP API

URL: https://docs.domainruntime.dev/docs/platform/admin-http-api
Status: Verified
Reviewed: 2026-09-22



Each environment answers at `https://<handle>.domainruntime.cloud`. Use this API from languages without an SDK, from scripts, or to debug. Authenticate every request with a bearer: a [user token](/docs/auth/users) acts as that user; your organization's [service key](/docs/auth/service-keys) acts as an administrator.

```bash
export ENV=https://dev-orders-alice-7f3k9x2m.domainruntime.cloud
export TOKEN=...
```

## Run an action [#run-an-action]

```bash
curl -X POST "$ENV/actions/orders.place/invoke" \
  -H "authorization: Bearer $TOKEN" -H "content-type: application/json" \
  -d '{"requestId": "3f0c1b2e-8a4d-4c1e-9b2a-5d6e7f8a9b0c", "input": {"orderId": "…", "total": 10}}'
```

* An input that does not fit the action's schema answers `400 action_contract_validation_failed` with `details.issues`: `[{ "where": "input.total", "code": "type", "message": "…" }]`.
* `requestId` must be a UUID. The same id returns the first execution instead of running the action again; reusing it with other input answers `REQUEST_CONFLICT`.
* The call waits up to 110 s and answers `200` with `{ kind, execution, uploads, statusUrl }`. The output is `execution.output`.
* A failed action is also `200`, with `execution.status: "failed"`, `execution.errorCode` (`action_failed`) and your message.
* A workflow answers `202` with its `runId` as soon as the run is admitted.
* The body is limited to 8 MiB; files go through file inputs.

`GET /actions/{name}/contract` returns the action's input and output schemas, its contract hash and the file limits.

## Follow an execution [#follow-an-execution]

|                                        |                                                                       |
| -------------------------------------- | --------------------------------------------------------------------- |
| `GET /executions`                      | your executions, paged                                                |
| `GET /executions/{id}`                 | status, output, error code and message, uploads                       |
| `GET /executions/{id}/result`          | waits up to 110 s for the result, then `504 execution_result_timeout` |
| `GET /executions/requests/{requestId}` | find an execution by your request id                                  |
| `GET /runs/{id}`                       | a workflow run                                                        |

## Query [#query]

```bash
curl -X POST "$ENV/query" \
  -H "authorization: Bearer $TOKEN" -H "content-type: application/json" \
  -d '{"query": {"orders_order": {"$": {"limit": 5}}}}'
```

The response is the Instant triple format (`result[].data.datalog-result.join-rows` plus `attrs`), what the SDKs read. `POST /query?format=objects` answers the result as nested objects instead (`{ "orders_order": [{ "id": …, … }] }`), for the same caller and under the same rules. The body is limited to 4 MiB. A rejected query answers `{ "ok": false, "error": "data_provider_rejected" }` with the engine's status.

## Files [#files]

|                                               |                                                                  |
| --------------------------------------------- | ---------------------------------------------------------------- |
| `PUT /storage/upload`                         | upload; headers `path` and `content-type`, body is the file      |
| `POST /storage/signed-upload-url`             | a URL to upload directly from a browser (JSON body, up to 1 MiB) |
| `GET /storage/signed-download-url?filename=…` | a URL to download                                                |
| `DELETE /storage/files?filename=…`            | delete                                                           |

## Live queries [#live-queries]

`GET /session` upgrades to a WebSocket that speaks the Instant real-time protocol for reading: `init`, `add-query`, `remove-query`, `subscribe-stream`. Writes are not accepted on this socket. Use an SDK rather than implementing it by hand.

## Errors [#errors]

Runtime errors are JSON with a stable code: `{ "ok": false, "error": "execution_not_found" }`. Action invocation errors also carry `executionId` and `requestId`. See [Errors](/docs/reference/errors).
