> ## 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.

# Deep Investigations

> Start, continue and read Atlas deep investigations: the persistent research workspace and attribution graph behind xhigh People Intelligence.

Run a deep investigation on a person and keep it: a team of research agents builds a workspace of files and an attribution graph that links every finding to its source, which you can read, export as a report, and continue later. Use it for diligence, background research and any lead where a single enrichment answer isn't enough.

A deep investigation is the same run as [People Intelligence](/api-reference/endpoint/people-intelligence#deep-investigations-xhigh) on `tier: "xhigh"` (or `scout` with `graph: true`). Use this API when you want the investigation itself rather than a `structured_data` answer: to start one without a `struct`, list your investigations, or read their findings, graph, files and report.

## Endpoint

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

| Method | Path | Purpose |
| - | - | - |
| `GET` | `/access` | Check whether your org has deep investigations. |
| `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 event stream. |
| `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.

## How an investigation works

```mermaid theme={null}
flowchart LR
    A[POST /investigations] --> B[Run: agents research]
    B --> C[(Workspace files + attribution graph)]
    C --> D[Read findings, graph, files]
    C --> E[POST .../report → report.pdf]
    C --> F[export.zip]
    C --> G[POST .../runs: continue]
    G --> B
```

Each run researches until its credit budget, its time limit or, when you set a `struct` without `relentless`, its answers are complete. Findings and files persist on the investigation, so a later run builds on them instead of starting over.

## 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 multi-agent research, or `scout` for the same investigation tooling on a lighter, cheaper model (needs Scout access). |
| `research_plan` | string | — | Plain-language guidance on what to look into. |
| `struct` | object | — | Optional target fields, in the same format as [People Intelligence](/api-reference/endpoint/people-intelligence#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. Needs a signed-in user and a team that allows private runs. |

<CodeGroup>
  ```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;
  ```
</CodeGroup>

```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}`](/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,
  "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 source URLs and quotes) 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. |

Field confidence on a deep-investigation People Intelligence run lists, for each value, the `nodes` in this graph that support it. See [Confidence Scoring](/api-reference/endpoint/field-confidence).

## 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.

<CodeGroup>
  ```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));
  }
  ```
</CodeGroup>

## 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 as a deep-investigation People Intelligence run; reading, reports and exports are not billed per call. See [Credits & Pricing Guide](/guides/credits-and-pricing) for the price per unit.

## Errors

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

Deep investigations are enabled on request. Without access, starting or reading an investigation returns 403; `GET /access` works for every org and returns `{"has_atlas": false}`, 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.