# Get cited answers from Google results

> Add a cited answer written by Claude to any Google search, or call /v1/answer to read the top pages first, stream it over SSE or get JSON for your schema.

SerpKite can write the answer for you: Claude reads the live Google results (and, if you like, the top pages), answers the question, and cites every claim with a `[n]` marker that points at a numbered source. There are two ways to ask for one.

| | `include_answer: true` | [`POST /v1/answer`](https://serpkite.com/docs/endpoints/answer) |
| --- | --- | --- |
| Where | [`/v1/search`](https://serpkite.com/docs/endpoints/search), [`/v1/news`](https://serpkite.com/docs/endpoints/news) | Its own endpoint |
| Answers from | That response's results, and the pages `include_content` read | The results page (`depth: "fast"`) or the top 1–5 pages (`depth: "standard"`) |
| You get | The whole search response plus `answer` (`text`, `citations`) | `answer`, `citations`, `results` |
| Streaming | No | `stream: true` (Server-Sent Events) |
| JSON for a schema | No | `output_schema` |
| Model part | +2 credits, +4 with `include_content` | +2 (`fast`) or +4 (`standard`) on top of the search |

The model part is charged only when the answer is written. If the model fails, it is refunded: `include_answer` returns the results with a `meta.warnings` entry, and `/v1/answer` returns `503 ai_unavailable` with a message saying what the search part cost.

## Add an answer to a search

Send `include_answer: true`. The response is the normal search response with an `answer` object. Its sources are numbered in this order: the answer box, the knowledge panel, then the results.

cURL:

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

TypeScript:

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

const sk = new SerpKite(); // reads SERPKITE_API_KEY
const res = await sk.search({ q: "what is retrieval-augmented generation", include_answer: true });
console.log(res.results[0].title, res.meta.credits_used);
```

```json
{
  "answer": {
    "text": "Retrieval-augmented generation (RAG) grounds a model's answer in documents retrieved at query time [1], which keeps answers current without retraining [3].",
    "citations": [
      { "index": 1, "title": "Retrieval-augmented generation", "link": "https://en.wikipedia.org/wiki/Retrieval-augmented_generation", "domain": "en.wikipedia.org" },
      { "index": 3, "title": "What is RAG?", "link": "https://www.example.com/blog/what-is-rag", "domain": "example.com" }
    ]
  },
  "results": ["…"],
  "meta": { "credits_used": 3, "llm": { "provider": "anthropic", "model": "claude-haiku-5-5", "input_tokens": 1840, "output_tokens": 61 } }
}
```

Combine it with [`include_content`](https://serpkite.com/docs/include-content) (and `highlights`) to answer from the pages instead of the snippets. With `format: "markdown"`, the document starts with an `## Answer` section and its sources. The remote [MCP server](https://serpkite.com/docs/mcp)'s `search` tool takes `include_answer` too.

## Answer first: /v1/answer

`/v1/answer` is built for the question itself. `depth: "fast"` answers from the results page in a few seconds. `depth: "standard"` (the default) also reads the top `num_sources` pages (default 3, up to 5) and answers from their passages most relevant to the question.

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));
```

Every search option works: `country`, `language`, `location`, `time`, `include_domains`, `exclude_domains`, `boost_domains`, `start_date`, `end_date`, `engine` and `max_age`. Scope an answer to official sources with `include_domains`, or to recent coverage with `time: "week"`.

`results` lists every source the model was given, numbered as in the prompt, and `citations` lists the ones it cited, in first-cited order. Render the `[n]` markers as links by looking them up in `citations`. A marker that doesn't match a source is removed before the response is sent. When the search finds nothing to answer from, `answer` is `null`, `meta.warnings` says why, and only the search is billed.

## Stream the answer

With `stream: true`, `/v1/answer` returns `text/event-stream`. Events arrive in this order:

| Event | Data |
| --- | --- |
| `results` | `{request, results}`: the numbered sources, sent first |
| `delta` | `{text}`: the next piece of the answer, repeated |
| `done` | `{answer, citations, meta}`: the final answer with checked markers, and the total credits |
| `error` | `{error}`: instead of `done` when the model failed (the model part is refunded) |

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

const sk = new SerpKite(); // reads SERPKITE_API_KEY
for await (const ev of sk.answerStream({ q: "what is retrieval-augmented generation" })) {
  if (ev.event === "results") console.log(ev.data.results.length, "sources");
  if (ev.event === "delta") process.stdout.write(ev.data.text);
  if (ev.event === "done") console.log("\n", ev.data.citations);
}
```

The credit headers on a stream carry the search part only, since they are sent before the answer exists; the `done` event's `meta.credits_used` has the total. Without the SDK, read the body as Server-Sent Events: lines of `event: <name>` and `data: <JSON>`, separated by a blank line.

## Answer as JSON

Pass `output_schema` (a JSON Schema, at most 16 KB) and the answer comes back as a JSON value in `output`, with `answer` set to `null`. Fields that hold claims keep their `[n]` markers, so you can still cite them. `output_schema` can't be combined with `stream`.

```bash
curl https://api.serpkite.com/v1/answer \
  -H "Authorization: Bearer $SERPKITE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "q": "latest stable Go release",
    "depth": "fast",
    "output_schema": {
      "type": "object",
      "properties": {
        "version": { "type": "string" },
        "released": { "type": "string", "description": "YYYY-MM-DD" },
        "summary": { "type": "string" }
      },
      "required": ["version"]
    }
  }'
```

## How it's built

- **Model:** Claude Haiku 5.5 (Anthropic) writes the answer. A decision model (OpenAI's Decisions API) checks which sources help and sends easy questions to a faster setting. `meta.llm` names the provider and model and reports tokens.
- **Grounding:** the model may use only the numbered sources. It is told to say when the sources don't answer the question, and instructions inside a page are ignored.
- **Privacy:** the question and the source text are sent to the model providers under API terms that exclude training. SerpKite never logs prompts or page text, and answers are not cached. See [Privacy and data retention](https://serpkite.com/docs/privacy-and-data-retention#ai-features).

## Related

- [Answer reference](https://serpkite.com/docs/endpoints/answer): Every parameter, field and error of /v1/answer.
- [Page content](https://serpkite.com/docs/include-content): Read the top results as Markdown in the same call.
- [Deep research](https://serpkite.com/docs/guides/deep-research): Many searches and pages, one cited report.
- [AI pricing](https://serpkite.com/docs/credits-and-billing#ai-features): What answers, summaries and research cost.