Skip to main content
POST /v1/search runs ranked retrieval over canonical web documents. Every result carries stable handles (doc_id, canonical_url) you can pass straight to /v1/document, plus provenance you can cite.
curl -s https://search-api-staging-779189860552.europe-west1.run.app/v1/search \
  -H "Content-Type: application/json" \
  -d '{
    "query": "postgres 17 logical replication failover",
    "mode": "standard",
    "max_results": 5
  }'
Anonymous access works as written. Send Authorization: Bearer $CAESAR_API_KEY only if you have a partner key for higher throughput — see authentication.

Modes

mode sets retrieval depth. Default is standard. Any other value returns 400 unsupported_mode.
faststandard (default)research
Second-stage rerankingno (first-stage order)yesyes
Extra per-result snippetsnoyesyes
Additional context-enrichment pass (richer snippets and passages per result)nonoyes
Reranking is a modular second stage and never fails a request: if it is unavailable, results fall back to first-stage order with warning rerank_unavailable and ranking.ranker_version reports first_stage_order_v1.

Query and query variants

query is the only required field — the original user or agent question. search_queries optionally supplies your own rewrites as an array of strings: the first entry, when non-empty, replaces query as the candidate first-stage query, and the full list is given as context to the server-side query transform. If your agent already produced good rewrites, send them — you skip a round of server-side guessing.

max_results

max_results is an integer from 1 to 50, default 10. It is the complete result window — there is no cursor or offset pagination. The server fills the window itself by paging first-stage retrieval internally and deduplicating URLs, so asking for 50 just works; you never page manually. You may still receive fewer than max_results when sources run dry. That is not an error and does not set the envelope truncated flag — truncated refers only to response-shaping budget sheds.

Filters

FieldTypeEffect
filters.countrystring (single value)forwarded to first-stage retrieval
filters.languagestring (single value)forwarded to first-stage retrieval
filters.exact_matchbooleanwraps the candidate query in double quotes (exact phrase) unless it is already quoted

Freshness policy

FieldAcceptsBehavior
freshness_policy.published_afterRFC3339 timestamp or YYYY-MM-DDmapped to a coarse recency window — past day, past week, past month, past year, or an explicit YYYY-MM-DDtoYYYY-MM-DD range for older dates. Unparseable values are ignored.
freshness_policy.freshnessraw window token: pd, pw, pm, py, or YYYY-MM-DDtoYYYY-MM-DDpassed through to the search infrastructure; used only when published_after is absent

Source policy

FieldTypeEffect
source_policy.include_domainsstring[]with exactly one domain, the first-stage query is scoped with a site: operator; all entries also act as a post-retrieval allow list
source_policy.exclude_domainsstring[]post-retrieval deny list
source_policy.require_domain_matchbooleanwhen true and include_domains is non-empty, results not matching the allow list are dropped
Domain matching is host-suffix based: example.com matches example.com and any subdomain; a leading www. is ignored. When the policy removes results, the response carries warning source_policy_filtered with details.filtered_results counting what was dropped — so a thin result set is explainable rather than silent.

The ranking block

Successful responses include a ranking object describing how results were ordered:
FieldValues
modeechoes the request mode: fast, standard, or research
ranker_versionfirst_stage_order_v1 (first-stage provider order, no rerank) or reranked_v1 (second-stage reranker reordered results)
score_scopealways response_local
Scores are response-local. A result score (an object like {"value": 0.87}, present only when the rerank stage scored that result) is comparable to other scores in the same response only — never across responses, modes, or ranker versions. Do not persist scores as absolute relevance.
Replayed searches may be served from cache; deterministic ordering, stable scores, and identical search_id values are not guaranteed across calls.

Reserved request fields

These fields are schema-valid and accepted today, but not forwarded into retrieval. Sending them is harmless; expecting behavior from them is a bug.
FieldStatus
objectivereserved — intended to let agents shape retrieval with a task objective
client_modelreserved — calling-model identifier for analytics and tuning
contentreserved — content-return controls have no effect on /v1/search
debugreserved — internal evaluation only

A full request

Every implemented request field in one call (the response block is covered in response shaping):
cURL
curl -s https://search-api-staging-779189860552.europe-west1.run.app/v1/search \
  -H "Content-Type: application/json" \
  -d '{
    "query": "postgres 17 logical replication failover",
    "search_queries": ["postgres 17 failover slot synchronization"],
    "mode": "research",
    "max_results": 20,
    "filters": { "country": "us", "language": "en", "exact_match": false },
    "freshness_policy": { "published_after": "2024-09-01" },
    "source_policy": {
      "include_domains": ["postgresql.org"],
      "require_domain_match": true
    },
    "response": { "verbosity": "standard" }
  }'

The response

Trimmed to one result, at the default standard verbosity:
{
  "request_id": "5f0c2c4e-1d2a-4f6b-9e0a-7c1b2d3e4f50",
  "search_id": "a7e2b9c1-3d4f-4a5b-8c6d-9e0f1a2b3c4d",
  "session_id": "b1c2d3e4-f5a6-4b7c-8d9e-0f1a2b3c4d5e",
  "access": { "tier": "api_key", "rate_limit": { "limit_rps": 100, "remaining": 99, "reset_at": "2026-06-12T10:00:01Z" } },
  "ranking": { "mode": "standard", "ranker_version": "reranked_v1", "score_scope": "response_local" },
  "results": [
    {
      "rank": 1,
      "doc_id": "0c944fa8-4c8f-4f48-9b08-0fb2fd3438ec",
      "canonical_url": "https://www.postgresql.org/docs/17/logical-replication-failover.html",
      "source_url": "https://www.postgresql.org/docs/17/logical-replication-failover.html",
      "title": "Logical Replication Failover",
      "description": "How to ensure logical replication continues after failover…",
      "snippet": "When the publisher server fails, the subscriber can be redirected…",
      "score": { "value": 0.87 },
      "metadata": {
        "first_seen_at": "2026-06-12T09:58:00Z",
        "last_seen_at": "2026-06-12T09:58:00Z",
        "last_crawled_at": "2026-06-12T09:58:00Z",
        "extracted_at": "2026-06-12T09:58:00Z",
        "content_digest": "sha256:3f6e…",
        "published_at": "2024-09-26T00:00:00Z"
      },
      "passages": [
        { "passage_id": "d4e5f6a7-b8c9-4d0e-9f1a-2b3c4d5e6f70", "doc_id": "0c944fa8-4c8f-4f48-9b08-0fb2fd3438ec", "ordinal": 1, "text": "When the publisher server fails…" }
      ]
    }
  ],
  "usage": { "requests": 1, "bytes_returned": 2148, "approx_tokens": 537 }
}
Notes on the envelope:
  • search_id is the handle for /v1/feedback. session_id echoes yours or is server-generated — see sessions.
  • Per-result provenance (capture_id, capture_time) appears only at response.verbosity: "full" — the default standard omits it. See response shaping.
  • usage.approx_tokens is bytes_returned divided by 4, rounded up — a documented estimate, not a tokenizer count.
  • Error responses use a shared envelope with stable machine codes — see errors. Full field schemas live in the API reference.