> ## Documentation Index
> Fetch the complete documentation index at: https://docs.resolve.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Resolve REST API

Query Resolve investigations from scripts, dashboards, or any HTTP client.

If you're connecting a coding agent (Claude Code, Codex, Cursor) or another MCP client, use [AI Assistant Plugins](/ai-assistant-plugins) instead.

## Authentication

All requests require a Bearer token.

**Recommended: a personal token** from **User menu > API Tokens**. Personal tokens attribute all actions to your user identity.

For shared service integrations or scripts that run on behalf of the organization, use an **organization token** from **Admin > API Tokens** instead.

Include the token in all requests:

```http theme={null}
Authorization: Bearer <your-token>
```

## Trigger an Investigation

```http theme={null}
POST /api/v1/investigations
```

**Base URL:** `https://app0.resolve.ai`

Requires a **personal token** (**User menu > API Tokens**). Organization tokens cannot trigger investigations (`401`), because every investigation is attributed to a real user.

**Body:** exactly one of the following.

| Field | Type | Description |
| :- | :- | :- |
| `source` | string | Free-form text describing the problem (e.g. built from a ServiceNow incident short description plus context) |
| `alertId` | string | The `alert.id` of an alert Resolve already ingested (from the [List Investigations](#list-investigations) endpoint) |

**Example (free-form text):**

```bash theme={null}
curl -sS -X POST "https://app0.resolve.ai/api/v1/investigations" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"source": "INC12345678: Checkout p99 latency spiked to 4s starting 14:32 UTC, only us-east-1, correlated with the deploy of svc-checkout 1.42.0"}'
```

**Example (existing alert):**

```bash theme={null}
curl -sS -X POST "https://app0.resolve.ai/api/v1/investigations" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"alertId": "alert-123"}'
```

**Response:**

Returns `202 Accepted` immediately; the investigation continues in the background. Poll [Get Investigation Details](#get-investigation-details) until `isComplete` is `true`, then read the markdown report from the `reports` array. `canvasUrl` is the link to paste into the ServiceNow work notes.

```json theme={null}
{
  "canvasId": "01KNW9EYDMCJ35A9F2PD630ZYG",
  "canvasUrl": "https://app0.resolve.ai/canvas/01KNW9EYDMCJ35A9F2PD630ZYG"
}
```

**Errors:**

| Status | Cause |
| :- | :- |
| `400` | The body does not contain exactly one of `source` or `alertId`, or the referenced event is not an alert |
| `401` | The request used an organization token instead of a personal token |
| `404` | The `alertId` was not found in your organization |

To find the alert id for an incident, if the alert carries the INC number as a label, look it up first with [List Investigations](#list-investigations), then trigger by id:

```bash theme={null}
curl -sS -H "Authorization: Bearer $TOKEN" \
  "https://app0.resolve.ai/api/v1/investigations?startTime=2026-07-01T00:09:59Z&label.number=INC12345678"
```

## List Investigations

```http theme={null}
GET /api/v1/investigations
```

**Base URL:** `https://app0.resolve.ai`

**Query Parameters:**

| Parameter | Type | Description |
| :- | :- | :- |
| `startTime` | ISO datetime | Start of search window (default: 1 hour ago) |
| `endTime` | ISO datetime | End of search window (default: now) |
| `cursor` | string | Pagination cursor from a previous response |
| `label.*` | string | Filter by alert labels (e.g. `label.service_name=checkout-api`) |

Multiple label filters use AND logic: all specified labels must match.

**Example:**

```bash theme={null}
curl -H "Authorization: Bearer $TOKEN" \
  "https://app0.resolve.ai/api/v1/investigations?label.service_name=checkout-api&label.severity=critical"
```

**Response:**

```json theme={null}
{
  "investigations": [
    {
      "canvasId": "01KNW9EYDMCJ35A9F2PD630ZYG",
      "name": "High error rate on checkout-api",
      "alert": {
        "id": "alert-123",
        "name": "Checkout Error Rate > 5%",
        "labels": { "service_name": "checkout-api", "severity": "critical" }
      },
      "createdAt": "2025-03-01T10:00:00.000Z"
    }
  ],
  "nextCursor": null
}
```

## Get Investigation Details

```http theme={null}
GET /api/v1/investigations/:canvasId
```

Returns the full investigation including status, completion state, and report files (problem summary, status updates, theories).

**Example:**

```bash theme={null}
curl -H "Authorization: Bearer $TOKEN" \
  "https://app0.resolve.ai/api/v1/investigations/01KNW9EYDMCJ35A9F2PD630ZYG"
```

**Response:**

```json theme={null}
{
  "canvasId": "01KNW9EYDMCJ35A9F2PD630ZYG",
  "name": "High error rate on checkout-api",
  "status": "stopped",
  "isComplete": true,
  "reportFinishedAt": "2025-03-01T10:25:00.000Z",
  "mttrMetrics": {
    "firstHypothesis":  { "at": "2025-03-01T10:07:30.000Z", "elapsedSeconds": 450 },
    "convergedRca":     { "at": "2025-03-01T10:19:00.000Z", "elapsedSeconds": 1140 },
    "investigationEnd": { "at": "2025-03-01T10:25:00.000Z", "elapsedSeconds": 1500 },
    "measured": true
  },
  "reports": [
    {
      "filePath": "/problem.md",
      "versions": [
        { "versionId": 0, "createdAt": "2025-03-01T10:05:00.000Z", "content": "# Problem\n..." }
      ]
    },
    {
      "filePath": "/status_update.md",
      "versions": [...]
    }
  ]
}
```

### Resolution timing: `mttrMetrics`

How long the investigation took to reach its milestones. `null` while the investigation is still running.

| Field | Meaning |
| :- | :- |
| `firstHypothesis` | When the report first stated a candidate root cause |
| `convergedRca` | When the report settled on the root cause it finally held |
| `investigationEnd` | When the investigation finished |
| `measured` | `true` when the milestones were measured from the report's revision history; `false` when only `investigationEnd` could be computed |

Each milestone carries `at` (timestamp) and `elapsedSeconds` (seconds from investigation start, excluding any time the investigation sat waiting on a human response, so `elapsedSeconds` is deliberately not `at` minus the start time). `investigationEnd` is always present. When `measured` is `true`, `convergedRca` is always present too (an investigation that never settled earlier converges at its final report state), and only `firstHypothesis` can be absent, for the rare report that never states a cause. When `measured` is `false`, only `investigationEnd` is returned.

The same numbers are returned by the [MCP server's](/resolve-mcp-server) `get_investigation` tool as `mttr_metrics`, in snake\_case (`first_hypothesis`, `converged_rca`, `investigation_end`, each with `at` and `elapsed_seconds`, plus `measured`). Connected agents get them without any extra call.

```bash theme={null}
# Average time to root cause across recent checkout-api investigations
curl -sS -H "Authorization: Bearer $TOKEN" \
  "https://app0.resolve.ai/api/v1/investigations?startTime=2026-08-01T00:00:00Z&label.service_name=checkout-api" \
| jq -r '.investigations[].canvasId' \
| while read id; do
    curl -sS -H "Authorization: Bearer $TOKEN" \
      "https://app0.resolve.ai/api/v1/investigations/$id" | jq '.mttrMetrics.convergedRca.elapsedSeconds // empty'
  done | jq -s 'add / length'
```
