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

# Research API Reference

> Complete reference for research requests, streams, and saved runs

<Info>**Beta:** The Research API is available to everyone while in beta. Contact support if you encounter any bugs.</Info>

## Endpoints

| Endpoint | Method | Purpose |
| - | - | - |
| `/v1/automation/run-research` | `POST` | Start a research run and stream progress |
| `/v1/research-run` | `GET` | List saved research runs |
| `/v1/research-run/{research_run_id}` | `GET` | Retrieve one saved run |
| `/v1/research-run/{research_run_id}/cancel` | `POST` | Cancel a running research run |

All endpoints use `https://agent.tinyfish.ai` and require the `X-API-Key` header.

<Note>
  Research must be enabled for the API key's account. `POST /v1/automation/run-research` returns `403` when it is not.
</Note>

## Modes

| Mode | Best for | Typical time | Browser agents |
| - | - | - | - |
| `standard` | Fast, source-backed answers | 2–10 minutes | No |
| `deep` | Broader coverage and synthesis | 5–20 minutes | No |
| `max` | Complex or dynamic research | 5–45 minutes | On by default |

An omitted mode selects `deep`. Legacy `auto` selects `standard`. Set `browser_enabled: false` to keep Max mode to
search and static fetches. `browser_enabled: true` is accepted only in Max mode.

## Request Body

| Field | Type | Required | Notes |
| - | - | - | - |
| `query` | `string` | Yes | Research question, 1–2,000 characters |
| `mode` | `auto \| standard \| deep \| max` | No | Defaults to `deep` |
| `stream` | `boolean` | No | Emits synthesis text through `synthesis_delta` |
| `output_language` | `string` | No | BCP 47 tag such as `en`, `ja`, or `pt-BR` |
| `browser_enabled` | `boolean` | No | Max only; defaults to `true` in Max mode |
| `weak_sources_enabled` | `boolean` | No | Allows relevant social and community sources |
| `domain_type` | `web \| news \| research_paper` | No | Defaults to `web` |
| `after_date` | `YYYY-MM-DD` | No | Include results on or after this date |
| `before_date` | `YYYY-MM-DD` | No | Include results on or before this date |
| `recency_minutes` | `integer` | No | Include results from the last 1–5,256,000 minutes |
| `domain_filter` | `object` | No | Prefer, require, or block specified domains |
| `prior_run_id` | `string` | No | Seed a run with a completed report |
| `session_id` | `UUID` | No | Continue a standard-mode session |

<Note>
  Do not combine `recency_minutes` with date filters. Date and recency filters are unavailable for `research_paper`.
  `session_id` and `prior_run_id` are mutually exclusive.
</Note>

## Event Stream

Accepted requests return `text/event-stream`, including when `stream` is omitted or false. Invalid input and other
pre-run failures return the standard JSON error body.

| Event | Purpose |
| - | - |
| `created` | Supplies the research run ID |
| `session` | Supplies a reusable conversation session ID |
| `plan_updated` | Reports current subquestions and searches |
| `sources_searched` | Lists candidate sources |
| `source_fetched` | Reports static source extraction |
| `agent_run_started` / `agent_run_completed` | Reports Max-mode browser work |
| `partial_summary` | Supplies an intermediate synthesis |
| `synthesis_delta` | Streams report text when enabled |
| `synthesis_discarded` | Discard provisional content for the named checkpoint |
| `heartbeat` | Keep the long-running connection open |
| `evidence_snapshot` | Supplies the current evidence set |
| `final_result` | Supplies the report, citations, and termination reason |
| `run_stats` | Supplies final source, agent, and claim counts |
| `error` | Reports a pipeline failure |
| `done` | Terminates the stream |

Ordered `synthesis_delta` values reconstruct their matching summary or final result. Discard a provisional partial
checkpoint after `synthesis_discarded`. Heartbeats keep long-running connections open.

## Run Statuses

| Status | Meaning |
| - | - |
| `RUNNING` | The run is in progress. |
| `COMPLETED` | The run finished and its report is saved. |
| `FAILED` | The pipeline failed before producing a report. |
| `CANCELLED` | The run was cancelled through the cancel endpoint. |
| `TIMED_OUT` | The run exceeded the time budget for its mode. |

`COMPLETED`, `FAILED`, `CANCELLED`, and `TIMED_OUT` are terminal.

## List Saved Runs

`GET /v1/research-run` supports `status`, `query`, `created_after`, and `created_before`. Pagination uses `limit` from
1–100, `sort_direction=asc|desc`, and the returned `next_cursor`. Reuse a cursor only with the same sort direction.

```bash theme={null}
curl "https://agent.tinyfish.ai/v1/research-run?status=COMPLETED&limit=20" \
  -H "X-API-Key: $TINYFISH_API_KEY"
```

```json theme={null}
{
  "data": [
    {
      "research_run_id": "019...",
      "status": "COMPLETED",
      "query": "Compare long-duration energy storage approaches",
      "quick_result": { "answer": "...", "citations": ["https://example.com"] },
      "quick_result_summary": "...",
      "deep_result": { "result": "...", "citations": ["https://example.com"] },
      "run_ids": [],
      "created_at": "2026-09-09T16:00:00.000Z",
      "completed_at": "2026-09-09T16:07:41.000Z"
    }
  ],
  "pagination": {
    "total": 34,
    "next_cursor": "eyJ...",
    "has_more": true
  }
}
```

`quick_result` holds the standard-mode answer and `deep_result` the Deep and Max report. Both are objects: read the
report from `deep_result.result`, not from `deep_result` itself. `quick_result_summary` is the one plain string.
`run_ids` lists the Agent runs a Max run started. Fields that do not apply to the run are `null`.

## Retrieve One Run

`GET /v1/research-run/{research_run_id}` returns the list fields plus the working state kept for the run.

```bash theme={null}
curl "https://agent.tinyfish.ai/v1/research-run/$RESEARCH_RUN_ID" \
  -H "X-API-Key: $TINYFISH_API_KEY"
```

| Field | Notes |
| - | - |
| `research_plan` | Subquestions and searches the run planned |
| `evidence` | Sources gathered, with the claims they support |
| `iterations` | Number of plan-search-synthesize iterations completed |

A run that does not exist returns HTTP `404`. A run owned by another API key returns HTTP `403`.

## Cancel a Run

Call `POST /v1/research-run/{research_run_id}/cancel` to cancel a running research run. The response reports whether
this request changed the run to `CANCELLED` and includes its current status.

```json theme={null}
{
  "research_run_id": "019...",
  "status": "CANCELLED",
  "cancelled": true
}
```

Cancellation is idempotent. A run that is already terminal returns HTTP `200` with `cancelled: false` and its current
status. A missing run, or a run owned by another API key, returns HTTP `404`.

## Limits

Research creation is limited by concurrent runs and by runs started per Pacific calendar day. While Research is in beta
both default to 5 per account. Contact support if you need higher limits.

The daily count includes runs still in progress as well as completed ones, so five in-flight runs exhaust the day's
allowance. Runs that fail, time out, or are cancelled do not count.

Daily-limit responses use HTTP `429` with `error.code` set to `DAILY_LIMIT_EXCEEDED`, carry `Retry-After` and
`X-RateLimit-Limit` / `X-RateLimit-Remaining` / `X-RateLimit-Reset` headers, and report the window in `error.details`.

```json theme={null}
{
  "error": {
    "code": "DAILY_LIMIT_EXCEEDED",
    "message": "Today's Research limit has been reached. Please try again later.",
    "details": {
      "capability": "big_search_completion",
      "limit": 5,
      "used": 5,
      "remaining": 0,
      "reason": "exhausted",
      "window": "pacific_day",
      "resets_at": "2026-09-10T07:00:00.000Z"
    }
  }
}
```

If the limit cannot be evaluated, the request returns HTTP `503` with `error.code` set to `SERVICE_BUSY`. Retry after a
short pause.
