Back
Headband

API Reference

The Headband public API lives under the /v1 path of your Headband instance. All requests (except health checks) are authenticated with a Bearer token.

Authentication

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.

Health

A simple health-check endpoint. No authentication required.

GET
/v1/health

Check whether the Headband API is available.

Auth: none

Returns: 200

Response
{
  "status": "available"
}

Indexes

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.

GET
/v1/indexes

List all indexes in your project.

Auth: admin or search key

Returns: 200

Response
{
  "results": [
    {
      "uid": "products",
      "primaryKey": "id",
      "createdAt": "2025-01-15T08:30:00Z",
      "updatedAt": "2025-01-15T09:12:00Z"
    }
  ]
}
POST
/v1/indexes

Create a new index.

Auth: admin key only

Returns: 202

Request body
{
  "uid": "products",
  "primaryKey": "id"   // optional
}
Response
{
  "taskUid": 1,
  "indexUid": "products",
  "status": "enqueued"
}
GET
/v1/indexes/:uid

Get information about a single index.

Auth: admin or search key

Returns: 200

Response
{
  "uid": "products",
  "primaryKey": "id",
  "createdAt": "2025-01-15T08:30:00Z",
  "updatedAt": "2025-01-15T09:12:00Z"
}
DELETE
/v1/indexes/:uid

Delete an index and all its documents.

Auth: admin key only

Returns: 202

Response
{
  "taskUid": 4,
  "indexUid": "products",
  "status": "enqueued"
}

Index Settings

Configure search behavior for an index. Changes to settings are processed asynchronously and may trigger a re-index of your documents.

GET
/v1/indexes/:uid/settings

Get all settings for an index.

Auth: admin or search key

Returns: 200

Response
{
  "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
  }
}
PATCH
/v1/indexes/:uid/settings

Update settings for an index. Only include the settings you want to change.

Auth: admin key only

Returns: 202

Request body
{
  "filterableAttributes": ["category", "price"],
  "sortableAttributes": ["price", "createdAt"],
  "searchableAttributes": ["title", "description"]
}
Response
{
  "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.

Index Stats

Retrieve statistics about an index, including document count and field distribution.

GET
/v1/indexes/:uid/stats

Get stats for a single index.

Auth: admin or search key

Returns: 200

Response
{
  "numberOfDocuments": 19547,
  "isIndexing": false,
  "fieldDistribution": {
    "id": 19547,
    "title": 19547,
    "price": 19520,
    "category": 18230
  }
}

Documents

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.

GET
/v1/documents?index=products

List documents in an index with pagination.

Supports limit and offset query parameters for pagination.

Auth: admin or search key

Returns: 200

Response
{
  "results": [
    { "id": 1, "title": "MacBook Pro", "price": 1999 },
    { "id": 2, "title": "iPhone 16", "price": 999 }
  ],
  "total": 19547,
  "limit": 20,
  "offset": 0
}
GET
/v1/documents/:id?index=products

Get a single document by its primary key.

Auth: admin or search key

Returns: 200

Response
{
  "id": 1,
  "title": "MacBook Pro",
  "price": 1999,
  "category": "laptops"
}
POST
/v1/documents?index=products&primaryKey=id

Add 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

Request body
[
  { "id": 1, "title": "MacBook Pro", "price": 1999, "category": "laptops" },
  { "id": 2, "title": "iPhone 16", "price": 999, "category": "phones" }
]
Response
{
  "taskUid": 2,
  "indexUid": "products",
  "status": "enqueued",
  "enqueuedAt": "2025-01-15T09:00:00Z"
}
DELETE
/v1/documents?index=products

Delete documents from an index by IDs or by filter.

Auth: admin key only

Returns: 202

Request body
// Delete by IDs:
{ "ids": [1, 2] }

// Or delete by filter:
{ "filter": "price > 1000" }
Response
{
  "taskUid": 3,
  "indexUid": "products",
  "status": "enqueued"
}

Bulk Import

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.

POST
/v1/bulk

Import documents in optimized parallel batches.

Auth: admin key only

Returns: 202

Request body
{
  "index": "products",
  "primaryKey": "id",
  "documents": [
    { "id": 1, "title": "Widget", "price": 9.99 },
    { "id": 2, "title": "Gadget", "price": 24.99 }
    // ... up to 500K documents
  ]
}
Response
{
  "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).

Streaming Progress

POST
/v1/bulk/stream

Import 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)

Request body
{
  "index": "products",
  "primaryKey": "id",
  "documents": [
    { "id": 1, "title": "Widget", "price": 9.99 },
    { "id": 2, "title": "Gadget", "price": 24.99 }
    // ... up to 500K documents
  ]
}
Response
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}

Tasks

Many operations (index creation, document ingestion, settings updates) are processed asynchronously. These operations return a taskUid you can poll to track progress.

GET
/v1/tasks

List all tasks for your project.

Auth: admin or search key

Returns: 200

Response
{
  "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"
    }
  ]
}
GET
/v1/tasks/:taskId

Get the status and details of a single task.

Task statuses: enqueued, processing, succeeded, failed.

Auth: admin or search key

Returns: 200

Response
{
  "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"
}

Quick Start

Get up and running in five steps. Replace the example URL with your own Headband instance.

1

Create a project in the dashboard

You'll receive an admin key (hb_adm_) and a search key (hb_src_) automatically.

2

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"}'
3

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}
  ]'
4

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"}'
5

Check task status

curl https://your-instance.com/v1/tasks/2 \
  -H "Authorization: Bearer hb_adm_YOUR_ADMIN_KEY"

Engine Compatibility

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.

CORS

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.

Errors

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.