The Headband public API lives under the /v1 path of your Headband instance. All requests (except health checks) are authenticated with a Bearer token.
Include your API key as a Bearer token in the Authorization header on every request:
Authorization: Bearer hb_adm_xxxxx...
Headband issues two types of API keys per project. Each key automatically scopes all operations to the project it belongs to.
Admin Key
Prefix: hb_adm_
Full access — create indexes, push and delete documents, manage settings, and search. Keep this key on your server; never expose it to clients.
Search Key
Prefix: hb_src_
Read-only — search, list indexes, view settings and stats. Safe for client-side and frontend use.
A simple health-check endpoint. No authentication required.
/v1/healthCheck whether the Headband API is available.
Auth: none
Returns: 200
{
"status": "available"
}Indexes hold your documents and search configuration. Each index has a unique identifier (uid) and an optional primary key that identifies each document. Indexes are automatically scoped to your project.
/v1/indexesList all indexes in your project.
Auth: admin or search key
Returns: 200
{
"results": [
{
"uid": "products",
"primaryKey": "id",
"createdAt": "2025-01-15T08:30:00Z",
"updatedAt": "2025-01-15T09:12:00Z"
}
]
}/v1/indexesCreate a new index.
Auth: admin key only
Returns: 202
{
"uid": "products",
"primaryKey": "id" // optional
}{
"taskUid": 1,
"indexUid": "products",
"status": "enqueued"
}/v1/indexes/:uidGet information about a single index.
Auth: admin or search key
Returns: 200
{
"uid": "products",
"primaryKey": "id",
"createdAt": "2025-01-15T08:30:00Z",
"updatedAt": "2025-01-15T09:12:00Z"
}/v1/indexes/:uidDelete an index and all its documents.
Auth: admin key only
Returns: 202
{
"taskUid": 4,
"indexUid": "products",
"status": "enqueued"
}Configure search behavior for an index. Changes to settings are processed asynchronously and may trigger a re-index of your documents.
/v1/indexes/:uid/settingsGet all settings for an index.
Auth: admin or search key
Returns: 200
{
"searchableAttributes": ["*"],
"filterableAttributes": [],
"sortableAttributes": [],
"rankingRules": [
"words", "typo", "proximity",
"attribute", "sort", "exactness"
],
"synonyms": {},
"stopWords": [],
"displayedAttributes": ["*"],
"distinctAttribute": null,
"typoTolerance": {
"enabled": true,
"minWordSizeForTypos": {
"oneTypo": 5,
"twoTypos": 9
}
},
"faceting": {
"maxValuesPerFacet": 100
},
"pagination": {
"maxTotalHits": 1000
}
}/v1/indexes/:uid/settingsUpdate settings for an index. Only include the settings you want to change.
Auth: admin key only
Returns: 202
{
"filterableAttributes": ["category", "price"],
"sortableAttributes": ["price", "createdAt"],
"searchableAttributes": ["title", "description"]
}{
"taskUid": 5,
"indexUid": "products",
"status": "enqueued"
}Available Settings
searchableAttributesstring[]Attributes used for search. Order determines relevance ranking.filterableAttributesstring[]Attributes that can be used in filter expressions.sortableAttributesstring[]Attributes that can be used in sort expressions.rankingRulesstring[]Ordered list of ranking rules applied to search results.synonymsobjectMap of words to their synonyms, e.g. { "phone": ["mobile", "cell"] }.stopWordsstring[]Words ignored during search (e.g. "the", "a", "is").displayedAttributesstring[]Attributes returned in search results. Defaults to all.distinctAttributestring | nullDe-duplicate results by this attribute.typoToleranceobjectConfigure typo tolerance behavior and thresholds.facetingobjectConfigure facet behavior (e.g. maxValuesPerFacet).paginationobjectConfigure pagination limits (e.g. maxTotalHits).embeddersobjectConfigure vector embedders for hybrid/semantic search.Retrieve statistics about an index, including document count and field distribution.
/v1/indexes/:uid/statsGet stats for a single index.
Auth: admin or search key
Returns: 200
{
"numberOfDocuments": 19547,
"isIndexing": false,
"fieldDistribution": {
"id": 19547,
"title": 19547,
"price": 19520,
"category": 18230
}
}Documents are JSON objects stored in an index. Headband auto-detects schema from the document structure — no upfront schema definition required. You can send thousands of documents in a single request for bulk ingestion.
/v1/documents?index=productsList documents in an index with pagination.
Supports limit and offset query parameters for pagination.
Auth: admin or search key
Returns: 200
{
"results": [
{ "id": 1, "title": "MacBook Pro", "price": 1999 },
{ "id": 2, "title": "iPhone 16", "price": 999 }
],
"total": 19547,
"limit": 20,
"offset": 0
}/v1/documents/:id?index=productsGet a single document by its primary key.
Auth: admin or search key
Returns: 200
{
"id": 1,
"title": "MacBook Pro",
"price": 1999,
"category": "laptops"
}/v1/documents?index=products&primaryKey=idAdd or replace documents in an index. If a document with the same primary key already exists, it will be replaced.
Supports bulk upload — send thousands of documents in one request.
Auth: admin key only
Returns: 202
[
{ "id": 1, "title": "MacBook Pro", "price": 1999, "category": "laptops" },
{ "id": 2, "title": "iPhone 16", "price": 999, "category": "phones" }
]{
"taskUid": 2,
"indexUid": "products",
"status": "enqueued",
"enqueuedAt": "2025-01-15T09:00:00Z"
}/v1/documents?index=productsDelete documents from an index by IDs or by filter.
Auth: admin key only
Returns: 202
// Delete by IDs:
{ "ids": [1, 2] }
// Or delete by filter:
{ "filter": "price > 1000" }{
"taskUid": 3,
"indexUid": "products",
"status": "enqueued"
}Import large volumes of documents efficiently. The bulk endpoint automatically splits your documents into optimized batches and sends them in parallel, handling payloads of up to 500K documents in a single request.
/v1/bulkImport documents in optimized parallel batches.
Auth: admin key only
Returns: 202
{
"index": "products",
"primaryKey": "id",
"documents": [
{ "id": 1, "title": "Widget", "price": 9.99 },
{ "id": 2, "title": "Gadget", "price": 24.99 }
// ... up to 500K documents
]
}{
"tasks": [
{ "taskUid": 10, "indexUid": "products", "status": "enqueued", "batchNumber": 1, "documentsInBatch": 10000 },
{ "taskUid": 11, "indexUid": "products", "status": "enqueued", "batchNumber": 2, "documentsInBatch": 10000 }
],
"totalDocuments": 20000,
"totalBatches": 2,
"batchSize": 10000
}Parameters
batchSizenumber10000Documents per batch (min 100, max 50000)./v1/bulk/streamImport documents with real-time Server-Sent Events progress. Same request body as /v1/bulk.
Use the streaming endpoint for large imports to get real-time progress feedback. Combine with the Tasks API to poll individual batch status after import.
Auth: admin key only
Returns: 200 (SSE stream)
{
"index": "products",
"primaryKey": "id",
"documents": [
{ "id": 1, "title": "Widget", "price": 9.99 },
{ "id": 2, "title": "Gadget", "price": 24.99 }
// ... up to 500K documents
]
}data: {"event":"batch_complete","batchNumber":1,"taskUid":10,"documentsInBatch":10000}
data: {"event":"batch_complete","batchNumber":2,"taskUid":11,"documentsInBatch":10000}
data: {"event":"complete","totalDocuments":20000,"totalBatches":2}Full-text search with support for filters, faceted search, sorting, highlighting, and hybrid vector search.
/v1/searchSearch an index.
Auth: admin or search key
Returns: 200
{
"index": "products",
"q": "macbook",
"limit": 10,
"offset": 0,
"filter": "price < 2000",
"sort": ["price:asc"],
"facets": ["category"],
"attributesToHighlight": ["title"],
"attributesToRetrieve": ["id", "title", "price"]
}{
"hits": [
{
"id": 1,
"title": "MacBook Pro",
"price": 1999,
"_formatted": {
"title": "<em>MacBook</em> Pro"
}
}
],
"query": "macbook",
"processingTimeMs": 2,
"estimatedTotalHits": 42,
"facetDistribution": {
"category": { "laptops": 12, "phones": 30 }
}
}Parameters
indexstringRequiredThe index uid to search.qstringRequiredThe search query string.limitnumber10Maximum number of hits to return.offsetnumber0Number of hits to skip (for pagination).filterstring""Filter expression, e.g. "price < 2000 AND category = laptops".sortstring[][]Sort order, e.g. ["price:asc", "title:desc"].facetsstring[][]Attributes to compute facet distributions for.attributesToHighlightstring[][]Attributes to wrap matches with <em> tags.attributesToRetrievestring[]["*"]Attributes to include in each hit. Defaults to all.attributesToCropstring[][]Attributes whose values will be cropped around matches.cropLengthnumber10Number of words around a match when cropping.showMatchesPositionbooleanfalseInclude match position information in each hit.showRankingScorebooleanfalseInclude the ranking score in each hit.matchingStrategystring"last"Strategy for matching query terms: "last", "all", or "frequency".hybridobjectnullEnable hybrid search. Example: { semanticRatio: 0.5, embedder: "default" }.vectornumber[]nullVector for nearest-neighbor search (used with hybrid or standalone).Execute multiple search queries in a single request. Each query targets an index and accepts the same parameters as /v1/search.
/v1/multi-searchSearch multiple indexes in a single request.
Each query in the queries array accepts all parameters from the search endpoint, using indexUid instead of index.
Auth: admin or search key
Returns: 200
{
"queries": [
{
"indexUid": "products",
"q": "macbook",
"limit": 5
},
{
"indexUid": "articles",
"q": "macbook review",
"limit": 3,
"attributesToHighlight": ["title"]
}
]
}{
"results": [
{
"indexUid": "products",
"hits": [ ... ],
"query": "macbook",
"processingTimeMs": 1,
"estimatedTotalHits": 12
},
{
"indexUid": "articles",
"hits": [ ... ],
"query": "macbook review",
"processingTimeMs": 2,
"estimatedTotalHits": 5
}
]
}Many operations (index creation, document ingestion, settings updates) are processed asynchronously. These operations return a taskUid you can poll to track progress.
/v1/tasksList all tasks for your project.
Auth: admin or search key
Returns: 200
{
"results": [
{
"uid": 1,
"indexUid": "products",
"status": "succeeded",
"type": "indexCreation",
"enqueuedAt": "2025-01-15T08:30:00Z",
"startedAt": "2025-01-15T08:30:01Z",
"finishedAt": "2025-01-15T08:30:01Z"
},
{
"uid": 2,
"indexUid": "products",
"status": "processing",
"type": "documentAdditionOrUpdate",
"enqueuedAt": "2025-01-15T09:00:00Z",
"startedAt": "2025-01-15T09:00:01Z"
}
]
}/v1/tasks/:taskIdGet the status and details of a single task.
Task statuses: enqueued, processing, succeeded, failed.
Auth: admin or search key
Returns: 200
{
"uid": 2,
"indexUid": "products",
"status": "succeeded",
"type": "documentAdditionOrUpdate",
"details": {
"receivedDocuments": 1500,
"indexedDocuments": 1500
},
"enqueuedAt": "2025-01-15T09:00:00Z",
"startedAt": "2025-01-15T09:00:01Z",
"finishedAt": "2025-01-15T09:00:03Z"
}Get up and running in five steps. Replace the example URL with your own Headband instance.
Create a project in the dashboard
You'll receive an admin key (hb_adm_) and a search key (hb_src_) automatically.
Create an index
curl -X POST https://your-instance.com/v1/indexes \
-H "Authorization: Bearer hb_adm_YOUR_ADMIN_KEY" \
-H "Content-Type: application/json" \
-d '{"uid": "products", "primaryKey": "id"}'Push your documents
curl -X POST https://your-instance.com/v1/documents?index=products&primaryKey=id \
-H "Authorization: Bearer hb_adm_YOUR_ADMIN_KEY" \
-H "Content-Type: application/json" \
-d '[
{"id": 1, "title": "Widget", "price": 9.99},
{"id": 2, "title": "Gadget", "price": 24.99}
]'Search
curl -X POST https://your-instance.com/v1/search \
-H "Authorization: Bearer hb_src_YOUR_SEARCH_KEY" \
-H "Content-Type: application/json" \
-d '{"index": "products", "q": "widget"}'Check task status
curl https://your-instance.com/v1/tasks/2 \ -H "Authorization: Bearer hb_adm_YOUR_ADMIN_KEY"
Headband supports Meilisearch and Typesense backends. The API is engine-agnostic — the same endpoints work regardless of which engine your project uses.
When you create a project, you select the engine type and provide a connection URL. All subsequent API calls are translated to the appropriate engine protocol automatically.
The /v1 API supports CORS for browser-based usage. Search keys are safe to use in frontend applications.
Admin keys should only be used server-side. Never expose admin keys in client-side code, browser requests, or public repositories.
Error Format
All error responses follow a consistent JSON structure:
{
"error": "Index not found: products"
}HTTP Status Codes
200OK — request succeeded.202Accepted — task enqueued for async processing.400Bad Request — invalid parameters or body.401Unauthorized — missing or invalid API key.403Forbidden — key does not have permission for this action.404Not Found — index or resource does not exist.405Method Not Allowed — HTTP method not supported for this endpoint.500Internal Server Error — something went wrong on our end.