Search API · PostgreSQL sync · Web console
Hosted search with an Elasticsearch-compatible API.
Index over REST or sync from PostgreSQL, then query with match, term, bool and range.
Authorization: ApiKey bsk_… Content-Type: application/json
{ "query": { "match": { "title": "matrix reloaded" } }, "size": 3 }
"total": { "value": 3, "relation": "eq" }
- { "_id": "2", "_score": 3.02, "_source": { "title": "The Matrix Reloaded", "year": 2003 } },
- { "_id": "1", "_score": 2.31, "_source": { "title": "The Matrix", "year": 1999 } },
- { "_id": "3", "_score": 1.74, "_source": { "title": "The Matrix Revolutions", "year": 2003 } },
What you get
One API, one engine, one console.
Search API
Create indexes, index documents one at a time or in bulk, and query them with match, term, bool and range clauses, sorting, pagination and aggregations.
API referencePOST /v1/movies/_search { "query": { "bool": { "must": [{ "match": { "title": "matrix" } }], "must_not": [{ "range": { "year": { "lt": 1990 } } }] } }, "sort": [{ "year": { "order": "desc" } }], "size": 10 }PostgreSQL sync
Point a job at a table or a SELECT. It polls for rows past a saved cursor and indexes them, and a scheduled resync can rebuild the index and swap it in.
How sync worksSync articlesRunningpublic.articles → articles
- Total synced
- 12,500
- Last cursor
- 2026-01-01T00:00:00Z
- Errors
- 0
07:00:01 [info] polled public.articles, batch of 1000 rows
07:00:01 [info] bulk indexed 1000 documents into articles
07:00:02 [info] full batch returned, polling again
07:00:03 [info] cursor saved
Web console
Manage indexes, search documents in the Explorer, connect PostgreSQL databases, watch syncs, read search analytics and issue API keys from a browser.
The console- Indices
- Connections
- Explorer
- Analytics
- API keys
- Webhooks
Projects and keys
Every project is isolated, with editor and viewer API keys, allowed origins for browser calls and its own prepaid credit balance.
Roles and keysBackend servicebsk_a1b2c3…editorActiveSearch widgetbsk_d4e5f6…viewerActive
Your first search in three requests
Familiar Elasticsearch-style endpoints under /v1. Send Authorization: ApiKey bsk_…: the key selects its project, so no project header is needed, and it carries an editor or viewer role.
- Base URL
https://api.boltsearch.app- Auth
Authorization: ApiKey bsk_…- Field types
textkeywordintegerfloatbooleandate
Request PUT /v1/{index}
curl -X PUT https://api.boltsearch.app/v1/movies \
-H 'Authorization: ApiKey bsk_YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{"mappings":{"properties":{
"title":{"type":"text"},
"year":{"type":"integer"},
"genre":{"type":"keyword"}}}}'Response
{
"acknowledged": true,
"index": "movies"
}Request PUT /v1/{index}/_doc/{id}
curl -X PUT https://api.boltsearch.app/v1/movies/_doc/1 \
-H 'Authorization: ApiKey bsk_YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{"title":"The Matrix","year":1999,"genre":"sci-fi"}'Response
{
"_index": "movies",
"_id": "1",
"result": "created",
"_version": 1
}Request POST /v1/{index}/_search
curl -X POST https://api.boltsearch.app/v1/movies/_search \
-H 'Authorization: ApiKey bsk_YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{"query":{"match":{"title":"matrix"}},
"from":0,"size":10,
"sort":[{"year":{"order":"desc"}}]}'Response
{
"hits": {
"total": { "value": 1, "relation": "eq" },
"max_score": 1.0,
"hits": [{
"_index": "movies", "_id": "1", "_score": 1.0,
"_source": { "title": "The Matrix", "year": 1999 }
}]
}
}TypeScript
const client = new BoltSearchClient({
baseUrl: 'https://api.boltsearch.app/v1',
apiKey: process.env.BOLT_SEARCH_API_KEY,
})
const results = await client.search('movies', {
query: { match: { title: 'matrix' } },
})Install
No runtime dependencies: it uses native fetch (Node.js 18 or newer) and ships as ESM and CJS. An HTTP 402 arrives as a BoltSearchError. A Python SDK is also provided on request: from bolt_search import BoltSearch. Email support for SDK access.
How it works
One REST API in front of one search engine. The console and your code use the same calls.
- Each request is authenticated by key, resolved to a project and checked against the key’s role before it reaches the engine.
- PostgreSQL rows reach the same index through a sync worker that polls your database.
- Searches use credits. Indexing, sync and analytics do not.
- Callercurl, an SDK or the web consoleAuthorization: ApiKey bsk_…HTTPS
- REST APIauthenticate the keyresolve the project, check the rolecheck credits, prefix index namesgRPC
- Search engineparses the queryBM25 ranking, aggregationsreads
- Index filesone set per indexnamed with the project prefixkept on disk
Security and data handling
A few facts, described in full on the security page.
- API keys
- Shown once, stored only as SHA-256 hashes. Each key has one project and one role.
- Isolation
- Every project’s indexes are namespaced, and a key cannot manage projects, members or billing.
- Your database
- Sync jobs only run SELECT statements. The database password is write-only.
- Payments
- Card details are entered on Stripe-hosted checkout and never reach Techsstuff LLC.
Pricing
Metered usage: every search attempt draws from prepaid credits, bought in packs from $10 to $210 USD. No subscription, and credits never expire. 1 credit = 10 search attempts. Above the $210 pack, contact sales.
- Metered
- Search, count and scroll requests
- Not metered
- Writes, indexing, sync and analytics
- searches for $10
- 70,000
- credits for $210
- 147,000
- search attempts per credit
- 10
- packs, no subscription
- 12
FAQ
Is it the same as Elasticsearch?
No. Bolt Search is a search engine built from scratch on Tantivy, with an Elasticsearch-compatible REST API. It supports a subset of the query language: match_all, match, term, bool and range, plus terms, metric and range aggregations.
Which databases can it sync from?
PostgreSQL. A sync job reads a table or a custom SELECT query and indexes every returned column. You can also push documents from any source with the REST API.
How does the sync know what is new?
You choose a cursor column that only increases, such as updated_at or an auto-increment id. Each poll fetches the rows beyond the saved cursor, and the cursor is saved after each successful batch.
Is there a client library?
Yes, a TypeScript SDK with no runtime dependencies and a Python SDK; email support for access. Any HTTP client works with the REST API.
How is usage counted?
Search, count and scroll requests are metered at 10 attempts per credit; an _msearch request counts one attempt per contained search. Writes, indexing, sync and analytics are not. See the pricing page for packs.