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

# Atlas API

> Start and continue Atlas investigations, and read their findings, attribution graph, files, agent activity, reports and exports.

Start and continue [Atlas](https://docs.sixtyfour.ai/atlas/overview.md) investigations, and read everything they produce.

Use this API when you want the investigation itself: to start one without a `struct`, list your investigations, or read their findings, graph, files and report. To get a `structured_data` answer from the same research, use [People Intelligence with `tier: "xhigh"`](https://docs.sixtyfour.ai/atlas/integrations#people-intelligence).

## Endpoint

All paths are under `https://api.sixtyfour.ai/v1/atlas`.

| Method | Path | Purpose |
| - | - | - |
| `GET` | `/access` | Check whether your org has Atlas, and the engines it can run with their prices. |
| `POST` | `/investigations` | Start an investigation. |
| `POST` | `/investigations/{investigation_id}/runs` | Continue an investigation with another run. |
| `GET` | `/investigations` | List investigations. |
| `GET` | `/investigations/{investigation_id}` | Get one investigation. |
| `GET` | `/investigations/{investigation_id}/findings` | List findings (graph nodes), paginated. |
| `GET` | `/investigations/{investigation_id}/links` | List links between findings (graph edges), paginated. |
| `GET` | `/investigations/{investigation_id}/graph` | The whole attribution graph. |
| `GET` | `/investigations/{investigation_id}/files` | List workspace files. |
| `GET` | `/investigations/{investigation_id}/file-entries` | List workspace files, paginated. |
| `GET` | `/investigations/{investigation_id}/files/{path}` | Read one workspace file or attachment. |
| `GET` | `/investigations/{investigation_id}/events` | The agents' sessions and events, paginated. |
| `GET` | `/investigations/{investigation_id}/events/stream` | Follow the agents' turn summaries live over Server-Sent Events. |
| `GET` | `/investigations/{investigation_id}/events/{event_id}/payload` | One event's full input and output. |
| `POST` | `/investigations/{investigation_id}/report` | Generate the intelligence report. |
| `GET` | `/investigations/{investigation_id}/report` | Report generation status. |
| `GET` | `/investigations/{investigation_id}/report.pdf` | Download the report PDF. |
| `GET` | `/investigations/{investigation_id}/export.zip` | Export the whole workspace as a ZIP. |

Authenticate with your `x-api-key` header, as on every other endpoint.

## Checking access

`GET /access` works for every org. It returns whether your org has Atlas and, when it does, the engines it can run, the default first, each priced for your org:

```bash cURL theme={null}
curl "https://api.sixtyfour.ai/v1/atlas/access" \
  -H "x-api-key: YOUR_API_KEY"
```

```python Python theme={null}
import requests

response = requests.get(
    "https://api.sixtyfour.ai/v1/atlas/access",
    headers={"x-api-key": "YOUR_API_KEY"}
)
response.raise_for_status()
access = response.json()
```

```javascript JavaScript theme={null}
const response = await fetch("https://api.sixtyfour.ai/v1/atlas/access", {
  headers: { "x-api-key": "YOUR_API_KEY" }
});
if (!response.ok) throw new Error(`Request failed: ${response.status}`);
const access = await response.json();
```

```json theme={null}
{
  "has_atlas": true,
  "engines": [
    {"engine": "xhigh", "label": "XHigh", "credits": 250},
    {"engine": "scout", "label": "Scout", "credits": 50}
  ]
}
```

Without access the response is `{"has_atlas": false, "engines": []}`.

| Field | Type | Description |
| - | - | - |
| `has_atlas` | boolean | Whether your org can use Atlas. |
| `engines` | array | The engines your org can run, the default first. Empty when `has_atlas` is `false`. |
| `engines[].engine` | string | The value to pass as `engine` when starting or continuing a run. |
| `engines[].label` | string | Display name for the engine. |
| `engines[].credits` | number or null | Price of one unit of research on this engine, in credits. The default `max_credits` is one unit. `null` if the price could not be read; retry. |

## Starting an investigation

`POST /investigations` returns 202 with the run's `task_id` and the new investigation:

| Field | Type | Default | Description |
| - | - | - | - |
| `lead_info` | object | required | Who to investigate, for example `{"name": "Jane Doe", "company": "Acme"}`. |
| `name` | string | derived from `lead_info` | Title for the investigation. |
| `engine` | string | `xhigh` | `xhigh` for the deepest research, or `scout` for faster, lower-cost research (needs Scout access). [`GET /access`](#checking-access) lists the engines your org can run. |
| `research_plan` | string | — | Plain-language guidance on what to look into. |
| `struct` | object | — | Optional target fields, in the same format as [People Intelligence](https://docs.sixtyfour.ai/api-reference/endpoint/people-intelligence.md#using-the-struct-field). |
| `relentless` | boolean | `true` | Research until the budget runs out. Set `false` with a `struct` to let the run stop once every field is answered. |
| `max_credits` | integer | one unit of the engine price | How much research to buy, from one to ten units of the engine price. |
| `max_minutes` | integer (10–1440) | no limit | Working-time limit. When it is reached the run writes up what it found and charges only the credits it used, rounded up to the next 50. |
| `dispatch_id` | string (8–128 chars) | — | Idempotency key. Resending the same key returns the existing run instead of starting and billing a second one. |
| `private` | boolean | `false` | Make the investigation visible only to you, not your team. Your team must allow private runs. With an API key, it is private to the key's creator: they see it in the app, and their keys on the same team read it through the API, even after they leave the team or organization. A key with no recorded creator gets a 400. |

```bash cURL theme={null}
curl -X POST "https://api.sixtyfour.ai/v1/atlas/investigations" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "lead_info": {"name": "Jane Doe", "company": "Acme Corp"},
    "research_plan": "Professional background, current role and public board seats",
    "max_minutes": 60
  }'
```

```python Python theme={null}
import requests

response = requests.post(
    "https://api.sixtyfour.ai/v1/atlas/investigations",
    headers={"x-api-key": "YOUR_API_KEY"},
    json={
        "lead_info": {"name": "Jane Doe", "company": "Acme Corp"},
        "research_plan": "Professional background, current role and public board seats",
        "max_minutes": 60
    }
)
response.raise_for_status()
run = response.json()
investigation_id = run["investigation"]["id"]
```

```javascript JavaScript theme={null}
const response = await fetch("https://api.sixtyfour.ai/v1/atlas/investigations", {
  method: "POST",
  headers: { "x-api-key": "YOUR_API_KEY", "Content-Type": "application/json" },
  body: JSON.stringify({
    lead_info: { name: "Jane Doe", company: "Acme Corp" },
    research_plan: "Professional background, current role and public board seats",
    max_minutes: 60
  })
});
if (!response.ok) throw new Error(`Request failed: ${response.status}`);
const run = await response.json();
const investigationId = run.investigation.id;
```

```json theme={null}
{
  "task_id": "job_123",
  "status": "RUNNING",
  "investigation": {
    "id": "29beab70-42e4-5d19-b3b1-9a28279ca19f",
    "workspace_url": "https://app.sixtyfour.ai/atlas/29beab70-42e4-5d19-b3b1-9a28279ca19f/graph"
  }
}
```

Poll the run with [`GET /job-status/{task_id}`](https://docs.sixtyfour.ai/api-reference/endpoint/people-intelligence#async-and-timeouts), or open `workspace_url` to watch it in the Atlas section of the Sixtyfour app.

## Continuing an investigation

`POST /investigations/{investigation_id}/runs` starts another run on the same workspace and graph. It takes the same body as starting one, without `lead_info`, `name` and `private`, and returns the same 202 response. Continuing needs editor access to the investigation.

```bash theme={null}
curl -X POST "https://api.sixtyfour.ai/v1/atlas/investigations/INVESTIGATION_ID/runs" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"research_plan": "Follow up on the earlier role at the previous employer"}'
```

## Listing and reading investigations

`GET /investigations` returns `investigations`, the page `limit` and a `next_cursor`:

| Query parameter | Default | Description |
| - | - | - |
| `limit` | `50` | Page size, 1–200. |
| `after` | — | `next_cursor` from the previous page. |
| `shared` | `all` | `owned` for your team's investigations, `shared` for ones other teams shared with yours, or `all`. |
| `status` | — | Only investigations in this state: `created`, `running`, `stalled`, `completed` or `failed`. |
| `created_after`, `created_before` | — | ISO 8601 timestamps. |

Each investigation, also returned by `GET /investigations/{investigation_id}`, looks like this:

```json theme={null}
{
  "id": "29beab70-42e4-5d19-b3b1-9a28279ca19f",
  "name": "Jane Doe — Acme Corp",
  "status": "completed",
  "visibility": "public",
  "lead_info": {"name": "Jane Doe", "company": "Acme Corp"},
  "created_at": "2026-01-15T10:00:00Z",
  "updated_at": "2026-01-15T10:42:00Z",
  "completed_at": "2026-01-15T10:42:00Z",
  "cost_cents": 25000,
  "cost_credits": 2500,
  "shared": null,
  "workspace_url": "https://app.sixtyfour.ai/atlas/29beab70-42e4-5d19-b3b1-9a28279ca19f/graph",
  "private": false
}
```

`shared` is `null` when your team owns the investigation. Otherwise it names the team that shared it and your `tier` on it: a `viewer` can read and export, an `editor` can also run and edit.

## Reading the graph and workspace

| Endpoint | Returns |
| - | - |
| `GET .../graph` | The whole attribution graph: `nodes` (findings with their source URLs) and `edges` (confidence-weighted links between them). |
| `GET .../findings`, `GET .../links` | The same nodes and edges one page at a time: `items` and `next_cursor`. `limit` is 1–50 (default 50); pass `next_cursor` as `after`. |
| `GET .../files` | Every workspace file: `path`, `content_type`, `size_bytes`, `updated_at`, `version`, and `attachment` metadata for saved images and documents. |
| `GET .../file-entries` | The same file metadata one page at a time: `items` and `next_cursor`. |
| `GET .../files/{path}` | One file's content, or an attachment's bytes. |
| `GET .../events` | The agents' `sessions` (type, task, status, turn count, cost) and `events`, oldest first, with `next_cursor`. What you see depends on your org's access: turn summaries, or the full tool stream with per-event payloads. |
| `GET .../events/{event_id}/payload` | One event's full input and output, for events too large to return inline. Needs the same access as the full tool stream. |

Field confidence on an Atlas run lists, for each value, the `nodes` in this graph that support it. See [Confidence Scoring](https://docs.sixtyfour.ai/api-reference/endpoint/field-confidence.md).

## Following a run live

`GET .../events/stream` sends the agents' turn summaries over [Server-Sent Events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events) as they are written, in order. Omit `after` to replay from the start.

```bash theme={null}
curl -N "https://api.sixtyfour.ai/v1/atlas/investigations/INVESTIGATION_ID/events/stream" \
  -H "x-api-key: YOUR_API_KEY"
```

| Frame | Sent | Data |
| - | - | - |
| `sessions` | First, and whenever an agent session starts, finishes or changes | Every agent session |
| `event` | For each turn summary | The event. Its `id:` is the cursor to resume from |
| `status` | When the stream opens, and whenever the status changes | `status` and `completed_at` |
| `end` | When the run is `completed` or `failed` and every event has been sent | `status`. The stream closes |
| `access_lost` | When you can no longer see the investigation | None. The stream closes |

The `sessions` frame before `end` carries the run's recorded cost, or `null` if settlement did not record it in time. Comment lines are heartbeats.

A stream closes after about five minutes so access is checked again. SSE clients reconnect on their own with `Last-Event-ID` and resume from the last event. Other clients pass that id as `after`, which also accepts `next_cursor` from `GET .../events`.

## Reports

1. `POST .../report` starts generating a PDF intelligence report from the current workspace and returns 202 with a report job. If an up-to-date report already exists, the job comes back with `cached: true`. Pass `{"retry_failed": true}` to retry after a failure. An empty workspace returns 400.
2. `GET .../report` returns the job: `job_id`, `status` (`pending`, `running`, `completed`, `failed`, or `superseded` when the workspace changed and a newer job replaced it), `requested_at`, `completed_at`, `error` and `byte_size`.
3. `GET .../report.pdf` returns the PDF when it is ready, 202 with the job and a `Retry-After` header while it is generating, and 404 if no report has been requested.

```bash cURL theme={null}
curl -X POST "https://api.sixtyfour.ai/v1/atlas/investigations/INVESTIGATION_ID/report" \
  -H "x-api-key: YOUR_API_KEY"

# 200 is the PDF, 202 means still generating, anything else is a failure
while true; do
  code=$(curl -s -o report.pdf -w '%{http_code}' \
    "https://api.sixtyfour.ai/v1/atlas/investigations/INVESTIGATION_ID/report.pdf" \
    -H "x-api-key: YOUR_API_KEY")
  [ "$code" = "200" ] && break
  [ "$code" != "202" ] && { echo "Report failed: $code"; cat report.pdf; exit 1; }
  sleep 15
done
```

```python Python theme={null}
import time
import requests

BASE = "https://api.sixtyfour.ai/v1/atlas/investigations/INVESTIGATION_ID"
HEADERS = {"x-api-key": "YOUR_API_KEY"}

requests.post(f"{BASE}/report", headers=HEADERS).raise_for_status()
while True:
    pdf = requests.get(f"{BASE}/report.pdf", headers=HEADERS)
    if pdf.status_code == 200:
        open("report.pdf", "wb").write(pdf.content)
        break
    if pdf.status_code != 202:
        raise RuntimeError(f"Report failed: {pdf.status_code}")
    time.sleep(int(pdf.headers.get("Retry-After", "15")))
```

```javascript JavaScript theme={null}
const BASE = "https://api.sixtyfour.ai/v1/atlas/investigations/INVESTIGATION_ID";
const HEADERS = { "x-api-key": "YOUR_API_KEY" };

await fetch(`${BASE}/report`, { method: "POST", headers: HEADERS });
let pdf;
while (true) {
  const res = await fetch(`${BASE}/report.pdf`, { headers: HEADERS });
  if (res.status === 200) { pdf = await res.arrayBuffer(); break; }
  if (res.status !== 202) throw new Error(`Report failed: ${res.status}`);
  await new Promise(r => setTimeout(r, Number(res.headers.get("Retry-After") ?? 15) * 1000));
}
```

## Export

`GET .../export.zip` downloads everything visible in the app in one archive: workspace files, attachments with `<path>.json` metadata sidecars, the attribution graph, `investigation.json`, and the agents' activity when your org has access to it.

## Pricing

Starting or continuing an investigation is billed at the engine's price per unit; reading, reports and exports are not billed per call. See [Credits & Pricing Guide](https://docs.sixtyfour.ai/guides/credits-and-pricing.md) for the price per unit.

## Errors

For error responses (400, 402, 403, 404, 409, 429, etc.), see [Handling Errors](https://docs.sixtyfour.ai/api-reference/errors.md).

Atlas is enabled on request. Without access, starting or reading an investigation returns 403; [`GET /access`](#checking-access) works for every org and returns `{"has_atlas": false, "engines": []}`, so clients can hide investigation features instead of handling the error. Contact [sales](mailto:support@sixtyfour.ai) to request access.

All `/v1/atlas` endpoints share a limit of 120 requests per minute per organization. Reads don't consume credits, so an org with no balance can still list and export what it already ran.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.