codai docs
API referenceGateway

Research

Asynchronous deep research: a cited report from several searches and page reads.

POST /v1/research starts a job that plans several searches, reads the best pages and writes a report where every claim cites its source as [S1]..[Sn] (or, with output_schema, a JSON answer). The request waits up to wait_s seconds (default 0) and answers 200 with the finished job or 202 while it is queued / running; poll GET /v1/research/{id} until status is done or failed. Resending the same Idempotency-Key returns the existing job. Admission is the same as tools — your rules see it as web_search. Price: $0.20 per job plus its model tokens; jobs inside the monthly free allowance or a codai agent turn are not charged the job fee.

The SDKs wrap the polling: codai.research.run({ question }) (TypeScript) and codai.research.run("…") (Python) start the job and wait for it. The same engine is the deep_research tool in VS Code, desktop, phone, headless and the hosted MCP. Details: tools guide.

POST
/v1/research

Authorization

bearerAuth
headerAuthorizationBearer <codai_…>

A codai API key (codai_ prefix). Ephemeral tokens from POST /v1/tokens are accepted only by the media surfaces matching their scope (/v1/realtime, /v1/audio/*, /v1/embeddings).

Header Parameters

x-request-id?string

Client correlation id; echoed back as x-codai-trace-id and persisted on the usage row.

Lengthlength <= 128
Idempotency-Key?string

Returns the job created earlier with the same key instead of starting another one (first 200 characters are used).

Lengthlength <= 200

Request Body

application/json
  1. body

Body of POST /v1/research.

question*string

The research question, with any constraints (region, period, what to compare).

Length1 <= length <= 2000
time_budget_s?integer

Maximum research time in seconds.

Range20 <= value <= 300
Default90
max_sources?integer

Maximum number of pages to read.

Range3 <= value <= 30
Default12
include_domains?array<>

Only use pages from these hosts.

Itemsitems <= 10
published_after?string

Only use pages published on or after this date (YYYY-MM-DD).

Match^\d{4}-\d{2}(-\d{2})?$
output_schema?

Optional JSON Schema; the result is then a JSON object matching it in answer instead of a prose report.

wait_s?number

Seconds to wait for the job to finish before answering 202.

Range0 <= value <= 55
Default0

Response Body

The job finished within wait_s (status is done or failed).

application/json
  1. response

A deep-research job. Result fields are present only when status is done, error only when it is failed.

id*string
Formatuuid
status*string
Value in"queued""running""done""failed"
created_at*string
Formatdate-time
finished_at?string
Formatdate-time
report?string

Markdown report citing sources as [S1]..[Sn] (absent when output_schema was set).

answer?

JSON object matching output_schema, when one was sent.

sources?array<>
searches?integer

Number of web searches the job ran.

Range0 <= value
pages_read?integer

Number of pages the job read.

Range0 <= value
error?
Example Request
curl -X POST 'https://ai.codai.ro/v1/research' \  -H 'Content-Type: application/json' \  -d '{  "question": "Compare the e-Factura obligations for B2C sales in Romania in 2025 and 2026"}'
Example Response
{  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",  "status": "queued",  "created_at": "2019-08-24T14:15:22Z",  "finished_at": "2019-08-24T14:15:22Z",  "report": "string",  "answer": {},  "sources": [    {      "id": "string",      "title": "string",      "url": "http://example.com"    }  ],  "searches": 0,  "pages_read": 0,  "error": {    "message": "string"  }}
GET
/v1/research/{id}

Authorization

bearerAuth
headerAuthorizationBearer <codai_…>

A codai API key (codai_ prefix). Ephemeral tokens from POST /v1/tokens are accepted only by the media surfaces matching their scope (/v1/realtime, /v1/audio/*, /v1/embeddings).

Path Parameters

id*string

Research job UUID returned by POST /v1/research.

Formatuuid

Header Parameters

x-request-id?string

Client correlation id; echoed back as x-codai-trace-id and persisted on the usage row.

Lengthlength <= 128

Response Body

The job.

application/json
  1. response

A deep-research job. Result fields are present only when status is done, error only when it is failed.

id*string
Formatuuid
status*string
Value in"queued""running""done""failed"
created_at*string
Formatdate-time
finished_at?string
Formatdate-time
report?string

Markdown report citing sources as [S1]..[Sn] (absent when output_schema was set).

answer?

JSON object matching output_schema, when one was sent.

sources?array<>
searches?integer

Number of web searches the job ran.

Range0 <= value
pages_read?integer

Number of pages the job read.

Range0 <= value
error?
Example Request
curl -X GET 'https://ai.codai.ro/v1/research/497f6eca-6276-4993-bfeb-53cbbbba6f08'
Example Response
{  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",  "status": "queued",  "created_at": "2019-08-24T14:15:22Z",  "finished_at": "2019-08-24T14:15:22Z",  "report": "string",  "answer": {},  "sources": [    {      "id": "string",      "title": "string",      "url": "http://example.com"    }  ],  "searches": 0,  "pages_read": 0,  "error": {    "message": "string"  }}