Response Shaping
Response shaping lets you control what the bucket search endpoint returns and how each result is formatted. Use it to trim fields for smaller payloads, inject formatted citations, or pull in graph neighbors for retrieved chunks.
Note: For fully assembled answer context with
context,citations,status, andoperational_status, use the Query & Search endpoint. The bucket search endpoint returns raw ranked chunks and is better suited when you own the downstream assembly.
API Versions
Section titled “API Versions”| Version | Status | Notes |
|---|---|---|
v2 | Current | POST /v2/buckets/\{bucket_id\}/search. Use for all new integrations. |
v1 | Deprecated | POST /v1/buckets/\{bucket_id\}/search is kept for existing clients and returns Deprecation, Warning, and Link headers pointing to the v2 successor. |
POST /v2/buckets/{bucket_id}/search
Section titled “POST /v2/buckets/{bucket_id}/search”Search a bucket and shape the returned chunks.
Path parameters
Section titled “Path parameters”| Name | Type | Description |
|---|---|---|
bucket_id | string | UUID or slug of the bucket to search. |
Request headers
Section titled “Request headers”| Header | Value |
|---|---|
Authorization | Bearer $SCHIFT_API_KEY |
Content-Type | application/json |
Request body
Section titled “Request body”| Field | Type | Required | Default | Description |
|---|---|---|---|---|
query | string | Yes | — | Natural-language query. Maximum 8,192 characters. |
top_k | integer | No | 10 | Maximum number of results to return (1–1000). |
mode | string | No | "hybrid" | "vector" or "hybrid". |
rerank | boolean | No | false | Whether to rerank candidates. |
min_score | number | No | null | Minimum score threshold (0.0–1.0). |
include_fields | array of string | No | null | Whitelist of result fields, e.g. ["id", "score", "metadata.title"]. Legacy raw-result control. |
exclude_fields | array of string | No | null | Blacklist of result fields, e.g. ["text", "metadata.source_url"]. Legacy raw-result control. |
citation_format | string | No | null | Template for per-result citation, e.g. "[\{title\}:p.\{page\}]". Legacy raw-result control. |
expand_neighbors | object | No | null | Fetch graph neighbors for each hit. See neighbor expansion. |
expand_context | object | No | null | Add same-document adjacent chunks before rerank. |
debug | boolean | No | false | Include detailed debug timings and per-chunk scores. |
Response
Section titled “Response”| Field | Type | Description |
|---|---|---|
bucket_id | string | Bucket that was searched. |
query | string | Query that was executed. |
search_id | string | null | Server-generated search identifier. |
results | array | Matching chunks, ordered by relevance. |
results[].id | string | Chunk identifier. |
results[].score | number | Final relevance score. |
results[].text | string | Chunk text. |
results[].metadata | object | Chunk metadata, including bucket_id and collection_id. |
results[].citation | string | null | Formatted citation when citation_format is set. |
results[].neighbors | array | null | Graph neighbors when expand_neighbors is set. |
degraded | boolean | Whether the response was produced in a degraded mode. |
warnings | array | Search warnings, if any. |
debug | object | null | Debug info when debug: true. |
Field projection
Section titled “Field projection”include_fields and exclude_fields control which keys appear in each result. Both support dotted paths such as metadata.title.
include_fieldswhitelists keys. When set, only listed top-level keys and requested metadata sub-keys are returned.exclude_fieldsblacklists keys. When set, listed top-level keys and metadata sub-keys are removed.- If both are set,
include_fieldstakes precedence.
Note:
id,score, andtextare always populated with defaults so that results remain valid even if projection drops them.
Citation formatting
Section titled “Citation formatting”When citation_format is provided, each result gets a citation string built by substituting \{key\} tokens. Tokens are resolved from the result first, then from metadata. Unknown tokens render as empty strings.
For example, with metadata {"title": "Terms", "page": 3} and format "[\{title\}:p.\{page\}]", the citation becomes "[Terms:p.3]".
Neighbor expansion
Section titled “Neighbor expansion”expand_neighbors fetches graph edges connected to each hit.
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
relations | array of string | No | null | Filter to these relation types. null means all. |
direction | string | No | "both" | "outgoing", "incoming", or "both". |
max_per_hit | integer | No | 10 | Maximum edges returned per hit (1–100). |
Each returned neighbor has:
| Field | Type | Description |
|---|---|---|
id | string | Neighbor node ID. |
relation | string | Relation type, e.g. follows, has_child. |
direction | string | "outgoing" or "incoming". |
weight | number | Edge weight. |
Example request
Section titled “Example request”curl -X POST ${API_BASE_URL:-https://api.schift.io}/v2/buckets/product-docs/search \ -H "Authorization: Bearer $SCHIFT_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "query": "annual leave policy", "top_k": 5, "min_score": 0.7, "citation_format": "[{title}:p.{page}]", "expand_neighbors": { "relations": ["references", "has_child"], "direction": "both", "max_per_hit": 3 }, "debug": true }'Example response
Section titled “Example response”{ "bucket_id": "product-docs", "query": "annual leave policy", "search_id": "search_0a1b2c3d4e5f", "results": [ { "id": "chunk_01j8x9q2mvn9q", "score": 0.91, "text": "Full-time employees receive 20 days of paid annual leave per year.", "metadata": { "bucket_id": "product-docs", "collection_id": "col_123", "title": "Employee Handbook", "page": 12, "doc_type": "policy" }, "citation": "[Employee Handbook:p.12]", "neighbors": [ { "id": "chunk_01j8x9q2mvna0", "relation": "references", "direction": "outgoing", "weight": 1.0 } ] } ], "degraded": false, "warnings": [], "debug": { "query_embedding_model": "schift-embed-v1", "search_method": "hybrid", "timing_ms": { "embedding": 23, "vector_search": 18, "bm25": 9, "hydration": 4, "total": 62 }, "results_detail": [ { "chunk_id": "chunk_01j8x9q2mvn9q", "vector_score": 0.88, "bm25_score": 0.72, "rrf_score": 0.85, "final_score": 0.91, "source": "hybrid" } ] }}Error examples
Section titled “Error examples”// 400 Bad Request — missing query{ "detail": "query or query_vector is required"}// 400 Bad Request — invalid filter{ "detail": "Invalid filter: unsupported operator"}// 402 Payment Required — search quota exhausted{ "allowed": false, "reason": "quota_exceeded"}// 403 Forbidden — search quota unavailable{ "detail": "Search quota unavailable. Upgrade your plan."}// 404 Not Found{ "detail": "Bucket not found"}// 500 Internal Server Error{ "detail": "Bucket search failed"}Legacy v1 endpoint
Section titled “Legacy v1 endpoint”POST /v1/buckets/\{bucket_id\}/search is deprecated. It returns the same payload shape but adds these response headers:
| Header | Value |
|---|---|
Deprecation | true |
Warning | 299 - "Deprecated search endpoint; migrate to /v2/buckets/\{bucket_id\}/search" |
Link | </v2/buckets/\{bucket_id\}/search>; rel="successor-version" |