Hanzo

Search

Package provisioning is one-click data add-ons: a SQL, key-value, document, vector, search or object store, wired straight into your app.

Package provisioning is one-click data add-ons: a SQL, key-value, document, vector, search or object store, wired straight into your app.

Base URLhttps://api.hanzo.ai
Operations7
AuthAuthorization: Bearer $HANZO_API_KEY

GET /v1/search/{name}

Returns one search index's metadata. It carries the index's status and the gateway address it is reached at, and no username: the backend authenticates with a shared, out-of-band key rather than a per-index credential.

ParameterInTypeRequiredDescription
namepathstringyesName is the resource's org-unique slug, from the path.

DELETE /v1/search/{name}

Deletes one search index from the shared backend and removes its metadata row. Answers 204 with no body; a second call is a 404.

ParameterInTypeRequiredDescription
namepathstringyesName is the resource's org-unique slug, from the path.

GET /v1/search/indexes

Lists the search indexes with their document counts and timestamps.

It reads the in-cluster Meilisearch service and reshapes its /stats and /indexes replies into the rows the console's Search panel renders. The read is degrade-friendly by design: an unreachable Meilisearch answers 200 with an EMPTY list, so the panel shows an honest empty state instead of an error. createdAt falls back to now and lastIndexedAt to null when the index list is unavailable.

ParameterInTypeRequiredDescription
AuthorizationheaderstringAuthorization carries the surface's bearer key (Bearer <key>); the bare key is accepted too.

GET /v1/search/stats

Totals the documents across every search index.

totalDocuments is summed from Meilisearch's own per-index counts. The other three fields are structurally zero rather than estimated: Meilisearch keeps no query-history counters, so searches, sessions and the per-day series are not derivable from the index and this surface reports the honest zero instead of a fabricated number. An unreachable Meilisearch answers 200 with all zeros.

ParameterInTypeRequiredDescription
AuthorizationheaderstringAuthorization carries the surface's bearer key (Bearer <key>); the bare key is accepted too.

GET /v1/search

Lists the caller org's search indexes. An index is a logical resource inside an already-live shared backend, so every one of them is reached through the public gateway rather than at an instance of its own.

POST /v1/search

Provision a search index for your org

Creates a search index inside the already-running shared search backend and answers with the endpoint that reaches it.

name is the org-unique slug every physical name derives from, and must match ^a-z0-9?$. instance optionally BINDS the add-on to one of your app instances: the DSN is injected into that instance's addons secret as <KIND>_URL, switching the app off its built-in store and onto this one. Omit it and the connection string is yours to wire.

THE CREDENTIAL COMES BACK ONCE. The connection string and password are in this response and nowhere else — every read beside it omits the password — so a caller that does not keep them has to provision again. Where KMS is configured the password is sealed there and only a reference is persisted; where it is not, it is returned this once and stored nowhere. It is never held in plaintext.

Scoped to the caller's validated org (403 without one), which also namespaces the physical resource under a fixed-width hash, so two tenants can never fold onto one backend resource — a residual collision fails closed with 409 rather than silently sharing. A name already taken in your org is 409; an invalid name or instance slug is 400; a backend that refuses the create is 502. Where a later step fails after the backend resource already exists, it is torn back down rather than left orphaned.

Billing is gated BEFORE anything is created: an unfunded org — or, in the fail-closed default, an unreachable meter — gets the fleet-wide 402/503 and nothing is provisioned. The fee is per-kind and set by the deployment.

Request bodyapplication/json

FieldTypeRequiredDescription
instancestring
namestring

websearch

POST /v1/websearch

Search the live web

Searches the live web and answers with ranked results.

This is the fleet's path to what is happening RIGHT NOW — today's weather, an outage, a release that postdates any model's training. q is the query and language narrows it to a locale. The answer is &#123;query, number_of_results, results:[&#123;url, title, content, engine&#125;]&#125;, where content is the ENGINE's snippet and not the page: read a page with POST /v1/crawl.

It is served in-process by a Go meta-search over keyless public engines — never a third-party search API and never a search key. The enabled engines run concurrently and their hits are merged, deduplicated by normalised URL (host and path, trailing slash and fragment dropped, query kept, so distinct queries stay distinct results) and capped at 30. Ranking is deterministic rather than scored: the first configured engine's hits lead.

It fails SOFT on the engines. One that errors, times out or is served a bot-challenge page contributes zero results and never fails the call, so an empty results is a real answer — nothing was found — and not an outage. The array is always present, never null.

A VALIDATED PRINCIPAL IS REQUIRED, and there is no tenant beyond that: the results are public web pages, identical for every caller, so nothing here is scoped and nothing here can leak across orgs. A typed op is also an MCP tool and a CLI command, and tools/call invokes it with no route and therefore no middleware — so the gate is in the handler, where every door reaches it, rather than in a middleware only one door passes through.

Request bodyapplication/json (required)

FieldTypeRequiredDescription
languagestringLanguage narrows the engines to a locale, BCP-47-ish ("en", "ja", "de").
qstringQ is the query.

Search guide · All Hanzo APIs · Interactive reference

How is this guide?

On this page