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

# Web search in Responses API

> Give models access to current web information via the Responses API with built-in web search across OpenAI, Anthropic, and Google.

## Overview

Use **`POST /responses`** on the AI Router with the same request shape as the [OpenAI Responses API](https://developers.openai.com/api/reference/responses/overview): `model`, `input`, and a `tools` array that includes a built-in web search entry. The router forwards search to each provider’s native capability when the model supports it.

There is no separate Perplexity or Parallel tool in the router; the supported contract is **OpenAI-style** `web_search` / `web_search_preview` tools on `/responses`, mapped to Anthropic and Google where applicable.

<Note>
  Prefer models whose metadata indicates web search support. See [Supported Models](/docs/proxy/supported-models) and your workspace model list.
</Note>

## Quick start

Use the OpenAI SDK against the AI Router base URL and call the Responses API directly.

<CodeGroup>
  ```bash cURL theme={"theme":{"light":"github-light","dark":"github-dark"}}
  curl -sS -X POST "https://api.orq.ai/v3/router/responses" \
    -H "Authorization: Bearer ${ORQ_API_KEY}" \
    -H "Content-Type: application/json" \
    -d '{
      "model": "openai/o3",
      "input": "What are the latest changes to the OpenAI Responses API?",
      "tools": [{ "type": "web_search_preview" }]
    }'
  ```

  ```typescript Typescript theme={"theme":{"light":"github-light","dark":"github-dark"}}
  import OpenAI from "openai";

  const openai = new OpenAI({
    apiKey: process.env.ORQ_API_KEY,
    baseURL: "https://api.orq.ai/v3/router",
  });

  const response = await openai.responses.create({
    model: "openai/o3",
    input: "What are the latest changes to the OpenAI Responses API?",
    tools: [{ type: "web_search_preview" }],
  });

  console.log(response.output_text);
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}}
  from openai import OpenAI
  import os

  client = OpenAI(
      api_key=os.environ.get("ORQ_API_KEY"),
      base_url="https://api.orq.ai/v3/router",
  )

  response = client.responses.create(
      model="openai/o3",
      input="What are the latest changes to the OpenAI Responses API?",
      tools=[{"type": "web_search_preview"}],
  )

  print(response.output_text)
  ```
</CodeGroup>

Endpoint:

`POST https://api.orq.ai/v3/router/responses`

## Tool definitions

Request `tools` entries use the discriminated **`type`** field, matching the gateway schema.

### `web_search_preview`

| Field                 | Type                   | Description                                                                                 |
| --------------------- | ---------------------- | ------------------------------------------------------------------------------------------- |
| `type`                | `"web_search_preview"` | Identifies the preview web search tool.                                                     |
| `domains`             | string\[]              | Optional allowlist of domains to restrict search.                                           |
| `search_context_size` | string                 | Optional. One of `low`, `medium`, `high`. Controls how much context to retrieve per result. |
| `user_location`       | object                 | Optional. Hints for localized results (`type`, `city`, `country`, `region`, `timezone`).    |

### `web_search`

| Field                 | Type           | Description                                                            |
| --------------------- | -------------- | ---------------------------------------------------------------------- |
| `type`                | `"web_search"` | Stable web search tool type.                                           |
| `search_context_size` | string         | Optional. `low`, `medium`, `high`.                                     |
| `user_location`       | object         | Optional. Same shape as above.                                         |
| `filters`             | object         | Optional. e.g. `allowed_domains` (nullable array) to restrict domains. |

<Warning>
  The router accepts the full tool object on `/responses`. **OpenAI** requests pass tools through to the upstream Responses API. **Anthropic** and **Google** paths map `web_search` / `web_search_preview` to native web search tools; fields the upstream API does not support may be ignored.
</Warning>

## `include` (optional)

You can ask for additional fields on web search output items, aligned with OpenAI Responses `include`:

| Value                            | Meaning                                          |
| -------------------------------- | ------------------------------------------------ |
| `web_search_call.results`        | Include detailed search results where available. |
| `web_search_call.action.sources` | Include source URLs and titles on the action.    |

Example request body:

<CodeGroup>
  ```json JSON theme={"theme":{"light":"github-light","dark":"github-dark"}}
  {
    "model": "openai/gpt-4o",
    "input": "Summarize today’s headlines in finance.",
    "tools": [{ "type": "web_search_preview" }],
    "include": ["web_search_call.action.sources"]
  }
  ```
</CodeGroup>

## Output: `web_search_call`

Responses can contain output items with `"type": "web_search_call"`:

| Field    | Description                                                                                                                        |
| -------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| `id`     | Item id.                                                                                                                           |
| `type`   | `"web_search_call"`.                                                                                                               |
| `status` | Lifecycle status for the call.                                                                                                     |
| `action` | Optional. `type` may be `search`, `open_page`, or `find`, plus fields like `query`, `url`, `pattern`, and `sources` (url + title). |

Exact payload shape matches what the provider returns; streaming uses the same event model as other `/responses` streams.

## Provider behavior

### OpenAI

Tools and `include` are passed to **`client.responses.create`** with your model id (for example `openai/o3`). Use the same parameters OpenAI documents for [web search](https://platform.openai.com/docs/guides/tools-web-search) on the Responses API.

<Card title="OpenAI" icon="openai" href="/docs/integrations/providers/openai" horizontal>
  Set up your OpenAI API key to use o3 and GPT-4o with web search.
</Card>

### Anthropic

`web_search` and `web_search_preview` in `tools` are mapped to Anthropic’s web search tool for the Messages path used under `/responses`.

<Card title="Anthropic" icon="https://mintcdn.com/orqai/d-t0Z04KwFlGVsS1/images/logos/anthropic.svg?fit=max&auto=format&n=d-t0Z04KwFlGVsS1&q=85&s=b097662b141ad6f89f0c8d039ae241dc" href="/docs/integrations/providers/anthropic" horizontal width="61" height="43" data-path="images/logos/anthropic.svg">
  Set up your Anthropic API key to use Claude with web search.
</Card>

### Google Gemini

The same tool types enable **Google Search grounding** (`googleSearch`) for Gemini models that support it.

<Card title="Google AI" icon="https://mintcdn.com/orqai/d-t0Z04KwFlGVsS1/images/logos/google_ai_studio.svg?fit=max&auto=format&n=d-t0Z04KwFlGVsS1&q=85&s=eac05c3f32c81d329e7645eed547f5c0" href="/docs/integrations/providers/google-ai" horizontal width="48" height="48" data-path="images/logos/google_ai_studio.svg">
  Set up your Google AI API key to use Gemini models with Google Search grounding.
</Card>

## `tool_choice`

You can steer the model toward web search using the structured `tool_choice` form, for example:

<CodeGroup>
  ```json JSON theme={"theme":{"light":"github-light","dark":"github-dark"}}
  {
    "tool_choice": { "type": "web_search_preview" }
  }
  ```
</CodeGroup>

Supported `tool_choice.type` values for built-in tools are defined in the API schema (including `web_search`, `web_search_preview`, and related literals). Strings `none`, `auto`, and `required` behave as usual.

## Streaming

Set **`"stream": true`** on the same JSON body. The server responds with **`text/event-stream`** and events in the OpenAI-style response stream format.

<CodeGroup>
  ```bash cURL theme={"theme":{"light":"github-light","dark":"github-dark"}}
  curl -sS -N -X POST "https://api.orq.ai/v3/router/responses" \
    -H "Authorization: Bearer ${ORQ_API_KEY}" \
    -H "Content-Type: application/json" \
    -H "Accept: text/event-stream" \
    -d '{
      "model": "openai/o3",
      "input": "What is the current phase of the moon for San Francisco?",
      "tools": [{ "type": "web_search_preview" }],
      "stream": true
    }'
  ```

  ```typescript Typescript theme={"theme":{"light":"github-light","dark":"github-dark"}}
  import OpenAI from "openai";

  const openai = new OpenAI({
    apiKey: process.env.ORQ_API_KEY,
    baseURL: "https://api.orq.ai/v3/router",
  });

  const stream = await openai.responses.create({
    model: "openai/o3",
    input: "What is the current phase of the moon for San Francisco?",
    tools: [{ type: "web_search_preview" }],
    stream: true,
  });

  for await (const event of stream) {
    console.log(event);
  }
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}}
  from openai import OpenAI
  import os

  client = OpenAI(
      api_key=os.environ.get("ORQ_API_KEY"),
      base_url="https://api.orq.ai/v3/router",
  )

  stream = client.responses.create(
      model="openai/o3",
      input="What is the current phase of the moon for San Francisco?",
      tools=[{"type": "web_search_preview"}],
      stream=True,
  )

  for event in stream:
      print(event)
  ```
</CodeGroup>

## Code examples

Set **`ORQ_API_KEY`** (or pass the key explicitly) so the `Authorization` header resolves.

### Non-streaming

<CodeGroup>
  ```bash cURL theme={"theme":{"light":"github-light","dark":"github-dark"}}
  curl -sS -X POST "https://api.orq.ai/v3/router/responses" \
    -H "Authorization: Bearer ${ORQ_API_KEY}" \
    -H "Content-Type: application/json" \
    -d '{
      "model": "openai/o3",
      "input": "What is the current phase of the moon for San Francisco?",
      "tools": [{ "type": "web_search_preview" }],
      "include": ["web_search_call.action.sources"]
    }'
  ```

  ```typescript Typescript theme={"theme":{"light":"github-light","dark":"github-dark"}}
  import OpenAI from "openai";

  const openai = new OpenAI({
    apiKey: process.env.ORQ_API_KEY,
    baseURL: "https://api.orq.ai/v3/router",
  });

  const response = await openai.responses.create({
    model: "openai/o3",
    input: "What is the current phase of the moon for San Francisco?",
    tools: [{ type: "web_search_preview" }],
    include: ["web_search_call.action.sources"],
  });

  console.log(response.output_text);

  for (const item of response.output ?? []) {
    if (item.type === "web_search_call") {
      console.log("web_search_call", item.action);
    }
  }
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}}
  from openai import OpenAI
  import os

  client = OpenAI(
      api_key=os.environ.get("ORQ_API_KEY"),
      base_url="https://api.orq.ai/v3/router",
  )

  response = client.responses.create(
      model="openai/o3",
      input="What is the current phase of the moon for San Francisco?",
      tools=[{"type": "web_search_preview"}],
      include=["web_search_call.action.sources"],
  )

  print(response.output_text)

  for item in response.output or []:
      if item.type == "web_search_call":
          print("web_search_call", item.action)
  ```
</CodeGroup>

### Streaming

<CodeGroup>
  ```bash cURL theme={"theme":{"light":"github-light","dark":"github-dark"}}
  curl -sS -N -X POST "https://api.orq.ai/v3/router/responses" \
    -H "Authorization: Bearer ${ORQ_API_KEY}" \
    -H "Content-Type: application/json" \
    -H "Accept: text/event-stream" \
    -d '{
      "model": "openai/o3",
      "input": "What is the current phase of the moon for San Francisco?",
      "tools": [{ "type": "web_search_preview" }],
      "stream": true
    }'
  ```

  ```typescript Typescript theme={"theme":{"light":"github-light","dark":"github-dark"}}
  import OpenAI from "openai";

  const openai = new OpenAI({
    apiKey: process.env.ORQ_API_KEY,
    baseURL: "https://api.orq.ai/v3/router",
  });

  const stream = await openai.responses.create({
    model: "openai/o3",
    input: "What is the current phase of the moon for San Francisco?",
    tools: [{ type: "web_search_preview" }],
    stream: true,
  });

  for await (const event of stream) {
    console.log(event);
  }
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}}
  from openai import OpenAI
  import os

  client = OpenAI(
      api_key=os.environ.get("ORQ_API_KEY"),
      base_url="https://api.orq.ai/v3/router",
  )

  stream = client.responses.create(
      model="openai/o3",
      input="What is the current phase of the moon for San Francisco?",
      tools=[{"type": "web_search_preview"}],
      stream=True,
  )

  for event in stream:
      print(event)
  ```
</CodeGroup>

<Note>
  For cURL streaming, `-N` disables buffering so SSE lines show up as they arrive. Parse `data:` lines from the response body the same way you would against OpenAI’s Responses stream.
</Note>

## See also

* [OpenAI-Compatible API](/docs/proxy/openai-compatible-api): base URL and `/responses`
* [Reasoning](/docs/proxy/reasoning): Responses API `reasoning` and `thinking` on the same endpoint
* [Tool Calling](/docs/proxy/tool-calling): function tools on `/chat/completions`
