> ## Documentation Index
> Fetch the complete documentation index at: https://docs.llmlayer.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Answer API

> Generate web-grounded answers with /answer and real-time SSE with /answer_stream.

## Overview

The Answer API combines live web search with LLM generation in one request.

Use it when you need:

* Current information from the web
* Source-backed responses
* Structured output (JSON) for downstream processing
* Streaming UX for chat and copilots

## Endpoints

| Endpoint                | Method       | Best for                        | Supports JSON output |
| ----------------------- | ------------ | ------------------------------- | -------------------- |
| `/api/v2/answer`        | `POST`       | Standard request/response flows | Yes                  |
| `/api/v2/answer_stream` | `POST` (SSE) | Real-time streaming UX          | No                   |

<Note>
  `provider_key` is accepted for backward compatibility but currently ignored; provider usage is not billed to the user's provider account.
</Note>

## Authentication

All requests require:

```bash theme={null}
Authorization: Bearer YOUR_LLMLAYER_API_KEY
```

<Warning>
  Keep API keys server-side. Do not expose them in browser code.
</Warning>

## Model Selection

| Model                | Pricing model                | Best for                  |
| -------------------- | ---------------------------- | ------------------------- |
| `llmlayer-web`       | Flat `$0.007 × max_queries`  | Default recommendation    |
| `llmlayer-fast`      | Flat `$0.009 × max_queries`  | Faster responses          |
| `openai/gpt-4o-mini` | Token pricing + LLMLayer fee | Budget + quality          |
| `openai/gpt-5.1`     | Token pricing + LLMLayer fee | Highest reasoning quality |

<Tip>
  If unsure, start with `llmlayer-web` and `max_queries=1`.
</Tip>

## Quickstart

### Non-streaming (`/answer`)

<CodeGroup>
  ```typescript TypeScript theme={null}
  import { LLMLayerClient } from 'llmlayer';

  const client = new LLMLayerClient({
    apiKey: process.env.LLMLAYER_API_KEY,
  });

  const response = await client.answer({
    query: 'What are the latest developments in quantum computing?',
    model: 'llmlayer-web',
    returnSources: true,
  });

  console.log(response.answer);
  console.log('Sources:', response.sources?.length || 0);
  console.log('LLMLayer cost:', response.llmlayer_cost);
  ```

  ```python Python theme={null}
  from llmlayer import LLMLayerClient

  client = LLMLayerClient(api_key='YOUR_LLMLAYER_API_KEY')

  response = client.answer(
      query='What are the latest developments in quantum computing?',
      model='llmlayer-web',
      return_sources=True,
  )

  print(response.answer)
  print('Sources:', len(response.sources or []))
  print('LLMLayer cost:', response.llmlayer_cost)
  ```

  ```bash cURL theme={null}
  curl -X POST https://api.llmlayer.dev/api/v2/answer \
    -H "Authorization: Bearer YOUR_LLMLAYER_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "query": "What are the latest developments in quantum computing?",
      "model": "llmlayer-web",
      "return_sources": true
    }'
  ```
</CodeGroup>

Example response (simplified):

```json theme={null}
{
  "answer": "...",
  "sources": [
    {
      "title": "...",
      "link": "https://...",
      "snippet": "..."
    }
  ],
  "response_time": "2.14",
  "input_tokens": 1432,
  "output_tokens": 288,
  "model_cost": null,
  "llmlayer_cost": 0.007
}
```

### Streaming (`/answer_stream`)

<CodeGroup>
  ```typescript TypeScript theme={null}
  import { LLMLayerClient } from 'llmlayer';

  const client = new LLMLayerClient({
    apiKey: process.env.LLMLAYER_API_KEY,
  });

  const stream = client.streamAnswer({
    query: 'Explain retrieval-augmented generation in simple terms',
    model: 'openai/gpt-4o-mini',
    returnSources: true,
  });

  for await (const event of stream) {
    if (event.type === 'answer') {
      process.stdout.write(event.content || '');
    } else if (event.type === 'sources') {
      console.log('\n\nSources:', event.data?.length || 0);
    } else if (event.type === 'usage') {
      console.log('\nCost:', (event.model_cost || 0) + (event.llmlayer_cost || 0));
    } else if (event.type === 'done') {
      console.log('\nDone in', event.response_time, 'seconds');
    }
  }
  ```

  ```python Python theme={null}
  from llmlayer import LLMLayerClient

  client = LLMLayerClient(api_key='YOUR_LLMLAYER_API_KEY')

  stream = client.stream_answer(
      query='Explain retrieval-augmented generation in simple terms',
      model='openai/gpt-4o-mini',
      return_sources=True,
  )

  for event in stream:
      t = event.get('type')
      if t == 'answer':
          print(event.get('content', ''), end='', flush=True)
      elif t == 'sources':
          print('\n\nSources:', len(event.get('data', [])))
      elif t == 'usage':
          total = (event.get('model_cost') or 0) + (event.get('llmlayer_cost') or 0)
          print('\nCost:', total)
      elif t == 'done':
          print('\nDone in', event.get('response_time'), 'seconds')
  ```

  ```bash cURL (SSE) theme={null}
  curl -N -X POST https://api.llmlayer.dev/api/v2/answer_stream \
    -H "Authorization: Bearer YOUR_LLMLAYER_API_KEY" \
    -H "Content-Type: application/json" \
    -H "Accept: text/event-stream" \
    -d '{
      "query": "Explain retrieval-augmented generation in simple terms",
      "model": "openai/gpt-4o-mini",
      "return_sources": true
    }'
  ```
</CodeGroup>

## Request Parameters

This is the canonical request-body table for both endpoints.

| Parameter             | Type       | Required    | Default    | Applies to | Cost impact            | Details                                                                                                             |
| --------------------- | ---------- | ----------- | ---------- | ---------- | ---------------------- | ------------------------------------------------------------------------------------------------------------------- |
| `query`               | `string`   | Yes         | -          | Both       | -                      | User question/instruction                                                                                           |
| `model`               | `string`   | Yes         | -          | Both       | Depends on model       | Example: `llmlayer-web`, `openai/gpt-4o-mini`                                                                       |
| `search_type`         | `string`   | No          | `general`  | Both       | -                      | `general` or `news`                                                                                                 |
| `date_filter`         | `string`   | No          | `anytime`  | Both       | -                      | `anytime`, `hour`, `day`, `week`, `month`, `year`                                                                   |
| `location`            | `string`   | No          | `us`       | Both       | -                      | Country code for localized search                                                                                   |
| `domain_filter`       | `string[]` | No          | `null`     | Both       | -                      | Include domains, or exclude with `-` prefix                                                                         |
| `search_context_size` | `string`   | No          | `medium`   | Both       | Indirect               | `low`, `medium`, `high`                                                                                             |
| `max_queries`         | `integer`  | No          | `1`        | Both       | Increases LLMLayer fee | Range `1-4`                                                                                                         |
| `max_tokens`          | `integer`  | No          | `1500`     | Both       | Increases model usage  | Response length cap                                                                                                 |
| `temperature`         | `number`   | No          | `0.7`      | Both       | -                      | Range `0.0-2.0`                                                                                                     |
| `response_language`   | `string`   | No          | `auto`     | Both       | -                      | Example: `en`, `fr`, `es`                                                                                           |
| `citations`           | `boolean`  | No          | `false`    | Both       | Indirect               | Adds inline citation markers                                                                                        |
| `return_sources`      | `boolean`  | No          | `false`    | Both       | -                      | Includes `sources` array                                                                                            |
| `return_images`       | `boolean`  | No          | `false`    | Both       | `+ $0.001`             | Includes `images` array                                                                                             |
| `answer_type`         | `string`   | No          | `markdown` | `/answer`  | -                      | `markdown`, `html`, `json`                                                                                          |
| `json_schema`         | `string`   | Conditional | `null`     | `/answer`  | -                      | Required when `answer_type="json"`. Raw HTTP expects a JSON-encoded string; SDKs accept objects and serialize them. |
| `system_prompt`       | `string`   | No          | `null`     | Both       | -                      | Custom behavior instructions                                                                                        |
| `provider_key`        | `string`   | No          | `null`     | Both       | -                      | Accepted for backward compatibility, ignored                                                                        |

<Note>
  HTTP requests use `snake_case` field names. JavaScript SDK examples use `camelCase`.
</Note>

<Note>
  For `/answer` JSON mode, raw REST requests should send `json_schema` as a string. The Python and TypeScript SDKs accept schema objects for convenience and serialize them before sending the request.
</Note>

### Parameter Rules

1. `max_queries` must be between `1` and `4`.
2. `answer_type="json"` requires `json_schema`.
3. `/api/v2/answer_stream` does not support structured JSON output.
4. `provider_key` does not change routing or billing, and provider usage is not billed to the user's provider account.
5. Use `-domain.com` in `domain_filter` to exclude domains.

## Non-streaming Response Contract (`/answer`)

| Field           | Type               | When present             | Description                                |
| --------------- | ------------------ | ------------------------ | ------------------------------------------ |
| `answer`        | `string \| object` | Always                   | Generated answer (`object` when JSON mode) |
| `sources`       | `array`            | If `return_sources=true` | Source documents used                      |
| `images`        | `array`            | If `return_images=true`  | Image search results                       |
| `response_time` | `string`           | Always                   | Total processing time in seconds           |
| `input_tokens`  | `integer`          | Always                   | Input token usage                          |
| `output_tokens` | `integer`          | Always                   | Output token usage                         |
| `model_cost`    | `number \| null`   | Usually                  | Model usage cost                           |
| `llmlayer_cost` | `number`           | Always                   | LLMLayer infrastructure cost               |

Source objects typically include `title`, `link`, `snippet` (plus provider-specific extras).

Image objects typically include `title`, `imageUrl`, `thumbnailUrl`, `source`, `link`.

## Streaming Event Contract (`/answer_stream`)

The stream is Server-Sent Events (`text/event-stream`). Each frame contains JSON under `data:`.

| Event type | Payload                                                                                                   | Notes                              |
| ---------- | --------------------------------------------------------------------------------------------------------- | ---------------------------------- |
| `sources`  | `{ "type": "sources", "data": Source[] }`                                                                 | Emitted when `return_sources=true` |
| `images`   | `{ "type": "images", "data": Image[] }`                                                                   | Emitted when `return_images=true`  |
| `answer`   | `{ "type": "answer", "content": "..." }`                                                                  | Main text chunks                   |
| `usage`    | `{ "type": "usage", "input_tokens": ..., "output_tokens": ..., "model_cost": ..., "llmlayer_cost": ... }` | Billing and token usage            |
| `done`     | `{ "type": "done", "response_time": "..." }`                                                              | Final event                        |
| `error`    | `{ "type": "error", "error": "..." }`                                                                     | Runtime stream error               |

Example stream sequence:

```json theme={null}
{"type":"sources","data":[...]}
{"type":"answer","content":"The "}
{"type":"answer","content":"main idea ..."}
{"type":"usage","input_tokens":1234,"output_tokens":210,"model_cost":0.0002,"llmlayer_cost":0.004}
{"type":"done","response_time":"2.41"}
```

<Warning>
  On early setup failures, some clients may receive an immediate frame like `{ "error": "missing_query" }`.
</Warning>

## Practical Examples

### 1) News summary with citations

```json theme={null}
{
  "query": "Latest developments in renewable energy",
  "model": "openai/gpt-5.1",
  "search_type": "news",
  "date_filter": "week",
  "citations": true,
  "return_sources": true,
  "max_queries": 2
}
```

### 2) Structured JSON extraction (`/answer` only)

```json theme={null}
{
  "query": "Summarize top AI model launches this month",
  "model": "openai/gpt-5.1",
  "answer_type": "json",
  "json_schema": "{\"type\":\"object\",\"properties\":{\"summary\":{\"type\":\"string\"},\"items\":{\"type\":\"array\",\"items\":{\"type\":\"string\"}}},\"required\":[\"summary\",\"items\"]}"
}
```

### 3) Domain-constrained answer

```json theme={null}
{
  "query": "What are current type 2 diabetes treatment guidelines?",
  "model": "openai/gpt-5.1",
  "domain_filter": ["pubmed.gov", "nih.gov", "-reddit.com"],
  "search_context_size": "high",
  "temperature": 0.3,
  "return_sources": true
}
```

## Error Handling

### `/answer` error format

```json theme={null}
{
  "detail": {
    "error_type": "validation_error",
    "error_code": "missing_query",
    "message": "Query parameter cannot be empty",
    "details": null
  }
}
```

### Common status codes

| Status | Category            | Typical reason                      |
| ------ | ------------------- | ----------------------------------- |
| `400`  | Validation          | Missing/invalid request parameters  |
| `401`  | Authentication      | Missing or invalid LLMLayer API key |
| `429`  | Rate limit/provider | Provider or account rate limiting   |
| `500`  | Internal/provider   | Unexpected backend/provider failure |
| `502`  | Provider            | Upstream provider-specific failure  |

### `/answer_stream` errors

* Runtime failures are emitted as stream events (`type: error`).
* Early validation failures can appear as an immediate single `error` frame.

## Pricing

### Standard token-priced models

```text theme={null}
Total = (0.004 × max_queries)
      + model_input_cost
      + model_output_cost
      + (0.001 if return_images=true)
```

### LLMLayer fixed-price models

```text theme={null}
llmlayer-web  = 0.007 × max_queries
llmlayer-fast = 0.009 × max_queries
```

<Note>
  Use `llmlayer_cost` and `model_cost` from responses as the billing source of truth.
</Note>

## Implementation Checklist

1. Start with `/answer` unless you need progressive rendering.
2. Set `max_queries=1` first; increase only for research-style queries.
3. Enable `return_sources=true` for trust-sensitive use cases.
4. Use `answer_type="json"` + `json_schema` for structured pipelines.
5. Add retry/backoff logic for transient `429/500/502` paths.
6. Keep keys server-side and log `llmlayer_cost` + token usage.

## FAQ

<AccordionGroup>
  <Accordion title="When should I use /answer_stream instead of /answer?">
    Use `/answer_stream` for chat UIs and live typing effects. Use `/answer` for batch jobs, strict request/response flows, and JSON structured output.
  </Accordion>

  <Accordion title="Can I stream JSON structured output?">
    No. Streaming returns incremental text chunks and does not support JSON schema-constrained output.
  </Accordion>

  <Accordion title="How do I control source quality?">
    Use `domain_filter`, `search_type`, `date_filter`, and `search_context_size` together. For factual tasks, use lower `temperature`.
  </Accordion>

  <Accordion title="Is provider_key still supported?">
    It is accepted for backward compatibility but currently ignored; provider usage is not billed to the user's provider account.
  </Accordion>

  <Accordion title="What happens if I pass an unsupported model?">
    The backend currently falls back to `llmlayer-web` instead of failing the request.
  </Accordion>

  <Accordion title="How do I minimize cost?">
    Start with `llmlayer-web`, keep `max_queries=1`, only request images/sources when needed, and tune `max_tokens` to expected output length.
  </Accordion>
</AccordionGroup>

## Next Steps

<CardGroup cols={3}>
  <Card title="Web Search API" icon="magnifying-glass" href="/api-reference/endpoint/web-search">
    Raw search results without LLM generation
  </Card>

  <Card title="Scraper API" icon="globe" href="/api-reference/endpoint/scrape">
    Extract full page content from URLs
  </Card>

  <Card title="Answer Stream Endpoint" icon="stream" href="/api-reference/endpoint/stream-answer">
    OpenAPI reference for SSE endpoint
  </Card>
</CardGroup>

<CardGroup cols={2}>
  <Card title="Python SDK" icon="python" href="https://pypi.org/project/llmlayer/">
    Python package and usage examples
  </Card>

  <Card title="TypeScript SDK" icon="js" href="https://www.npmjs.com/package/llmlayer">
    JS/TS package and usage examples
  </Card>
</CardGroup>

## Need Help?

<CardGroup cols={2}>
  <Card title="Discord Community" icon="discord" href="https://discord.gg/EqQF4cjTq5">
    Ask implementation questions
  </Card>

  <Card title="Email Support" icon="envelope" href="mailto:support@llmlayer.ai">
    [support@llmlayer.ai](mailto:support@llmlayer.ai)
  </Card>
</CardGroup>
