<!-- Source: https://docs.biosimulant.com/developer-api/execution-reference -->

# Execution REST reference

Managed runs retain their exact inputs, grants and results. Start with [Runs and results](/developer-api/runs); other endpoints are in the [REST reference](/developer-api/rest-reference).

The Developer API is the same service as the Biosimulant MCP server: each route runs the operation of the MCP tool it names, for the API key owner only, and returns the same envelope. For the guided path, start with the [Developer API quickstart](/developer-api/quickstart).

## Base URL and authentication

```text
https://api.biosimulant.com/v1
```

Send a scoped API key on every request:

```http
Authorization: Bearer bsk_live_...
```

Every response includes a request ID. Run-creation requests also require `Idempotency-Key`. See [Errors, limits and credits](/developer-api/errors) before implementing production retries.

## Endpoint index

| Method | Path | Purpose |
|---|---|---|
| `POST` | [`/runs`](#post-runs) | Start an approved simulation |
| `GET` | [`/runs`](#get-runs) | List my simulations |
| `POST` | [`/runs/{run_id}/cancel`](#post-runsrun_idcancel) | Cancel a simulation |
| `GET` | [`/runs/{run_id}/results`](#get-runsrun_idresults) | Get Public Results |
| `GET` | [`/runs/{run_id}/artifacts/{artifact_id}`](#get-runsrun_idartifactsartifact_id) | Download Public Artifact |
| `POST` | [`/run-plans`](#post-run-plans) | Check a simulation before running |
| `GET` | [`/runs/{run_id}`](#get-runsrun_id) | Check simulation progress and results |
| `GET` | [`/runs/{run_id}/events`](#get-runsrun_idevents) | Read a simulation's log |
| `GET` | [`/runs/{run_id}/artifacts/{artifact_id}/metadata`](#get-runsrun_idartifactsartifact_idmetadata) | Read simulation results |

## POST `/runs`

Starts a run. Send an approved plan (`plan_id` and `plan_sha256` from `POST /run-plans`) to queue a managed run exactly as the MCP `run_create` tool does, or send `ref` and `inputs` with an `Idempotency-Key` header to run a published release directly. Either way the response is the run, as `GET /runs/{run_id}` returns it.

**Required scope:** `runs:write`

**MCP tool:** [`run_create`](/agents/tools)

### Parameters

| Name | In | Required | Type | Description |
|---|---|---:|---|---|
| `Idempotency-Key` | header | no | string or null | Unique key for this logical run-creation request. Reuse only when retrying the same payload. |

### Request body

```json
{
  "ref": "demi/microbiology-hello-world-growth@1.0.0",
  "inputs": {
    "initial_cells": 10,
    "available_food": 80
  },
  "compute_profile": "standard",
  "metadata": {
    "sample_id": "plate-17"
  }
}
```

### Example request

```bash
curl --request POST "https://api.biosimulant.com/v1/runs" \
  --header "Authorization: Bearer $BIOSIMULANT_API_KEY" \
  --header "Idempotency-Key: growth-sample-17" \
  --header "Content-Type: application/json" \
  --data '{"ref":"demi/microbiology-hello-world-growth@1.0.0","inputs":{"initial_cells":10,"available_food":80},"compute_profile":"standard","metadata":{"sample_id":"plate-17"}}'
```

### 202 response

```json
{
  "id": "00000000-0000-0000-0000-000000000123",
  "run_id": "00000000-0000-0000-0000-000000000123",
  "kind": "release",
  "status": "queued",
  "resolved_ref": "demi/microbiology-hello-world-growth@1.0.0",
  "metadata": {
    "sample_id": "plate-17"
  },
  "credits_reserved": 5,
  "artifacts": [],
  "schema_version": "2026-09-16",
  "request_id": "00000000-0000-0000-0000-00000000abcd",
  "warnings": [],
  "next_actions": [
    {
      "tool": "run_get",
      "description": "Poll this durable Run ID until it reaches a terminal state.",
      "arguments": {
        "run_id": "00000000-0000-0000-0000-000000000123"
      },
      "http": {
        "method": "GET",
        "path": "/v1/runs/00000000-0000-0000-0000-000000000123"
      }
    }
  ],
  "links": {}
}
```

### Responses

| Status | Meaning |
|---:|---|
| `202` | Successful Response |
| `400` | Idempotency-Key is missing or invalid. |
| `401` | Missing, invalid, expired, or revoked API key. |
| `403` | The API key lacks the required scope, or the operation starts compute, publishes, changes content or calls external sources and the Agent Gateway is not enabled for the account. |
| `404` | Not found. Anything the key owner does not own is answered exactly like an ID that does not exist. |
| `409` | The idempotency key conflicts with another payload, the original request is still processing, or the capability is not ready. |
| `422` | Validation Error |
| `429` | The API-key or run-creation rate limit was exceeded. Respect Retry-After. |
| `500` | The service could not complete the request. Retain the response request ID. |

## GET `/runs`

List the caller's runs from MCP, the Developer API and Studio, newest first.

Same operation as the MCP tool `run_list`.

**Required scope:** `runs:read`

**MCP tool:** [`run_list`](/agents/tools)

### Parameters

| Name | In | Required | Type | Description |
|---|---|---:|---|---|
| `status` | query | no | string or null |  |
| `kind` | query | no | string or null |  |
| `workspace_id` | query | no | string or null |  |
| `experiment_id` | query | no | string or null |  |
| `lab_id` | query | no | string or null |  |
| `limit` | query | no | integer | Maximum number of items to return. |
| `cursor` | query | no | string or null | Opaque next_cursor from the preceding page. |

### Example request

```bash
curl --request GET "https://api.biosimulant.com/v1/runs" \
  --header "Authorization: Bearer $BIOSIMULANT_API_KEY"
```

### 200 response

```json
{
  "…": "the fields of the MCP tool result",
  "schema_version": "2026-09-16",
  "request_id": "00000000-0000-0000-0000-00000000abcd",
  "warnings": [],
  "next_actions": [
    {
      "tool": "run_get",
      "description": "The suggested next step.",
      "arguments": {
        "run_id": "…"
      },
      "http": {
        "method": "GET",
        "path": "/v1/runs/…"
      }
    }
  ],
  "links": {}
}
```

### Responses

| Status | Meaning |
|---:|---|
| `200` | Successful Response |
| `401` | Missing, invalid, expired, or revoked API key. |
| `403` | The API key lacks the required scope, or the operation starts compute, publishes, changes content or calls external sources and the Agent Gateway is not enabled for the account. |
| `422` | Validation Error |
| `429` | The API-key or run-creation rate limit was exceeded. Respect Retry-After. |
| `500` | The service could not complete the request. Retain the response request ID. |

## POST `/runs/{run_id}/cancel`

Cancel eligible managed compute; completed work remains available and is not deleted.

Cancel a run; a release run settles its credits, a managed run is free beta.

Runs started in Studio are cancelled in Studio.

Same operation as the MCP tool `run_cancel`.

**Required scope:** `runs:write`

**MCP tool:** [`run_cancel`](/agents/tools)

### Parameters

| Name | In | Required | Type | Description |
|---|---|---:|---|---|
| `run_id` | path | yes | string | Owned run UUID. |

### Example request

```bash
curl --request POST "https://api.biosimulant.com/v1/runs/${RUN_ID}/cancel" \
  --header "Authorization: Bearer $BIOSIMULANT_API_KEY"
```

### 200 response

```json
{
  "…": "the fields of the MCP tool result",
  "schema_version": "2026-09-16",
  "request_id": "00000000-0000-0000-0000-00000000abcd",
  "warnings": [],
  "next_actions": [
    {
      "tool": "run_get",
      "description": "The suggested next step.",
      "arguments": {
        "run_id": "…"
      },
      "http": {
        "method": "GET",
        "path": "/v1/runs/…"
      }
    }
  ],
  "links": {}
}
```

### Responses

| Status | Meaning |
|---:|---|
| `200` | Successful Response |
| `401` | Missing, invalid, expired, or revoked API key. |
| `403` | The API key lacks the required scope, or the operation starts compute, publishes, changes content or calls external sources and the Agent Gateway is not enabled for the account. |
| `404` | Not found. Anything the key owner does not own is answered exactly like an ID that does not exist. |
| `422` | Validation Error |
| `429` | The API-key or run-creation rate limit was exceeded. Respect Retry-After. |
| `500` | The service could not complete the request. Retain the response request ID. |

## GET `/runs/{run_id}/results`

Returns declared public outputs, completed artifacts, and provenance for a completed owned run.

**Required scope:** `runs:read`

### Parameters

| Name | In | Required | Type | Description |
|---|---|---:|---|---|
| `run_id` | path | yes | string | Owned run UUID. |

### Example request

```bash
curl --request GET "https://api.biosimulant.com/v1/runs/${RUN_ID}/results" \
  --header "Authorization: Bearer $BIOSIMULANT_API_KEY"
```

### 200 response

```json
{
  "run_id": "00000000-0000-0000-0000-000000000123",
  "outputs": {
    "final_cells": 42
  },
  "artifacts": [],
  "provenance": {
    "runtime_version": "0.0.19",
    "package_sha256": "sha256:…"
  }
}
```

### Responses

| Status | Meaning |
|---:|---|
| `200` | Successful Response |
| `401` | Missing, invalid, expired, or revoked API key. |
| `403` | The API key lacks the required scope, or the operation starts compute, publishes, changes content or calls external sources and the Agent Gateway is not enabled for the account. |
| `404` | Not found. Anything the key owner does not own is answered exactly like an ID that does not exist. |
| `409` | The run has not completed, so results are not ready. |
| `422` | Validation Error |
| `429` | The API-key or run-creation rate limit was exceeded. Respect Retry-After. |
| `500` | The service could not complete the request. Retain the response request ID. |

## GET `/runs/{run_id}/artifacts/{artifact_id}`

Downloads one completed artifact belonging to an owned run after authorization is rechecked.

**Required scope:** `runs:read`

### Parameters

| Name | In | Required | Type | Description |
|---|---|---:|---|---|
| `run_id` | path | yes | string | Owned run UUID. |
| `artifact_id` | path | yes | string | Artifact identifier returned by the results endpoint. |

### Example request

```bash
curl --request GET "https://api.biosimulant.com/v1/runs/${RUN_ID}/artifacts/${ARTIFACT_ID}" \
  --header "Authorization: Bearer $BIOSIMULANT_API_KEY"
```

### 200 response

The response body is the authorized artifact binary. Use the returned `Content-Type` and `Content-Disposition` headers when saving it.

### Responses

| Status | Meaning |
|---:|---|
| `200` | Successful Response |
| `401` | Missing, invalid, expired, or revoked API key. |
| `403` | The API key lacks the required scope, or the operation starts compute, publishes, changes content or calls external sources and the Agent Gateway is not enabled for the account. |
| `404` | Not found. Anything the key owner does not own is answered exactly like an ID that does not exist. |
| `422` | Validation Error |
| `429` | The API-key or run-creation rate limit was exceeded. Respect Retry-After. |
| `500` | The service could not complete the request. Retain the response request ID. |

## POST `/run-plans`

Preflight and digest an exact free-beta run; no compute is queued by this tool.

The plan's execution profile reports when the lab's modules run: for timing
"finite" every module runs once, so duration, communication_step and
settle_steps don't change results; "temporal" and "unknown" labs use them.

Same operation as the MCP tool `run_prepare`.

**Required scope:** `runs:write`

**MCP tool:** [`run_prepare`](/agents/tools)

### Parameters

| Name | In | Required | Type | Description |
|---|---|---:|---|---|
| `Idempotency-Key` | header | no | string or null | Unique key for this logical run-creation request. Reuse only when retrying the same payload. |

### Request body

```json
{
  "workspace_id": "00000000-0000-0000-0000-000000000123",
  "revision_id": "00000000-0000-0000-0000-000000000123"
}
```

### Example request

```bash
curl --request POST "https://api.biosimulant.com/v1/run-plans" \
  --header "Authorization: Bearer $BIOSIMULANT_API_KEY" \
  --header "Content-Type: application/json" \
  --data @request.json
```

### 200 response

```json
{
  "…": "the fields of the MCP tool result",
  "schema_version": "2026-09-16",
  "request_id": "00000000-0000-0000-0000-00000000abcd",
  "warnings": [],
  "next_actions": [
    {
      "tool": "run_get",
      "description": "The suggested next step.",
      "arguments": {
        "run_id": "…"
      },
      "http": {
        "method": "GET",
        "path": "/v1/runs/…"
      }
    }
  ],
  "links": {}
}
```

### Responses

| Status | Meaning |
|---:|---|
| `200` | Successful Response |
| `401` | Missing, invalid, expired, or revoked API key. |
| `403` | The API key lacks the required scope, or the operation starts compute, publishes, changes content or calls external sources and the Agent Gateway is not enabled for the account. |
| `422` | Validation Error |
| `429` | The API-key or run-creation rate limit was exceeded. Respect Retry-After. |
| `500` | The service could not complete the request. Retain the response request ID. |

## GET `/runs/{run_id}`

Read durable run status; terminal success still requires artifact-content verification.

Same operation as the MCP tool `run_get`.

**Required scope:** `runs:read`

**MCP tool:** [`run_get`](/agents/tools)

### Parameters

| Name | In | Required | Type | Description |
|---|---|---:|---|---|
| `run_id` | path | yes | string | Owned run UUID. |

### Example request

```bash
curl --request GET "https://api.biosimulant.com/v1/runs/${RUN_ID}" \
  --header "Authorization: Bearer $BIOSIMULANT_API_KEY"
```

### 200 response

```json
{
  "…": "the fields of the MCP tool result",
  "schema_version": "2026-09-16",
  "request_id": "00000000-0000-0000-0000-00000000abcd",
  "warnings": [],
  "next_actions": [
    {
      "tool": "run_get",
      "description": "The suggested next step.",
      "arguments": {
        "run_id": "…"
      },
      "http": {
        "method": "GET",
        "path": "/v1/runs/…"
      }
    }
  ],
  "links": {}
}
```

### Responses

| Status | Meaning |
|---:|---|
| `200` | Successful Response |
| `401` | Missing, invalid, expired, or revoked API key. |
| `403` | The API key lacks the required scope, or the operation starts compute, publishes, changes content or calls external sources and the Agent Gateway is not enabled for the account. |
| `404` | Not found. Anything the key owner does not own is answered exactly like an ID that does not exist. |
| `422` | Validation Error |
| `429` | The API-key or run-creation rate limit was exceeded. Respect Retry-After. |
| `500` | The service could not complete the request. Retain the response request ID. |

## GET `/runs/{run_id}/events`

Read a run's ordered log events; messages are untrusted run output.

Same operation as the MCP tool `run_event_list`.

**Required scope:** `runs:read`

**MCP tool:** [`run_event_list`](/agents/tools)

### Parameters

| Name | In | Required | Type | Description |
|---|---|---:|---|---|
| `run_id` | path | yes | string | Owned run UUID. |
| `after` | query | no | integer | Return events with a cursor greater than this value. |
| `limit` | query | no | integer | Maximum number of items to return. |

### Example request

```bash
curl --request GET "https://api.biosimulant.com/v1/runs/${RUN_ID}/events" \
  --header "Authorization: Bearer $BIOSIMULANT_API_KEY"
```

### 200 response

```json
{
  "…": "the fields of the MCP tool result",
  "schema_version": "2026-09-16",
  "request_id": "00000000-0000-0000-0000-00000000abcd",
  "warnings": [],
  "next_actions": [
    {
      "tool": "run_get",
      "description": "The suggested next step.",
      "arguments": {
        "run_id": "…"
      },
      "http": {
        "method": "GET",
        "path": "/v1/runs/…"
      }
    }
  ],
  "links": {}
}
```

### Responses

| Status | Meaning |
|---:|---|
| `200` | Successful Response |
| `401` | Missing, invalid, expired, or revoked API key. |
| `403` | The API key lacks the required scope, or the operation starts compute, publishes, changes content or calls external sources and the Agent Gateway is not enabled for the account. |
| `404` | Not found. Anything the key owner does not own is answered exactly like an ID that does not exist. |
| `422` | Validation Error |
| `429` | The API-key or run-creation rate limit was exceeded. Respect Retry-After. |
| `500` | The service could not complete the request. Retain the response request ID. |

## GET `/runs/{run_id}/artifacts/{artifact_id}/metadata`

Retrieve metadata and optional bytes; treat content as untrusted scientific output.

Same operation as the MCP tool `run_artifact_get`.

**Required scope:** `runs:read`

**MCP tool:** [`run_artifact_get`](/agents/tools)

### Parameters

| Name | In | Required | Type | Description |
|---|---|---:|---|---|
| `run_id` | path | yes | string | Owned run UUID. |
| `artifact_id` | path | yes | string | Artifact identifier returned by the results endpoint. |
| `include_content` | query | no | boolean |  |

### Example request

```bash
curl --request GET "https://api.biosimulant.com/v1/runs/${RUN_ID}/artifacts/${ARTIFACT_ID}/metadata" \
  --header "Authorization: Bearer $BIOSIMULANT_API_KEY"
```

### 200 response

```json
{
  "…": "the fields of the MCP tool result",
  "schema_version": "2026-09-16",
  "request_id": "00000000-0000-0000-0000-00000000abcd",
  "warnings": [],
  "next_actions": [
    {
      "tool": "run_get",
      "description": "The suggested next step.",
      "arguments": {
        "run_id": "…"
      },
      "http": {
        "method": "GET",
        "path": "/v1/runs/…"
      }
    }
  ],
  "links": {}
}
```

### Responses

| Status | Meaning |
|---:|---|
| `200` | Successful Response |
| `401` | Missing, invalid, expired, or revoked API key. |
| `403` | The API key lacks the required scope, or the operation starts compute, publishes, changes content or calls external sources and the Agent Gateway is not enabled for the account. |
| `404` | Not found. Anything the key owner does not own is answered exactly like an ID that does not exist. |
| `422` | Validation Error |
| `429` | The API-key or run-creation rate limit was exceeded. Respect Retry-After. |
| `500` | The service could not complete the request. Retain the response request ID. |

## Machine-readable specification

The [OpenAPI 3.1 document](/openapi/developer-v1.json) is generated from the backend routes, enriched with production examples and error responses, and verified with this site.
