← All docs

Guides

Web search

Updated

Add {"type": "web_search"} to tools. The model searches when it needs to and answers from the results. The search runs server-side, so your client runs no tool.

json
{
  "model": "everyais/gemini-3-8-flash",
  "messages": [{"role": "user", "content": "What's the weather in Seoul today?"}],
  "tools": [{"type": "web_search"}]
}

Supported models

Use models with capabilities.web_search: true in GET /v1/models. Support varies even within the Gemini family.

bash
curl https://api.everyais.com/v1/models \
  -H "Authorization: Bearer $EVERYAIS_API_KEY" \
  | jq '.data[] | select(.capabilities.web_search) | .id'

Other models return 400 web_search_unsupported_model and are not charged.

  • Only one web_search entry is allowed. Two or more return 400.
  • You can combine it with function tools. tool_choice: "none" turns off both. With only the search tool, required or a named function returns 400.
  • Only /v1/chat/completions supports web search.

Billing

Search is billed on top of tokens: billed_queries × the model's search price.

Model familyHow searches are counted
GeminiEach query run. Two searches count as 2; no search counts as 0
  • Search is billed even when tokens are free. pricing.is_free covers only input, output and cache tokens.
  • A stream you cut off still pays for the searches Google ran. Google reports the count at the end of the answer, so the gateway waits up to 10 seconds after the cut for it; if it doesn't arrive, the 10 searches reserved with the request are charged.
  • Pages fetched by Google search are not billed as input tokens.
  • x_everyais.web_search.billed_queries has the billed count. The x-everyais-cost-usd header on non-streaming responses includes search.
  • You can't cap the number of searches. Use the key's monthly or daily spend limit instead.

Citations

json
{
  "choices": [{
    "index": 0,
    "message": {
      "role": "assistant",
      "content": "Seoul is clear today with a high of 28 degrees.",
      "annotations": [
        {
          "type": "url_citation",
          "url_citation": {
            "url": "https://...",
            "title": "Seoul weather",
            "start_index": 0,
            "end_index": 47
          }
        }
      ]
    },
    "finish_reason": "stop"
  }],
  "x_everyais": {
    "web_search": {
      "queries": ["Seoul weather today"],
      "search_entry_point_html": "<div>...</div>",
      "billed_queries": 1
    }
  }
}
FieldDescription
message.annotations[]OpenAI url_citation citations. start_index and end_index are character positions in content
x_everyais.web_search.queriesQueries the model ran
x_everyais.web_search.billed_queriesSearches billed
x_everyais.web_search.search_entry_point_htmlGoogle search suggestions as HTML

If you show search results, Google requires you to display search_entry_point_html. Render this third-party HTML isolated, for example in <iframe sandbox srcdoc="...">.

Streaming

With stream: true, events arrive in this order:

  1. delta.content chunks
  2. One delta.annotations chunk
  3. The finish_reason chunk
  4. The usage chunk (choices: []) with x_everyais.web_search

Read the stream to the end if you track citations or cost.

Contact support