---
title: "Deep Research"
method: POST
path: "/v1/research"
---

# Deep Research

`POST /v1/research`

## Request

- Base URL: `https://api.octen.ai`
- URL: `https://api.octen.ai/v1/research`
- Auth: one of:
  - HTTP bearer
  - API key in header `x-api-key`

Generates a deep research report at the selected tier. The `pro-visual` tier also returns relevant images and videos.

**Two-phase invocation**
- **Phase 1:** the server generates a research plan. If the plan has no ambiguity, the server proceeds directly to research and streams the final report. If the plan is ambiguous, the `plan` event carries `requires_selection=true` together with a `plan_id`, and the SSE stream ends there — waiting for the client to confirm.
- **Phase 2:** call this endpoint again with the `plan_id` and `selections`. The server loads the stored plan, applies the selections, and streams the final report.

**Notes**
- Phase 2 only inherits the stored `plan` via `plan_id`. Other parameters are NOT inherited from Phase 1 — they must be supplied again in Phase 2, otherwise they fall back to defaults.
- `messages` is required in both phases and should carry the same user question.

## Request body

- DeepResearchRequest: Request body for the Deep Research API.
  - `tier` 'lite' | 'standard' | 'pro' | 'pro-visual': The research tier. `lite`, `standard`, and `pro` increase research depth, cost, and time in that order. `pro-visual` additionally illustrates each report section with images and videos and streams an HTML version of the report.
  - `messages` DeepResearchMessage[], required: Conversation messages. Only the last `role=user` message is used as the research question; other messages are ignored and do not enter plan generation, search, analysis, or report writing.
    - `role` 'system' | 'user' | 'assistant', required: The role of the message author.
    - `content` union, required: The content of the message. Can be a plain string, or an array of text content blocks.
      - string
      - DeepResearchTextContentBlock[]
        - `type` 'text', required: The block type. Always `text` for Deep Research.
        - `text` string: The text content.
  - `extra_context` string: Additional research background, constraints, or preferences, used as extra context for query rewriting and research direction supplementation.
  - `skip_brief` boolean: Skip the Research Brief stage and write the final report directly from raw search and analysis results. Note: when enabled, no `brief` event is emitted. Clients can rebuild the citation index by accumulating `search_results` events in the order they arrive (round-by-round / query-by-query / result-by-result) into a global index, then look up the corresponding url/title by the `N` in `[^N]`.
  - `skip_plan` boolean: Phase 1 only. Skip the Research Plan stage and proceed straight to the search loop. With `skip_plan=true`, the call never enters the Phase 2 pause mechanism.
  - `skip_plan_confirm` boolean: Phase 1 only. When `true`, the run continues with all angles even if the plan is ambiguous, instead of pausing and waiting for the user to confirm a selection.
  - `plan_id` string: Phase 2 only. The plan ID returned by a Phase 1 `plan` event with `requires_selection=true`. When provided, the server skips plan generation and applies the supplied `selections` against the stored plan. Each `plan_id` is retained for 30 minutes; after expiry the plan is regenerated.
  - `selections` DeepResearchSelection[]: Phase 2 only. The user's corrections and angle filtering against the Phase 1 plan.
    - `term` string: An ambiguous term, matching `plan.interpretations[].term`. When present, overrides the LLM's default `chosen` meaning.
    - `chosen` string: The selected meaning ID (from `plan.interpretations[].meanings[].id`, e.g. `"nasa_program"`). Pass `"all"` to keep every meaning. When used as an angle filter, this carries the `interpretation_id` of the angles to keep.
    - `indices` integer[]: 0-based angle indices within the group identified by `chosen`. Absent means keep every angle in that group.

## Response `200`

Successful Deep Research response. Always streamed as Server-Sent Events.

- DeepResearchChunk: A streaming chunk of a Deep Research response.
  - `type` 'status' | 'plan' | 'queries' | 'search_done' | 'analysis' | 'brief' | 'content' | 'visual' | 'html_delta' | 'html' | 'finish' | 'usage' | 'error': The type of this streaming chunk. On the `pro-visual` tier, `html_delta` chunks stream an HTML version of the report after the report content completes, and a final `html` chunk marks the end of that stream.
  - `request_id` string, required: The unique identifier for this request.
  - `object` 'research.chunk': The object type, always `research.chunk`.
  - `created` number, required: Unix timestamp (in seconds) of when the chunk was created.
  - `round` integer: Current research round. Present only in `queries`, `search_done`, and `analysis` chunks.
  - `latency` integer: Latency in milliseconds for the stage represented by this chunk.
  - `status` string: Pipeline progress copy. Present only in `status` chunks.
  - `plan` DeepResearchPlan: Research plan generated in Phase 1. Carried by `plan` chunks.
    - `title` string: Plan title.
    - `overview` string: Plan overview.
    - `interpretations` DeepResearchInterpretation[]: Ambiguous terms in the question along with their possible meanings. Empty when the question has no ambiguity.
      - `term` string: The ambiguous term.
      - `meanings` DeepResearchMeaning[]: All candidate meanings for this term.
        - `id` string: Unique meaning ID.
        - `label` string: Description of the meaning.
      - `chosen` string: The meaning ID the LLM picked by default.
      - `reasoning` string: The LLM's rationale for the chosen meaning.
    - `angles` DeepResearchAngle[]: Research angles the plan will explore.
      - `focus` string: Angle name.
      - `focus_desc` string: Angle description.
      - `interpretation_id` string: The meaning ID this angle serves. `"general"` denotes a cross-interpretation angle.
      - `queries` string[]: Search queries planned for this angle.
      - `sub_question_ids` string[]: Sub-question IDs covered by this angle.
    - `requires_selection` boolean: When `true`, the SSE stream ends at this `plan` chunk and waits for the client to continue via Phase 2 (`plan_id` + `selections`). When `false`, research continues automatically.
  - `plan_id` string: Plan ID carried by `plan` chunks. The client must echo this back as `plan_id` when entering Phase 2.
  - `queries` string[]: Sub-queries generated for this round. Present only in `queries` chunks.
  - `search_result_count` integer: Total number of search results returned this round. Present only in `search_done` chunks.
  - `search_results` SearchResultGroup[]: Search results for this round, one group per sub-query. Present only in `search_done` chunks.
    - `query` string: The sub-query that produced these results.
    - `results` SearchResult[]: The search results for this sub-query.
      - `title` string: The title of the result page.
      - `url` string: The URL of the result page.
      - `highlight` string: Query-relevant highlight snippets. Returned only if highlight.enable is true.
      - `full_content` string: Full raw page content. Returned only if full_content.enable is true.
      - `authors` string: Website name or author.
      - `time_published` string, date-time: Publish time in ISO 8601.
      - `time_last_crawled` string, date-time: Last crawl time in ISO 8601.
      - `favicon` string: The favicon URL of the result site.
      - `cover_image` object: The page cover image. Returned only when `include_images` is true and the page has a cover image.
        - `url` string: The cover image URL.
        - `description` string: Text description of the cover image.
      - `images` object[]: In-body images of the page, in order of appearance. Returned only when `include_images` is true.
        - `url` string: The image URL.
        - `description` string: Text description of the image.
    - `latency` integer: Search latency for this query in milliseconds.
  - `analysis` DeepResearchAnalysis: Analysis output for one research round. Carried by `analysis` chunks.
    - `findings` string[]: Key findings extracted from this round.
    - `should_continue` boolean: Whether the pipeline should run another research round.
    - `follow_up_suggestions` string[]: Suggested research directions for the next round.
  - `brief` DeepResearchBrief: Report outline and evidence set. Carried by `brief` chunks.
    - `report_type` 'general' | 'comparison' | 'trend' | 'how-to' | 'evaluation' | 'framework' | 'deep_explainer' | 'theoretical_analysis' | 'landscape_mapping' | 'multi_part': Report type, classified by the LLM from the question. `general`: general synthesis; `comparison`: cross-entity comparison; `trend`: time-axis trend analysis; `how-to`: step-by-step guide; `evaluation`: ranked or scored evaluation; `framework`: methodology or scoring framework; `deep_explainer`: deep explanation of a single topic; `theoretical_analysis`: scholarly analysis across multiple theoretical lenses; `landscape_mapping`: taxonomy and players in a domain; `multi_part`: composite question with explicit sub-questions.
    - `secondary_report_types` string[]: Secondary type tags for hybrid reports, combined with `report_type`.
    - `total_word_budget` integer: Total word budget for the report.
    - `assertiveness_required` boolean: Whether the report must deliver a clear verdict.
    - `verdict_scaffold` DeepResearchVerdictScaffold: Structured scaffold for reports that need to deliver a verdict.
      - `verdict_type` 'ranked_list' | 'single_pick' | 'tiered_recommendation' | 'qualified_pick': Shape of the verdict. `ranked_list`: ordered ranking; `single_pick`: a single best answer; `tiered_recommendation`: tiered recommendation; `qualified_pick`: conditional recommendation.
      - `items_expected` integer: Expected number of items in the verdict.
      - `justification_dimensions` string[]: Data dimensions supporting the verdict.
    - `tables` DeepResearchTable[]: Table metadata to render in the report. Mutually exclusive with `presentation_notes`.
      - `table_id` string: Unique table ID, referenced by `outline.table_ids`.
      - `title` string: Table title.
      - `columns` string[]: Column names.
      - `description` string: Description of the table contents, guiding how the report-writing stage should populate the cells.
      - `placement` string: Section ID this table belongs to.
    - `presentation_notes` string[]: Presentation notes for reports that do not use tables. Mutually exclusive with `tables`.
    - `outline` DeepResearchOutlineSection[]: Report outline in section order.
      - `section_id` string: Unique section ID, referenced by `sub_question_to_section_map` and `table.placement`.
      - `section_title` string: Section title.
      - `thesis` string: Central claim of this section.
      - `table_ids` string[]: Table IDs belonging to this section.
      - `covers_sub_questions` string[]: Sub-question IDs covered by this section.
      - `target_words` integer: Target word count for this section.
      - `evidence` DeepResearchEvidence[]: Evidence supporting this section.
        - `content` string: Evidence content.
        - `source_indices` integer[]: Source indices cited by this evidence (matching `brief.references[].index`).
        - `confidence` 'strong' | 'moderate' | 'weak' | 'conflicting': Confidence level of the evidence.
        - `layer` 'phenomenon' | 'mechanism' | 'evidence' | 'implication': Depth layer of the evidence.
    - `sub_question_to_section_map` object: Mapping from sub-question ID to section ID.
    - `unresolved` DeepResearchUnresolved: Items the brief stage flagged as unresolved.
      - `contradictions` string[]: Contradictions between sources.
      - `weak_claims` string[]: Claims with thin evidence.
      - `depth_gaps` string[]: Depth-layer gaps across sections.
      - `unanswered` string[]: Sub-questions left unanswered.
    - `suggested_title` string: Suggested title for the report.
    - `references` DeepResearchReference[]: List of cited references.
      - `index` integer: Reference index; cited in the report body as `[^N]`.
      - `url` string: Source URL.
      - `title` string: Source title.
  - `choices` DeepResearchChunkChoice[]: Incremental choices for the final report. Present in `content` and `finish` chunks.
    - `index` number: The index of this choice. Usually `0`.
    - `delta` DeepResearchChunkDelta: Incremental content in a Deep Research streaming chunk.
      - `content` string: Incremental report text. Concatenate across `content` chunks to build the final report.
    - `finish_reason` 'stop' | 'length' | 'content_filter' | 'error', nullable: The reason generation stopped. `null` in `content` chunks; populated in the `finish` chunk.
  - `visual` DeepResearchVisual: Visual material for one report section. Carried by `visual` chunks on the `pro-visual` tier.
    - `section_id` string: The report section this material belongs to, matching `brief.outline[].section_id`.
    - `images` DeepResearchVisualImage[]: Images selected for this section.
      - `url` string: The image URL.
      - `thumbnail` string: Thumbnail URL.
      - `caption` string: A short caption for the image.
      - `visual_evidence` string: Why this image supports the section's content.
      - `source_page` string: URL of the page the image was found on.
      - `width` integer: Image width in pixels.
      - `height` integer: Image height in pixels.
      - `confidence` number: Relevance confidence score.
    - `videos` DeepResearchVisualVideo[]: Videos selected for this section.
      - `url` string: The video URL.
      - `cover_url` string: Video cover image URL.
      - `title` string: The video title.
      - `duration_seconds` integer: Video duration in seconds.
      - `source_page` string: URL of the page the video was found on.
      - `time_published` string: Publish time in ISO 8601.
  - `html_delta` object: An incremental fragment of the HTML report. Present only in `html_delta` chunks. Concatenate the fragments in order to rebuild the full page.
    - `delta` string: The next fragment of the HTML page.
  - `meta` DeepResearchMeta: Usage and latency metadata for the Deep Research call. Carried by `usage` chunks.
    - `usage` object: Search usage.
      - `num_search_queries` integer: Total number of search queries executed across all rounds.
    - `latency` integer: Total request latency in milliseconds.
    - `total_rounds` integer: Total number of research rounds completed.
    - `total_search_count` integer: Total search results accumulated across all rounds.
    - `billed_tier` string: The tier actually billed for this request.

## Other responses

- `400`: Missing parameter messages
- `401`: Invalid API Key — Returned when the API key is missing or invalid.
- `403`: Insufficient balance in account — Returned when the account balance is insufficient to complete the request.
- `429`: Exceeding the rate limit — Returned when the request exceeds the configured rate limit.
- `500`: Internal error — Returned when an unexpected server-side error occurs.

---

[API](https://skmtc.dev/octen/apis/octen-api.md) - [All operations](https://skmtc.dev/octen/apis/octen-api/llms.txt) - [OpenAPI document](https://skmtc.dev/octen/apis/octen-api/revisions/aaa6caaf46b0?raw)
