Developers
Build search into your product.
Create a project, make an API key and send your first request in a few minutes. This page is about the hosted service.
Quickstart
From nothing to a search result. Replace bsk_YOUR_API_KEY with your own key; the base URL for the hosted service is https://api.boltsearch.app.
- Create an account. Sign up or sign in at the Bolt Search app, with an email and password or with Google. Signing up creates your account and a project that you own.
- Add credits. Searches use credits, and a new project has none, so search requests answer HTTP 402 until you buy a pack from the project’s Billing page. Creating indexes and indexing documents work without credits. See pricing.
- Create an API key. In the project, open Settings, then API Keys, choose a name and a role, editor to write and search or viewer to search only, and copy the key. It is shown once.
- Create an index. Declare your fields and their types.
faston a keyword makes it available for aggregations.Request
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", "fast": true } } } }'Response
HTTP 200 { "acknowledged": true, "index": "movies" } - Index a document. The id in the path is yours to choose. Indexing the same id again replaces the document.
Request
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
HTTP 201 { "_index": "movies", "_id": "1", "result": "created", "_version": 1 } - Search. The first hit is the best match by BM25 score.
Request
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" } }, "size": 10 }'Response
HTTP 200 { "took": 2, "hits": { "total": { "value": 1, "relation": "eq" }, "hits": [{ "_index": "movies", "_id": "1", "_score": 1.0, "_source": { "title": "The Matrix", "year": 1999, "genre": "sci-fi" } }] } }
Every endpoint, query clause and aggregation is in the API reference. To keep a PostgreSQL table searchable without writing indexing code, see PostgreSQL sync.
Authentication
Send the key in the Authorization header on every request.
Authorization: ApiKey bsk_a1b2c3d4e5f6…- A key is scoped to one project and carries a role,
vieweroreditor. It cannot be an owner. Because the key selects the project, you send no project header. - Keys cannot create or delete projects, change members or manage keys and billing. Those actions need a signed-in user in the web console.
- The console itself uses a user’s access token, which expires after 15 minutes by default, together with an
X-Project-IDheader. Programs should use API keys. - Only the SHA-256 hash of a key is stored, so a lost key cannot be shown again. Create a new one and revoke the old one.
| Role | Can |
|---|---|
viewer | Search, count, get documents and indexes, list indexes, read sync jobs and analytics. |
editor | Everything a viewer can, plus create and delete indexes, index, delete and bulk documents, manage data sources and sync jobs, and record clicks. |
TypeScript SDK
A typed client with no runtime dependencies. It uses the built-in fetch of Node.js 18 or newer and ships as both ES modules and CommonJS. Any HTTP client works with the REST API too.
TypeScript
const client = new BoltSearchClient({
baseUrl: 'https://api.boltsearch.app/v1',
apiKey: process.env.BOLT_SEARCH_API_KEY,
retries: 2,
})
const results = await client.search('movies', {
query: { match: { title: 'matrix' } },
size: 10,
})Notes
baseUrl is the API base URL and defaults to https://api.boltsearch.app/v1; the SDK appends paths such as /movies/_search. Keep the key on the server.
The Python SDK is provided on request too: from bolt_search import BoltSearch, then BoltSearch(api_key=…). Its default base URL is https://api.boltsearch.app/v1.
SDK access is provided on request: email support@techsstuff.com.
- Groups:
indices,documents,bulk,clusterandanalytics, plussearch,count,scrollandclearScrollon the client. retriesdefaults to 0 andretryDelayto one second, with exponential back-off and jitter. Only connection errors and 5xx responses are retried, never a 402. A retry is a new attempt for metering.timeoutdefaults to 30 seconds.onRequestandonResponsehooks help with logging.
| Error class | HTTP status | When thrown |
|---|---|---|
ValidationError | 400 | Invalid body or parameters |
NotFoundError | 404 | Index or document does not exist |
ConflictError | 409 | Index already exists |
ConnectionError | — | Server unreachable or request timed out |
BoltSearchError | Any other | Base class; statusCode 402 means credits are exhausted or billing is suspended |
Errors and status codes
Errors use the Elasticsearch shape, so existing error handling for it carries over.
Example error
HTTP 403
{
"error": {
"status": 403,
"type": "security_exception",
"reason": "insufficient project permissions"
},
"status": 403
}Notes
Read error.type to decide what to do and error.reason to log. A request id is returned in the X-Request-ID header: include it when you contact support.
| Status | Type | When | SDK error |
|---|---|---|---|
| 400 | parse_exception | The body is not valid JSON, or a search body could not be parsed. | ValidationError |
| 400 | illegal_argument_exception | size or from is above 10,000, a multi-index search names more than 20 indexes, or the engine rejected an argument. | ValidationError |
| 400 | invalid_index_name_exception | The index name contains __, which is reserved. | ValidationError |
| 400 | validation_exception | A required field of a data source or sync job is missing or invalid, including a custom query the service refuses. | ValidationError |
| 401 | security_exception | The key is missing, unknown or revoked. | BoltSearchError |
| 402 | insufficient_credits or billing_suspended | A search, count or scroll request on a project without credits, or whose billing is suspended. A project that has never bought credits gets insufficient_credits. | BoltSearchError, never retried |
| 403 | security_exception | The key’s role is too low for the endpoint, for example a viewer key that indexes a document. | BoltSearchError |
| 404 | resource_not_found_exception | The index, document, data source or sync job does not exist in this project. | NotFoundError |
| 409 | resource_already_exists_exception | The index already exists. Resetting a sync job that is not stopped answers 409 with illegal_state_exception. | ConflictError |
| 503 | billing_unavailable or unavailable_exception | Billing could not be checked for a metered request, or the search engine was unavailable. | BoltSearchError, retried if retries are set |
Sign-in and account endpoints are rate limited per IP address and answer 429 with the code RATE_LIMITED. Those endpoints are used by the console, not by API keys.
Limits
- Search request body
- 10 MB
- Single document body
- 10 MB
- Bulk request body
- 50 MB
- from and size on a search
- 10,000 each
- Indexes in one multi-index search
- 20, comma separated: /v1/movies,books/_search
- Index name
- Must not contain
__ - Analytics page size
- size defaults to 20 and is capped at 1,000; the range defaults to the last 7 days
Searching is limited by your credits. See how long data is kept.
Usage and credits
Search, count and scroll requests are metered at 10 attempts per credit, and an _msearch request counts one attempt per contained search. Everything else is free to call.
- A multi-index search is one attempt. A request that fails after it was admitted still counts, and so does every retry you send.
- Without credits, a metered request answers HTTP 402 and the SDK does not retry it. Add credits on the project’s Billing page and searches work again.
- Writes, indexing, PostgreSQL sync, analytics and index administration are not metered. Clearing a scroll is free.
- A search from the console’s Explorer is a normal attempt, even when it finds nothing.
Calling from a browser
A page on another website can call your project directly only if its origin is listed.
- Settings, Allowed Origins lists the websites that may call the project from a browser. An empty list allows same-origin requests only.
- Browsers may send
Accept,Authorization,Content-Type,X-Request-ID,X-Project-IDandIdempotency-Key, with GET, POST, PUT, DELETE and OPTIONS. - Anyone who loads the page can read a key that is placed in it. For a public search box, use a viewer key and keep writes on your server.
Create a project, make an API key and send your first search.