# Projects and runs API

Create and query the core tracking objects — projects group runs inside an
organization, and runs hold config, tags, notes, metadata, status, and summary
values for metrics and artifacts.

Authenticate with an `Authorization: Bearer instantml_...` API key or a browser
session. Read endpoints need the `export:read` scope, write endpoints need
`sdk:ingest`, and stop endpoints need `runs:control`; per-endpoint notes below
call out the exceptions.

## Create a project

```bash
curl -X POST https://api.instantml.ai/projects \
  -H "Authorization: Bearer instantml_..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "cartpole",
    "description": "Optional project description"
  }'
```

Requires `sdk:ingest` or a writable browser session.

Project-scoped API keys cannot create projects; create projects with an
org-scoped key or browser session.

## List projects

```http
GET /projects
Authorization: Bearer instantml_...
```

Requires `export:read` or a browser session. Project-scoped keys only see
their project.

## Create a run

```http
POST /runs
Authorization: Bearer instantml_...
Content-Type: application/json

{
  "project": "cartpole",
  "name": "ppo-seed-42",
  "config": { "seed": 42, "algorithm": "ppo" },
  "tags": ["ppo", "baseline"],
  "metadata": { "notes": "first pass" }
}
```

Requires `sdk:ingest` or a writable browser session. The project is created
automatically unless the caller uses a project-scoped key for a different
project.

## List runs

```http
GET /runs?project=cartpole&status=finished&q=seed%2042&limit=100
Authorization: Bearer instantml_...
```

Requires `export:read` or a browser session. Filters:

| Parameter | Meaning |
| --- | --- |
| `project` | Project name, omitted or `all` for all projects. |
| `status` | `running`, `finished`, `failed`, omitted, or `all`. |
| `display_status` | Derived display status: `running`, `stopping`, `stopped`, `finished`, or `failed`. |
| `q` | Run search query over run name, project, tags, notes, config, metadata, status, and ID. Bare text is implicit `AND`; fields, uppercase booleans, quoted phrases, field/group exclusion with `-`, grouping, and explicit Rust `re:/.../` regex are supported. Literal negative terms such as `-1` remain text searches. |
| `sort_by` | `created`, `name`, `status`, `duration`, `metric-latest`, or `metric-best`. |
| `metric_key` | Metric used by metric sorts. |
| `limit` | Page size, default 100, max 1,000. |
| `offset` | Offset pagination. |

`display_status` folds stop-request state into the stored status: a running run
with a pending or acknowledged stop request shows as `stopping`, and a finished
or failed run whose stop request completed shows as `stopped`. The same
`display_status` filter also works on `GET /api/overview` and
`GET /api/runs/summary`.

Use `/api/runs/summary` for dashboard-shaped pages with metric summaries.

Search examples:

```text
reward stability
tag:baseline status:finished
name:"long context" -tag:debug
(tag:baseline OR tag:candidate) notes:ablated
re:/seed-(13|14)/
```

Invalid closed search syntax returns HTTP `400` with
`code: "run_search_invalid"`, `field: "q"`, and an optional 1-based
`position`. Deprecated Node compatibility rejects completed regex with
`code: "run_search_regex_unsupported"`.

## Read one run

```http
GET /runs/{run_id}
Authorization: Bearer instantml_...
```

Returns a run summary with metric aggregates and artifact counts used by the
dashboard.

## Update status, tags, and notes

```http
PATCH /runs/{run_id}
Authorization: Bearer instantml_...
Content-Type: application/json

{
  "status": "finished",
  "tags": ["baseline", "reviewed"],
  "notes": "Reward stabilized after step 80."
}
```

Requires `sdk:ingest` or a writable browser session. At least one field is
required. Status must be `running`, `finished`, or `failed`. Empty notes remove
the stored note.

## Fork a run from a checkpoint

```http
POST /api/runs/{run_id}/forks
Authorization: Bearer instantml_...
Content-Type: application/json
Idempotency-Key: instantml-fork-...

{
  "checkpoint_artifact_id": "00000000-0000-0000-0000-000000000000",
  "step": 1000,
  "inherit_config": true,
  "config_overrides": { "learning_rate": 0.0001 },
  "name": "retry-from-step-1000",
  "tags": ["retry", "checkpoint"],
  "notes": "Retry from the stable checkpoint.",
  "metadata": { "sweep": "lr-retry" }
}
```

Forking creates a linked child run record in the same project. It does not
start training, copy metrics, or copy artifacts. `config_overrides` merges on
top of the inherited config, and `metadata` sets the child run's metadata. Use
a stable idempotency key for retries; the Python SDK derives one automatically
in `Api.fork_run(...)`.

The caller needs `export:read` on the source run and `sdk:ingest` to create the
child run.

## Read run lineage

```http
GET /api/runs/{run_id}/lineage
Authorization: Bearer instantml_...
```

Returns a bounded direct lineage graph for the selected run: the run, optional
parent, direct children, optional checkpoint artifact, total child count, and
whether more children exist beyond the current fixed child limit.

## Fetch dashboard summaries

Project overview:

```http
GET /api/overview?project=cartpole&metric_key=eval/return_mean
Authorization: Bearer instantml_...
```

Run summary page:

```http
GET /api/runs/summary?project=cartpole&sort_by=metric-best&metric_key=eval/return_mean&limit=100
Authorization: Bearer instantml_...
```

Both accept the same `project`, `status`, `display_status`, and `q` filters as
`GET /runs`. The summary response includes runs, metric keys, total count,
`next_cursor`, and page info. Pass `next_cursor` back as the `cursor` query
parameter to fetch the next page instead of increasing `limit` without bound.
Set `projection=selection` to get lightweight rows for bulk-selection UIs
instead of full summary rows.

## Compare runs side by side

```http
GET /api/runs/side-by-side?run_ids=run-a,run-b&reference_run_id=run-a&diff_only=true
Authorization: Bearer instantml_...
```

Limits:

- Up to 50 runs.
- Up to 5,000 comparison rows.

The response includes selected runs, reference run ID, comparison rows, and a
`truncated` flag.

## Stop runs

Request a cooperative stop for one run:

```http
POST /api/runs/{run_id}/stop
Authorization: Bearer instantml_...
Content-Type: application/json
Idempotency-Key: optional-stable-key

{
  "reason": "budget exhausted"
}
```

Requires `runs:control` or a writable browser session. `reason` is optional.
The response returns the run's control state:

```json
{
  "run_id": "4d14b2ea-7f49-4c7b-8d38-bb8437b5b029",
  "ok": true,
  "run_control": {
    "stop_state": "requested",
    "display_status": "stopping",
    "stop_requested": true,
    "stop_request_id": "86d2c75c-0c88-4d7c-8711-e461a77d4edc",
    "reason": "budget exhausted"
  },
  "already_requested": false,
  "already_terminal": false
}
```

Stopping is cooperative: the API records the request, and the training process
notices it through the stop signal below. Repeating the call returns
`already_requested: true`; stopping an already finished or failed run returns
`already_terminal: true`.

Stop up to 100 runs in one request:

```http
POST /api/runs/stop
Authorization: Bearer instantml_...
Content-Type: application/json
Idempotency-Key: optional-stable-key

{
  "run_ids": ["uuid-a", "uuid-b"],
  "reason": "sweep cancelled"
}
```

The response returns per-run `results` (each with `run_id`, `ok`, optional
`error`, and the run's `run_control` state) plus the bulk `limit`.

## Poll the stop signal

SDK-side processes poll for pending stop requests:

```http
GET /api/runs/{run_id}/stop-signal
Authorization: Bearer instantml_...
```

Requires an API key with `sdk:ingest`; browser sessions are not accepted.
Response:

```json
{
  "run_id": "4d14b2ea-7f49-4c7b-8d38-bb8437b5b029",
  "run_status": "running",
  "terminal": false,
  "stop_requested": true,
  "poll_after_seconds": 15,
  "stop_request": {
    "stop_request_id": "86d2c75c-0c88-4d7c-8711-e461a77d4edc",
    "requested_at": "2026-05-16T00:00:00Z",
    "acknowledged_at": null
  }
}
```

Wait at least `poll_after_seconds` between polls; the interval is plan-aware
(10-30 seconds). The Python SDK polls this route behind `run.should_stop()` and
`run.raise_if_stop_requested()`.

## Acknowledge a stop

After the process observes the signal, acknowledge and later complete it:

```http
POST /api/runs/{run_id}/stop-ack
Authorization: Bearer instantml_...
Content-Type: application/json

{
  "stop_request_id": "86d2c75c-0c88-4d7c-8711-e461a77d4edc",
  "state": "acknowledged",
  "message": "checkpoint saved, shutting down"
}
```

Requires an API key with `sdk:ingest`; browser sessions are not accepted.
`state` must be `acknowledged` or `completed`; the optional `message` is stored
as the completion message. The response returns the updated `run_control`
state. A `stop_request_id` that does not match the pending request returns
`409`.

## Write console logs

```http
POST /api/runs/{run_id}/logs
Authorization: Bearer instantml_...
Content-Type: application/json
Idempotency-Key: optional-event-id

{
  "stream": "stdout",
  "lines": [
    { "line_number": 0, "message": "epoch 1 started", "timestamp": "2026-05-16T00:00:00Z" }
  ]
}
```

Requires `sdk:ingest` or a writable browser session. `stream` is `stdout`
(default) or `stderr`. Each line needs `line_number` and `message`;
`timestamp` is optional. Batches cap at 50 lines and messages at 16 KiB.
Response:

```json
{ "inserted": 1 }
```

## Read console logs

```http
GET /api/runs/{run_id}/logs?stream=stdout&limit=250&q=error
Authorization: Bearer instantml_...
```

Requires `export:read` or a browser session. Query parameters:

| Parameter | Meaning |
| --- | --- |
| `stream` | `stdout` or `stderr`. |
| `limit` | Page size, default 250, max 1,000. |
| `cursor` | Pagination cursor from the previous page. |
| `q` | Substring filter over log messages. |

The response includes `lines`, `next_cursor`, `limit`, and a `truncated` flag.
Pass `next_cursor` back as `cursor` to page through long logs.

## Next steps

- [Write and read metric series](/docs/api/metrics-series.md)
- [Attach artifacts to runs](/docs/api/artifacts.md)
- [Handle errors, pagination, and limits](/docs/api/errors-and-limits.md)
- [Capture console logs from the SDK](/docs/sdk/console-system-integrations.md)
- [Compare runs in the dashboard](/docs/dashboard/compare-runs.md)

## Agent navigation

- [Docs index](/llms.txt)
- [Full docs bundle](/llms-full.txt)

### Get Started

- [Overview](/docs/index.md)
- [Quickstart](/docs/quickstart.md)
- [Core Concepts](/docs/concepts/core-concepts.md)
- [Pricing](/docs/pricing.md)
- [Benchmarks](/docs/benchmarks.md)
- [Examples](/docs/guides/examples.md)
- [Troubleshooting](/docs/troubleshooting.md)

### SDK

- [Installation Auth](/docs/sdk/installation-auth.md)
- [Logging](/docs/sdk/logging.md)
- [Tracing](/docs/sdk/tracing.md)
- [Metrics Steps](/docs/sdk/metrics-steps.md)
- [Config Tags Notes](/docs/sdk/config-tags-notes.md)
- [Artifacts Checkpoints](/docs/sdk/artifacts-checkpoints.md)
- [Rich Objects](/docs/sdk/rich-objects.md)
- [Distributed Training](/docs/sdk/distributed-training.md)
- [Console System Integrations](/docs/sdk/console-system-integrations.md)
- [Reliability](/docs/sdk/reliability.md)
- [Cli Login](/docs/sdk/cli-login.md)
- [Querying Data](/docs/sdk/querying-data.md)
- [Agent Mcp](/docs/sdk/agent-mcp.md)
- [Examples Patterns](/docs/sdk/examples-patterns.md)

### Integrations

- [Overview](/docs/integrations/overview.md)
- [Pytorch Lightning](/docs/integrations/pytorch-lightning.md)
- [Huggingface Transformers](/docs/integrations/huggingface-transformers.md)
- [Keras](/docs/integrations/keras.md)
- [Wandb](/docs/integrations/wandb.md)

### Dashboard

- [Tour](/docs/dashboard/tour.md)
- [Organizations Workspaces](/docs/dashboard/organizations-workspaces.md)
- [Runs Workspace](/docs/dashboard/runs-workspace.md)
- [Metrics Charts](/docs/dashboard/metrics-charts.md)
- [Run Detail](/docs/dashboard/run-detail.md)
- [Traces](/docs/dashboard/traces.md)
- [Compare Runs](/docs/dashboard/compare-runs.md)
- [Research Dashboards](/docs/dashboard/research-dashboards.md)
- [Artifacts Files](/docs/dashboard/artifacts-files.md)
- [Run Health](/docs/dashboard/alerts.md)
- [Datasets](/docs/dashboard/datasets.md)
- [Checkpoints](/docs/dashboard/checkpoints.md)
- [Reports](/docs/dashboard/reports.md)
- [Settings Api Keys](/docs/dashboard/settings-api-keys.md)
- [Api Tab](/docs/dashboard/api-tab.md)
- [Onboarding Team Billing](/docs/dashboard/onboarding-team-billing.md)

### Data

- [Imports](/docs/guides/imports.md)
- [W&B alternative](/docs/guides/wandb-alternative.md)
- [InstantML vs MLflow](/docs/guides/instantml-vs-mlflow.md)
- [W&B import guide](/docs/guides/wandb-import-guide.md)
- [W&B and Neptune imports](/docs/guides/wandb-neptune-imports.md)
- [Export Usage Limits](/docs/guides/export-usage-limits.md)
- [Pricing Limits Billing](/docs/guides/pricing-limits-billing.md)
- [Auth Billing Storage](/docs/guides/auth-billing-storage.md)
- [Customer Owned Clickhouse](/docs/guides/customer-owned-clickhouse.md)
- [Observability](/docs/guides/observability.md)

### API

**Practical API guides**

- [Authentication](/docs/api/authentication.md)
- [Errors And Limits](/docs/api/errors-and-limits.md)
- [Health Observability](/docs/api/health-observability.md)
- [Projects Runs](/docs/api/projects-runs.md) (current page)
- [Metrics Series](/docs/api/metrics-series.md)
- [Attributes Objects](/docs/api/attributes-objects.md)
- [Artifacts](/docs/api/artifacts.md)
- [Reports](/docs/api/reports.md)
- [Iframe Embeds](/docs/api/iframe-embeds.md)
- [Import Export Usage](/docs/api/import-export-usage.md)
- [Dashboard Control State](/docs/api/dashboard-control-state.md)
**Architecture**

- [System Overview](/docs/architecture/system-overview.md)
- [Service Planes](/docs/architecture/service-planes.md)
- [Storage Model](/docs/architecture/storage-model.md)
- [Google Clickhouse](/docs/architecture/google-clickhouse.md)
- [Auth Tenancy](/docs/architecture/auth-tenancy.md)
- [Schema Reference](/docs/architecture/schema-reference.md)

### API Reference

- [API Reference](/docs/api-reference.md)
