Search API
Overview
POST /v1/search runs the same retrieval pipeline that powers grounded answers — same agent scope, same bucket stores, same source enrichment — and returns the evidence itself: ranked passages with their source attributes. No answer is synthesized.
Use it when your application wants to do its own reasoning:
- an agent that gathers evidence and synthesizes with its own model
- a "related sources" or semantic-search UI over your knowledge
- evaluating what retrieval would find before asking for an answer
Because search results and answer citations share one contract, a source you see here carries the same source_index, label, and locator attributes you would find in a Responses reply's file_search_call.results[].
- Endpoint:
POST /v1/search - Base URL:
https://api.calypso.so/v1 - Authentication: Bearer project API key — see Authentication
Basic request
curl -X POST "https://api.calypso.so/v1/search" \
-H "Authorization: Bearer $CALYPSO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"query": "refund policy for international orders"
}'
By default the search runs over the default agent's retrieval scope — the same buckets and sources calypso-agent would answer from.
Request parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
query | string | required | The search query (1–4000 chars). |
agent | string | calypso-agent | Search a specific agent's scope: the default agent or a named agent (calypso-agent:{agent_id}). Mutually exclusive with buckets. |
buckets | array | — | Search specific buckets directly (ids or slugs, up to 5). Mutually exclusive with agent. |
max_results | integer | 10 | Maximum results returned (1–20). Retrieval always searches a larger internal candidate pool (at least 10, up to 2× max_results, capped at 20) before truncating — so a small max_results still surfaces the best-ranked matches; it just returns fewer of them. |
depth | string | fast | fast runs one bounded retrieval call (the historical behavior). standard runs 2–3 bounded searches in parallel — your additional_queries plus resamples of the primary — and merges the results by deduped best rank. Retrieval misses are stochastic, so standard materially raises recall on short keyword queries at the cost of extra retrieval tokens; latency stays that of one call. |
additional_queries | array | — | Up to 2 extra phrasings searched in parallel when depth: "standard" (no model call is spent generating them — you supply the rephrasings). Ignored on depth: "fast". |
depth: "standard" with a question-shaped
additional_queries entry.Searching specific buckets
curl -X POST "https://api.calypso.so/v1/search" \
-H "Authorization: Bearer $CALYPSO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"query": "refund policy",
"buckets": ["support-handbook"],
"max_results": 5
}'
Buckets accept ids or slugs. The search is scoped by store selection, exactly as a bucket-scoped agent answer would be.
Response
{
"object": "search.results",
"query": "refund policy for international orders",
"agent": "calypso-agent",
"strategy": "bucket_stores",
"depth": "fast",
"results": [
{
"source_index": 1,
"type": "file_citation",
"title": "refund_policy_2026.pdf",
"text": "Customers may request a full refund within 30 days of purchase.",
"file_id": "kb-1",
"filename": "refund_policy_2026.pdf",
"url": null,
"attributes": {
"source_index": 1,
"label": "refund_policy_2026.pdf (p. 4)",
"page_number": 4,
"locator_label": "p. 4",
"source_type": "file",
"knowledge_id": "kb-1"
}
}
],
"usage": {
"input_tokens": 812,
"output_tokens": 4,
"total_tokens": 816
},
"request_id": "req_abc123"
}
| Field | Description |
|---|---|
strategy | How the scope mapped to stores: bucket_stores, bucket_stores_degraded, explicit_selected_files, all_team_files, or scope_disabled / scope_empty (nothing to search → empty results). bucket_stores_degraded means at least one bucket in scope could not be read or prepared and was dropped — results come from the surviving buckets, so treat them as partial coverage rather than a complete answer. |
results[].source_index | Stable 1-based numbering, same convention as answer citations. |
results[].text | The retrieved passage supporting the match. |
results[].attributes | The same attribute set answer citations carry: label, page_number, locator_label, modality, access_url, and more when available. |
usage | Real provider token usage for the retrieval call. |
Errors
| Status | Code | Meaning |
|---|---|---|
| 400 | invalid_request | Both agent and buckets provided, or malformed body. |
| 404 | model_not_found | agent is not a Calypso agent model id. |
| 404 | agent_not_found | The named agent does not exist. |
| 404 | bucket_not_found | A named bucket does not exist or is archived. |
| 400 | metadata_filter_too_large | The agent's explicit-id scope is too large for one search — use bucket scope instead of explicit ids. |
| 409 | bucket_store_indexing_pending | The bucket has no indexed content yet — retryable. |
| 429 | rag_quota_exceeded | The workspace reached its plan limit. Searches are metered like answers. |
| 504 | search_timeout | Retrieval exceeded its latency budget — retryable. |
| 502 | search_failed | The search provider failed — retryable. On depth: "standard", per-call failures degrade to the surviving calls; this error means every parallel call failed. |
| 503 | search_disabled | Search is temporarily disabled for maintenance — retryable. |
All errors use the standard error envelope.
Billing
A served search is metered like a served answer: it runs real retrieval against the provider and its token usage is recorded. Quota-exhausted workspaces receive 429 exactly as they would on the ask endpoints.
Next steps
- Responses API — the ask surface these sources also power
- Citations and sources — the shared source contract
- Ingest — get knowledge into buckets