Hanzo
OpenapiWebsearch

Search the live web

Searches the live web and answers with ranked results.

POST /v1/websearch

Addresshttps://api.hanzo.ai/v1/websearch
MethodPOST
Operationsearch_web
AuthAuthorization: Bearer $HANZO_API_KEY

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 {query, number_of_results, results:[{url, title, content, engine}]}, 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

2 fields, body application/json (required).

FieldInTypeRequiredDescription
languagebodystringLanguage narrows the engines to a locale, BCP-47-ish ("en", "ja", "de").
qbodystringQ is the query.

Response

StatusBodyMeaning
200webSearchResultsok

200 body — 11 fields.

FieldInTypeAlwaysDescription
enginesbodywebEngine[]Engines is one entry per engine asked, in the order they were asked.
engines[].namebodystringName is the engine, matching the engine stamped on each result.
engines[].outcomebodystringOutcome is "answered", "blind" or "failed" — see outcome.go.
engines[].resultsbodyintegerResults is how many hits this engine contributed, before the merge deduplicated them against the others.
number_of_resultsbodyintegerNumberOfResults is len(results) — what this answer carries, never an estimate of what the web holds.
querybodystringQuery is the query that ran, echoed back.
resultsbodywebResult[]Results are the merged hits, deduplicated by normalised URL and capped at 30.
results[].contentbodystringContent is the ENGINE's snippet — the few lines shown under the title, not the page's text.
results[].enginebodystringEngine names the backend that found this hit, so one engine's view of a query can be told from another's.
results[].titlebodystringTitle is the page's title.
results[].urlbodystringURL is the page's address, as the engine reported it.

Failure carries the platform error shape — see Errors.

Examples

hanzo websearch create

Websearch API · All Hanzo APIs · Interactive reference

How is this guide?

On this page