API reference

The search endpoint

One call takes a query and returns ranked results from the live web, carrying the readable page text at advanced depth.

Wiring this up with a coding agent? Point it at agents.md or openapi.json rather than at these pages. Both are generated from the code that serves the requests, so neither can describe an endpoint that no longer exists.

POST /v1/search

{
  "query": "what changed in the EU AI act",   // required
  "search_depth": "basic",                     // basic | advanced | fast | ultra-fast
  "topic": "general",                          // general | news
  "max_results": 5,                            // 0-20
  "chunks_per_source": 3,                      // 1-3, passages per page for the answer
  "include_answer": false,                     // false | true | "basic" | "advanced"
  "include_raw_content": false,                // false | true | "markdown" | "text"
  "include_images": false,                     // image urls from inside the article
  "include_favicon": false,                    // the icon each page declares
  "include_domains": [],                       // up to 300 hosts
  "exclude_domains": [],                       // up to 150 hosts
  "time_range": "week",                        // day|week|month|year, or d|w|m|y
  "start_date": "2026-08-01",                  // YYYY-MM-DD
  "end_date": "2026-08-27",                    // YYYY-MM-DD, inclusive
  "country": "united states",                  // alpha-2 code or country name
  "language": "en",                            // ISO 639-1 code or language name
  "exact_match": false,                        // treat the query as a phrase
  "include_usage": false,                      // return the credits actually spent
  "safe_search": false
}

Depth is the cost dial. basic returns a snippet per result and fetches no pages. advanced fetches every result, extracts the readable content, and ranks passages against your query. That is roughly an order of magnitude in both latency and cost.

Two flags imply advanced regardless of what you set. include_answer has nothing to synthesise from without the page text, and include_raw_content asks for that text by name. Setting either one runs the full pipeline and is charged at the advanced rate. We would sooner quote you the higher price than take a parameter and then not honour it.

Topic changes what is searched. general covers the open web. news is tuned for recent events and returns a published_date that general results usually lack.

Response

{
  "query": "...",
  "answer": "The Act entered into force ...",   // null unless include_answer
  "answer_citations": ["https://..."],
  "results": [
    {
      "title": "...",
      "url": "https://example.com/article",
      "content": "# Heading\n\nThe readable content of the page ...",
      "score": 0.98387,
      "published_date": "Tue, 12 Aug 2026 09:14:00 GMT",
      "id": "9f2c...",
      "raw_content": null,
      "fetched": true,
      "fetch_error": null
    }
  ],
  "images": [],
  "usage": { "credits": 2 },
  "response_time": 3.1,
  "request_id": "req_1m11x24ak_k7nt2z54bv6"
}

score runs from 0 to 1, where 1 is the strongest match for your query. It is safe to threshold on directly, and results arrive sorted, so most callers can just take the first few.

At basic depth no page is fetched, so fetched, fetch_error and answer_citations are absent rather than null, and content carries a short snippet instead of the page. Branch on the depth you asked for, not on the presence of those fields.

request_id is on every response, and also on every response header as x-request-id, including the errors that carry no useful body. Quote it when reporting a problem; it is what makes a support mail answerable.

Ids look like req_1m11x24ak_k7nt2z54bv6 - the millisecond the request arrived, then 55 bits of randomness - so they sort by time. They are minted by the server, and a request-id request header is ignored: an id you could choose is one that can collide with somebody else's, which would make it worthless to whoever reads the logs. Keep your own trace id on your side and record ours next to it.

An empty result list is not a failure

results: [] only ever means the search found nothing for that query. It is never how a failure reaches you, so you never have to guess which happened:

You getIt meansDo
200 with resultsNormal.Use them.
200, empty resultsNothing matched.Reword. Retrying will not help.
429Rate limited, with Retry-After.Wait that long, then retry.
502We could not serve the search.Retry shortly. Not your fault, not an empty web.

Ranking already accounts for how strongly a result is corroborated, so score is the single number to threshold on. It runs 0 to 1 and results arrive sorted.

Extract endpoint → Errors →