Skip to main content
Kaer APIv1

Batch searchEndpoints


POST /v1/search/batch
Scope
search
Tier
Starter and up
Price
Per served row, at search prices
Free credit
Yes, once Starter opens it

Send many queries in one round trip. Every row shares the lane, the result count and the domain filters.

Request body

ParameterTypeDefaultDescription
queriesRequiredstring[]·1 to your tier's batch size. Each query is 1 to 512 characters after trimming.
lanestringautoweb, fast, deep or auto, case-insensitive. Anything else is a 400.
num_resultsinteger5Results per query, 1 to 25. Numbers outside are clamped; anything that is not a number is a 400. Also read as numResults.
include_domainsstring[]·Only results from these hosts or their subdomains, up to 20. The web lane applies it before ranking; the others filter after retrieval. Also includeDomains.
exclude_domainsstring[]·Never return results from these hosts or their subdomains, up to 20. Also excludeDomains.
fieldsstring[]·Result keys to keep, 1 to 20 of title, url, snippet, source, published_date, text, text_truncated, text_source. Leave it out for all of them. Any other name is a 400 invalid_fields.

Unread fields come back in kaer.ignored_params. The body is limited to 64 KB, and the whole batch to 35 seconds.

TierQueries per batch
Starter10
Build50
Scale100
Pro100

Understand how a batch is billed

  • Each row that comes back with ok: true is billed like a single search, at the lane that served it.
  • Queries that match after trimming, lowercasing and collapsing spaces run once and are billed once; the repeats come back with charged: false and duplicate_of.
  • Rows that fail carry charged: false and cost nothing.
  • While the batch runs, the gateway holds the dearest possible price for every row (auto holds the deep price).
  • If the whole batch fails, nothing is charged.

Response

FieldTypeDescription
objectstringsearch.batch
lanestringThe lane you asked for.
countintegerRows requested.
servedintegerRows served, repeats included. See billed_queries for what was billed.
billed_queriesintegerDistinct queries served and billed.
deduplicatedintegerRows that repeated an earlier query and were not billed.
duration_msintegerTime the batch took, in milliseconds.
results[].indexintegerPosition in queries.
results[].querystringThe query.
results[].okbooleanWhether the row was served.
results[].served_lanestringServed rows: the lane billed.
results[].resultsarrayServed rows: the hits, shaped like Search results; deep rows carry text, text_truncated and text_source.
results[].chargedbooleanfalse on rows that failed and on repeats.
results[].duplicate_ofintegerRepeats: the index of the row that ran the query.
results[].deepbooleanDeep rows: true when pages were read, false when the row fell back to snippets.
results[].degraded_reasonstringDeep rows with deep: false: timeout, engines_failed or pages_unreadable.
results[].qualityobjectpartial (boolean), coverage (0 to 1) and result_count, when the lane reports them.
results[].codestringFailed rows: timeout, backpressure, upstream_unavailable, invalid_query, no_results or internal.
results[].errorstringFailed rows: a fixed message for code.
kaer.cost_usdnumberWhat the batch cost.

Rows carry only the fields above. Retry timeout, backpressure and upstream_unavailable rows; fix invalid_query rows; internal is ours to fix.

Headers: x-request-id and the x-ratelimit-* headers. The cost is kaer.cost_usd in the body; there is no x-kaer-cost-usd header.

Errors

StatusCodeWhen
400invalid_jsonThe body is not valid JSON. Images also needs a JSON object.
400queries_requiredqueries is missing or empty.
400batch_too_largeMore queries than your tier's batch size.
400invalid_queryA batch query is blank or over 512 characters.
400invalid_lanelane is not web, fast, deep or auto.
400invalid_num_resultsnum_results is not a number.
400invalid_domainsinclude_domains or exclude_domains is not an array of up to 20 host names.
403tier_requiredYour tier does not include this service yet.
413body_too_largeThe body is over the endpoint's limit: chat 1 MB, search 16 KB, batch 64 KB, images 8 KB, mail 512 KB.
502search_failedThe search service failed. Nothing was charged.
503search_busySearch is at capacity. Nothing was charged.
504search_timeoutSearch ran out of time. Nothing was charged.
502 or 503search_unavailableSearch is unreachable or paused. Nothing was charged.
curl https://api.kaer.ai/v1/search/batch \
  -H "Authorization: Bearer $KAER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "queries": ["solar panel efficiency 2026", "heat pump grants uk"],
    "lane": "web",
    "num_results": 3
  }'

© 2026 Kaer Labs Ltd. All rights reserved.