# Answer

`POST https://api.serpkite.com/v1/answer` · Credits: 3 at `depth: "fast"`, 8 at `depth: "standard"` (3 pages); the model part is free when it fails

A cited answer to a question, written by Claude from live Google results and the top pages, with [n] citations. Streams over SSE or fills your JSON schema.

Answer runs your question on Google, then Claude Haiku 5.5 (Anthropic) writes a concise answer that cites the numbered sources with `[n]` markers. `depth: "fast"` answers from the results page (snippets, answer box, knowledge panel); `depth: "standard"` (the default) also reads the top `num_sources` pages and answers from their query-ranked passages. Sources are untrusted: instructions inside a page are ignored.

**Billing:** the search part is priced like [`/v1/search`](https://serpkite.com/docs/endpoints/search) with `include_content`: 1 credit plus 1 per page read, with the usual cache rules. The model adds 2 credits when it answers from the results page and 4 when it reads pages, so a fast answer costs 3 credits and a standard one 8 with 3 pages (6–10 for 1–5 pages). `meta.credits` splits the two parts. When the model fails, the model part is refunded and the call returns `503 ai_unavailable`; the message says what the search cost. A search with nothing to answer from returns `answer: null` with a `meta.warnings` entry, and the model part is not charged.

**Streaming:** `stream: true` returns `text/event-stream` with these events, in order: `results` (`{request, results}`), `delta` (`{text}`, repeated), then `done` (`{answer, citations, meta}`) or `error` (`{error}`). Billing headers on a stream carry the search part only; the final `meta` has the total.

**Structured output:** with `output_schema` (a JSON Schema, at most 16 KB) the answer is a JSON value in `output` and `answer` is null. Fields that hold claims keep their `[n]` markers. It can't be combined with `stream`. See [Cited answers](https://serpkite.com/docs/guides/cited-answers).

## Request body

| Parameter | Type | Default | Description |
| --- | --- | --- | --- |
| `q` **required** | string |  | The question, up to 2,048 characters. |
| `depth` | string | `standard` | `fast` answers from the results page; `standard` also reads the top pages. One of: `fast`, `standard`. |
| `num_sources` | integer | `3` | Pages to read, 1–5, with `depth: "standard"` only. +1 credit per page read. |
| `stream` | boolean | `false` | Send Server-Sent Events (`results`, `delta`…, then `done` or `error`) instead of one JSON body. |
| `output_schema` | object |  | A JSON Schema (at most 16 KB). The answer comes back as JSON in `output`. Not with `stream`. |
| `country` | string | `us` | Country to search from, as a two-letter ISO code (us, gb, de, in…). Defaults to the country a location ends in. |
| `language` | string | `en` | Interface language, as a language code with an optional region (en, de, pt-BR, zh-TW…). |
| `location` | string |  | Canonical location for local results, e.g. "Austin, Texas, United States". Ending in a country name also sets country. |
| `time` | string |  | Restrict to recent results. Shorthand for tbs=qdr:*. One of: `hour`, `day`, `week`, `month`, `year`. |
| `include_domains` | string[] |  | Only results from these sources, up to 20: a domain (example.com, subdomains match), a path prefix (github.com/org) or a TLD (.gov). Compiled to site: operators and enforced on the results. Search, news, images, videos. |
| `exclude_domains` | string[] |  | Drop results from these sources, up to 20, same formats as include_domains. Search, news, images, videos. |
| `boost_domains` | string[] |  | Move results from these sources to the top without filtering out the rest, up to 20. Search and news. |
| `start_date` | string |  | Only results published on or after this date (YYYY-MM-DD). Google's custom date range; can't be combined with time or tbs. |
| `end_date` | string |  | Only results published on or before this date (YYYY-MM-DD). |
| `engine` | string or array | `google` | Which search providers may answer. google is Google only (SerpKite still retries Google internally); auto falls back to other providers when Google is blocked or times out; consensus (search only) asks several independent indexes in parallel, merges the results by URL, ranks them by agreement and lists each result's sources, at the sum of one page per provider that returned results; a provider name or a list (e.g. google,brave) restricts the request to those. meta.engine names the provider that answered. One of: `google`, `auto`, `consensus`, `brave`, `bing`, `yahoo`, `duckduckgo`, `mojeek`, `wikipedia`, `yandex`. |
| `max_age` | integer |  | Accept a cached search up to this many seconds old (the search part at half price). |

## Example request

cURL:

```bash
curl https://api.serpkite.com/v1/answer \
  -H "Authorization: Bearer $SERPKITE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"q":"what is retrieval-augmented generation","depth":"standard","num_sources":3}'
```

TypeScript:

```ts
import { SerpKite } from "serpkite";

const sk = new SerpKite(); // reads SERPKITE_API_KEY
const res = await sk.answer({ q: "what is retrieval-augmented generation", depth: "standard", num_sources: 3 });
console.log(res.answer, res.citations.map((c) => c.link));
```

Python:

```python
from serpkite import SerpKite

sk = SerpKite()  # reads SERPKITE_API_KEY
res = sk.answer("what is retrieval-augmented generation", depth="standard", num_sources=3)
print(res.answer, [c.link for c in res.citations])
```

## Response fields

| Field | Type | Description |
| --- | --- | --- |
| `request` | object | The normalised request, with defaults filled in: `endpoint`, `engine`, `q`, `country`, `language`, `location`, `num`, `page`, `device`, `autocorrect`… |
| `answer` | string \| null | Markdown with `[n]` citation markers. Null with `output_schema`, or when there was nothing to answer from. |
| `output` | any | With `output_schema`: the JSON value matching your schema. |
| `citations[]` | array | The sources the answer cites, in first-cited order: `index`, `title`, `link`, `domain`. |
| `results[]` | array | Every source the answer could cite, numbered as in the prompt (`[index]`): `index`, `title`, `link`, `domain`, `date`. |
| `meta` | object | As on `/v1/search`, plus `credits` (`search` and `answer` parts) and `llm` (`provider`, `model`, `input_tokens`, `output_tokens`). |

## Example response

```json
{
  "request": {
    "endpoint": "answer",
    "engine": "google",
    "q": "what is retrieval-augmented generation",
    "country": "us",
    "language": "en",
    "depth": "standard",
    "num_sources": 3
  },
  "answer": "Retrieval-augmented generation (RAG) grounds a language model's answer in documents retrieved at query time [1], which reduces hallucinations and keeps answers current without retraining [2].",
  "citations": [
    {
      "index": 1,
      "title": "Retrieval-augmented generation",
      "link": "https://en.wikipedia.org/wiki/Retrieval-augmented_generation",
      "domain": "en.wikipedia.org"
    },
    {
      "index": 2,
      "title": "What is retrieval-augmented generation (RAG)?",
      "link": "https://www.example.com/blog/what-is-rag",
      "domain": "example.com"
    }
  ],
  "results": [
    {
      "index": 1,
      "title": "Retrieval-augmented generation",
      "link": "https://en.wikipedia.org/wiki/Retrieval-augmented_generation",
      "domain": "en.wikipedia.org"
    },
    {
      "index": 2,
      "title": "What is retrieval-augmented generation (RAG)?",
      "link": "https://www.example.com/blog/what-is-rag",
      "domain": "example.com"
    }
  ],
  "meta": {
    "request_id": "req_01J8ZK4M6Q2V7",
    "credits_used": 8,
    "cached": false,
    "engine": "google",
    "latency_ms": 4410,
    "parse_quality": "ok",
    "resolved_urls": true,
    "credits": {
      "search": 4,
      "answer": 4
    },
    "llm": {
      "provider": "anthropic",
      "model": "claude-haiku-5-5",
      "input_tokens": 3120,
      "output_tokens": 88
    }
  }
}
```

## Errors

| Status | Code | Meaning |
| --- | --- | --- |
| 400 | `invalid_request` | A parameter is missing or invalid. |
| 401 | `unauthorized` | The API key is missing, invalid or revoked. |
| 402 | `insufficient_credits` | Your balance is too low. Buy a pack or wait for the monthly free grant. |
| 429 | `rate_limited` | Too many requests per second for your plan. Retry after the Retry-After header. |
| 503 | `upstream_error` | Google could not be fetched or parsed. Not billed; retry after Retry-After. |
| 503 | `ai_unavailable` | An AI step (answer, summary, schema extraction, research) could not run. The model part is not billed; on /v1/answer the search that ran is. |

All errors: https://serpkite.com/docs/errors

## Notes

- `include_content`, `highlights`, `include_answer`, `format` and `fields` don't apply here (`400`); use `depth` and `num_sources`.
- To add an answer to a normal search response instead, send `include_answer: true` to [`/v1/search`](https://serpkite.com/docs/endpoints/search) or [`/v1/news`](https://serpkite.com/docs/endpoints/news): +2 credits over the results page, +4 when `include_content` also read pages.
- The question and the source text are sent to Anthropic to write the answer, and a decision model (OpenAI) may check which sources help. Neither trains on API data, and SerpKite never logs prompts or page text. See [Privacy and data retention](https://serpkite.com/docs/privacy-and-data-retention#ai-features).
- The remote MCP server has an `answer` tool.

## Related

- [Cited answers guide](https://serpkite.com/docs/guides/cited-answers)
- [Search](https://serpkite.com/docs/endpoints/search)
- [Research](https://serpkite.com/docs/endpoints/research)