Customise & APIs

Web Search API

Kaer's multi-engine web search as a metered endpoint — reachable with a signed-in session or with an API key carrying the search scope, billed per query.

The Web Search API is Kaer's own search stack — the multi-engine orchestration, quality scoring and resilience that power the operator's research — exposed as a metered endpoint.

One POST in, ranked and quality-scored results out. You are billed per query: $0.005 per query ($5.00 per 1,000), on every plan.

There are two doors onto this stack, and they are separate endpoints with separate request shapes:

Session endpointKey endpoint
PathPOST /api/searchPOST /api/v1/search
Credentialsigned-in Kaer sessionkaer_sk_… account key with the search scope
Forthe app, and anything holding your sessionserver-to-server integrations
Extra usage requirednoyes
Mode parametersearch_typelane

Pick the key endpoint if you are integrating from your own backend — a session token is not a credential you should be minting for machines.

The session endpoint

POST https://app.kaer.ai/api/search
Authorization: Bearer your_kaer_session_token
Content-Type: application/json

Authentication is your signed-in Kaer session — the __Host-kaer_session cookie a logged-in browser already sends, or that same session token passed as Authorization: Bearer. The cookie wins when both are present.

Every call also needs credit headroom. A depleted balance returns 402 with code: "INSUFFICIENT_CREDITS"; a free-plan account that has spent its monthly token allowance returns 402 with code: "FREE_TOKEN_LIMIT" instead. Treat any 402 as "top up, upgrade, or wait for the reset" and read code if you branch on the reason.

The key endpoint

POST https://app.kaer.ai/api/v1/search
Authorization: Bearer kaer_sk_…
Content-Type: application/json

The credential is a personal account key from Customise → API access (Account API) — the same kaer_sk_… family that reaches the other /api/v1/… routes. Two things must both be true, and both are re-checked on every single request:

  1. The key carries the search scope. Tick it when you create the key. Scopes are stored per key and are never back-filled, so a key minted before search existed does not have it — the fix is a new key, not an edit. A key without the scope answers 403.
  2. The account has extra usage switched on. Without it the call answers 402 with error: "search_api_requires_extra_usage".

The second gate is the unusual one, and it follows directly from the pricing: search has no included allowance, so a key on an account without extra usage would start 402-ing partway through a run with no way for the caller to see it coming. Requiring extra usage means the account has already agreed to be billed past its included credits — the only footing a pay-per-call API can stand on.

Keys are rate-limited to 60 queries per minute each. Over that, the endpoint answers 429 with a Retry-After header.

Request

{
  "query": "latest advances in small language models",
  "lane": "fast",
  "num_results": 5
}
FieldDefaultNotes
queryRequired. Max 512 characters.
lane"fast"fast, web, deep or auto. An unrecognised value falls back to fast rather than erroring.
num_results5Clamped to 1–25.

The lanes are different latency/breadth tradeoffs over the same stack:

  • fast — a first-non-empty race across the engines. The default, and the right choice for feeding an LLM context window.
  • web — a direct hit against Kaer's own index, no fanout.
  • deep — full orchestration with page fetching, enrichment and ranking. Seconds, not milliseconds, and the only lane that returns the full signal set below.
  • auto — classifies the query and forwards to one of the three.

Response

{
  "query": "latest advances in small language models",
  "lane": "fast",
  "results": [
    {
      "title": "Small language model",
      "url": "https://en.wikipedia.org/wiki/Small_language_model",
      "snippet": "Small language models are artificial intelligence language models…",
      "rank": 0,
      "relevance_score": 1.0,
      "result_id": "7e438c359f24",
      "source": ["fast"]
    }
  ]
}

Every lane returns title, url, snippet, rank, relevance_score, result_id and source (which engines contributed the hit). The deep lane additionally carries authority_score, freshness, language, likely_paywall, requires_js, rank_score and source_type — if you are ranking or filtering downstream, that is the lane to ask for.

Errors

StatusMeaningBilled?
400missing or over-long query, or an unreadable bodyno
401no key presented, or the key is invalid or revokedno
403the key does not carry the search scopeno
402extra usage is off — error: "search_api_requires_extra_usage"no
429over 60 queries/min for this keyno
502the search stack was reached and failedyes — see below
503search is not configured on our sideno

What gets billed

The charge lands before the query is served, so a query that reaches the search stack and then fails upstream is still billed: it consumed index capacity, which makes it a metered call. Every refusal that happens before the stack is reached — all of the 4xx rows above, plus the 503 — is free.

If you are reconciling spend, 502 responses are the ones that cost you money without returning results. Retry them; they are not deducted twice for the same result set, because no result set was produced.

Other key-authenticated routes

Two other surfaces run this same stack under a key and meter identically: the Web Search step in Workflows, and POST /api/v1/agent with an account key holding the agent scope — the agent's own web search drives these engines, though you get its answer rather than the raw result envelope.

Two credentials do not reach either search endpoint: a kaer_sk_… key from Settings → Developer → API Keys (a different key family, carrying assistants, agent, usage and profile), and a kmaps_… maps key, which does maps and nothing else.

Session endpoint reference

The request and response shapes below apply to POST /api/search only — the key endpoint's are above.

Session request

{
  "query": "latest advances in small language models",
  "num_results": 10,
  "search_type": "auto"
}
FieldDefaultNotes
queryRequired. Natural language or keywords.
num_results10Clamped to 1–50.
search_type"auto"auto lets the orchestrator detect the best mode for the query; you can pin a mode explicitly.

Session response

{
  "ok": true,
  "query": "latest advances in small language models",
  "search_type": "auto",
  "detected_mode": "Research",
  "results": [
    {
      "title": "…",
      "url": "https://…",
      "snippet": "…",
      "source_engines": ["engine-a", "engine-b"],
      "rank_score": 0.91,
      "source_type": "Official",
      "freshness": "Recent",
      "authority_score": 0.87,
      "likely_paywall": false,
      "requires_js": false,
      "language": "en"
    }
  ],
  "result_count": 10,
  "latency_ms": 412,
  "engine": "smart_search"
}

Every result carries the signals you need to rank, filter or cite with confidence — you do not have to re-score anything downstream:

  • authority_score — how trustworthy the source is estimated to be
  • freshness — recency classification of the page
  • source_engines — which upstream engines contributed the hit (deduplicated)
  • likely_paywall / requires_js — whether the content is behind a paywall or needs a JavaScript render
  • source_type / language — classification and detected language

Resilience model

The session endpoint is engineered to degrade gracefully rather than fail:

  1. Smart Search runs the full multi-engine orchestration with deduplication and quality scoring inside a 15-second budget.
  2. Fast Search fallback answers from the lightweight path when the full stack is degraded — the response's engine field reads fast_search_fallback so you can tell.
  3. Backpressure — under extreme concurrency the endpoint answers 503 with code: "BACKPRESSURE". Retry shortly; this protects result quality for everyone.

A total failure of both paths returns 503 with an error body — your caller should treat non-ok responses as retryable.

Pricing and metering

WhatRate
Per query$0.005
Per 1,000 queries$5.00

There is no included allowance for search. This is the one metered surface with no free quota behind it: the first query of the month costs $0.005, exactly like the ten-thousandth, on every plan including paid ones. Your plan's included credits are what the charge is drawn against — they are not a pool of free searches, and search is never bundled.

That is also why the key endpoint requires extra usage: with no allowance to spend down, an account that has not agreed to be billed past its included credits has no headroom a pay-per-call API can rely on.

Spend accrues in Settings → Usage, per key and in the account total. On the session endpoint the debit lands the moment results are served, and a ledger hiccup never blocks a served result — if a debit can't be recorded it is logged, not charged twice. On the key endpoint the debit lands before the query is served; see What gets billed.

Use it from a workflow

The Web Search step in Workflows runs on this same stack — bind a search step into a scheduled or mail-triggered workflow and the queries meter to your account identically. This is the route to take when the caller has neither a Kaer session nor a key of its own.

FAQ

Can I call this with an API key? Yes — POST /api/v1/search with a kaer_sk_… account key carrying the search scope, on an account with extra usage on. See The key endpoint. The older POST /api/search remains session-only; a key sent there is still rejected.

I already have an account key — why does it get a 403? Scopes are stored per key and are never back-filled, so a key created before the search scope existed does not have it. Create a new key with search ticked from Customise → API access and revoke the old one — a fresh key is safer than a widened one.

Is there a free allowance? No. Search bills per query from the first call on every plan — see Pricing and metering. This is the one metered surface with no included quota.

What happens when I'm out of credits? The session endpoint returns 402 until you top up, upgrade, or the monthly reset lands — code: "INSUFFICIENT_CREDITS" for an exhausted balance, code: "FREE_TOKEN_LIMIT" when a free plan has spent its monthly token allowance. The key endpoint returns 402 with error: "search_api_requires_extra_usage" when extra usage is off. Nothing is served on credit.

How fresh are results? Results come from live upstream engines with recency-aware ranking. On the session endpoint and the key endpoint's deep lane, the freshness field classifies each hit so you can filter for recent sources.

How many results can I get? num_results clamps at 50 on the session endpoint and at 25 on the key endpoint. Paginate by refining the query, or ask for a research-grade synthesis inside the product instead.