Accept turns on our own product analytics and lets the daily.dev ad pixel report to daily.dev; Decline keeps both off. The Reddit ad pixel runs either way, on our public pages and when you sign up or buy, to measure our ads. The daily.dev pixel loads on our public pages and at sign-up too, but reports nothing unless you accept. Ad pixels may set their own cookies and never see your chats. See our Privacy Policy.

API reference

API reference

Web search and web fetch tools

Add the provider's own web tool to a request and the model can search the web and read pages while it answers. Vani runs each search and page read, gives the model the results, and returns the answer with the tool calls, results and citations in the provider's own format: Anthropic's web_search and web_fetch server tools on /messages, the web_search tool on /responses, and web_search_options on /chat/completions.

Price
USD 0.01 per search (USD 10 per 1,000), plus tokens
Page reads
Tokens only
Per request
Up to 8 uses of each tool
Endpoints
POST /messages · /responses · /chat/completions
On this pageHow it works

How it works

The model decides when to search or read a page. Each call runs on Vani while the request is open, the result goes back to the model, and the model goes on with its answer. It works with every chat model in GET /models except the Derisked models (GLM 5.3 Derisked and its Flash version), whose requests are sent exactly as written: a request that asks one of them for web tools is refused with 400 hosted_web_tools_unsupported_model before anything is billed.

  • Results are input tokens of the model's next step, like any tool result. usage is the sum of every step of the request.
  • Search results and pages are untrusted web content: the model is told to use them as reference only and never to follow instructions found in them.
  • Web tools and your own function tools work in the same request. A step that calls both runs the web tools first; your tool calls come back to you as usual.

Messages: web_search and web_fetch

Add {"type": "web_search_20250305", "name": "web_search"} and, to read pages, {"type": "web_fetch_20250910", "name": "web_fetch"} to tools. The later dated versions work the same way: web_search_20260209 and web_search_20260318, web_fetch_20260209, web_fetch_20260309 and web_fetch_20260318 (as the Vercel AI SDK sends them). The anthropic-beta headers web-fetch-2025-09-10 and code-execution-web-tools-2026-02-09 are accepted but not needed.

  • web_search takes max_uses, allowed_domains or blocked_domains (not both; example.com covers its subdomains, example.com/docs the pages under that path) and user_location ({"type": "approximate", "city", "region", "country", "timezone"}, given to the model, which adds a place to a query when it matters).
  • web_fetch takes max_uses, allowed_domains / blocked_domains, citations: {"enabled": true} and max_content_tokens. It reads only URLs that you send (in your messages, tool results or system prompt) and URLs that earlier search and page results brought, never an address the model wrote in an earlier answer, so a model cannot be led to send data to an address of its own choosing. Pages are read from public HTTPS addresses whose robots.txt allows Vani's research fetcher; HTML, plain text and PDF come back as text.
  • The later versions' options: Vani runs no code execution, so there is no dynamic filtering. allowed_callers and response_inclusion are accepted and change nothing: every call is the model's own, and every result comes back in full. The server_tool_use blocks of the 2026 versions say "caller": {"type": "direct"}. use_cache: false (web_fetch 20260309 and later) reads the page live from its site, never from a stored copy. url_sources (web_fetch, every version) narrows where a URL may come from: user_input (your messages and system prompt; all or none), client_tool_results and server_tool_results (all, none, or only / except with {"type": "tool_reference", "name"} entries naming tools of the request).
  • tool_choice: {"type": "tool", "name": "web_search"} (or web_fetch) makes the first step call that tool.
  • The answer holds a server_tool_use block (srvtoolu_… id, input with the query or URL), its web_search_tool_result (each result with type: web_search_result, url, title, page_age and an opaque encrypted_content) or web_fetch_tool_result (a document with the page text and retrieved_at), then the text. A text block that links to a search result carries a web_search_result_location citation with a short cited_text.
  • A failed or refused call is a result block, never an HTTP error, and is not charged: web_search_tool_result_error with max_uses_exceeded, too_many_requests, invalid_input, query_too_long or unavailable; web_fetch_tool_result_error with url_not_allowed, url_not_accessible, unsupported_content_type, url_too_long, invalid_input, max_uses_exceeded, too_many_requests or unavailable.
  • usage.server_tool_use counts web_search_requests (the charged searches) and web_fetch_requests. A stream sends the blocks in order: the server_tool_use input as an input_json_delta, citations as citations_delta, and the counts in message_delta.
  • Send an answer back in the history as it came. Its server tool blocks are read as text (what was searched or read, the results' titles and URLs, the page text); encrypted_content and encrypted_index are opaque and carry nothing, and page_age is null where a page's date is not known.
Shell

A Messages request with web search

curl "https://api.vani.ai/v1/messages" \
  -H "x-api-key: $VANI_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "anthropic/claude-sonnet-5.5",
    "max_tokens": 1024,
    "messages": [{"role": "user", "content": "What changed in the latest Rust release?"}],
    "tools": [{"type": "web_search_20250305", "name": "web_search", "max_uses": 3}]
  }'
JSON

The answer (shortened)

{
  "content": [
    {"type": "server_tool_use", "id": "srvtoolu_01…", "name": "web_search", "input": {"query": "Rust latest release notes"}},
    {"type": "web_search_tool_result", "tool_use_id": "srvtoolu_01…", "content": [
      {"type": "web_search_result", "url": "https://blog.rust-lang.org/…", "title": "Announcing Rust …", "encrypted_content": "vws1.…", "page_age": null}
    ]},
    {"type": "text", "text": "The latest release … ([Rust blog](https://blog.rust-lang.org/…)).",
     "citations": [{"type": "web_search_result_location", "url": "https://blog.rust-lang.org/…", "title": "Announcing Rust …", "cited_text": "…", "encrypted_index": "vwi1.…"}]}
  ],
  "stop_reason": "end_turn",
  "usage": {"input_tokens": 2810, "output_tokens": 164, "server_tool_use": {"web_search_requests": 1, "web_fetch_requests": 0}}
}

Responses: the web_search tool

Add {"type": "web_search"} (or web_search_preview, and their dated names) to tools.

  • Options: search_context_size (low, medium by default, or high: how many results the model reads and how much of each), user_location ({"type": "approximate", city, region, country, timezone}) and filters.allowed_domains. tool_choice: {"type": "web_search"} makes the first step search.
  • Each search is a web_search_call output item with status and action: {"type": "search", "query"}; with include: ["web_search_call.action.sources"] the action also lists the result URLs in sources. The message's output_text carries url_citation annotations (start_index, end_index, url, title) for its links to results.
  • A stream sends response.output_item.added, response.web_search_call.in_progress, response.web_search_call.searching, response.web_search_call.completed and response.output_item.done for each search, and response.output_text.annotation.added before response.output_text.done.
  • Earlier web_search_call items and annotated messages in input are accepted.
Shell

A Responses request with web search

curl "https://api.vani.ai/v1/responses" \
  -H "Authorization: Bearer $VANI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"openai/gpt-6-sol","input":"What changed in the latest Rust release?","tools":[{"type":"web_search","search_context_size":"medium"}],"store":false}'

Chat Completions: web_search_options

Add web_search_options (search_context_size; user_location: {"type": "approximate", "approximate": {city, region, country, timezone}}). The model searches when the question needs it and answers with links; message.annotations lists url_citation entries (start_index, end_index, url, title). A stream sends them in one annotations delta just before the finish chunk.

Shell

A Chat Completions request with web search

curl "https://api.vani.ai/v1/chat/completions" \
  -H "Authorization: Bearer $VANI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"google/gemini-3.8-flash","messages":[{"role":"user","content":"What changed in the latest Rust release?"}],"web_search_options":{"search_context_size":"low"}}'

Price and billing

  • USD 0.01 per search that ran (USD 10 per 1,000), on top of the request's tokens. A search that ran but found nothing still counts; a search that failed or was refused (an error result) is never charged.
  • Page reads (web_fetch) cost tokens only: the page text the model reads is input tokens.
  • Prepaid keys pay from the prepaid balance; keys created in Vani Chat pay from the plan allowance, at the same amount.
  • When a request starts, Vani reserves the cost of every search its max_uses allows (8 when not set) on top of its tokens; what the searches did not use is released when the request ends. The balance or allowance must cover that reservation.
  • The request log keeps server_tool_use with the number of searches, page reads and the search fee. A request that fails before delivering anything is not charged, its searches included. A request you cancel, or whose stream you leave, after its searches ran is charged for those searches and the tokens it used.

API prices per model

Limits and privacy

  • Up to 8 uses of each tool per request; a larger max_uses is lowered to 8. A request runs at most 8 model steps and 16 tool calls.
  • Search queries up to 500 bytes (query_too_long above); URLs up to 2,000 characters; up to 60 web tool calls a minute per account (too_many_requests above).
  • max_content_tokens takes up to 25,000 tokens of page text (about 100,000 characters); longer pages are shortened.
  • A query that looks like personal data (an e-mail address, a phone number or another long number) is searched with extra privacy, and the pages it finds, like the URLs you send, are read by Vani's own fetcher only.
  • Vani does not keep search results or pages after the request; nothing is shared between accounts.

Clients

  • Claude Code: its WebSearch tool works with no extra setting (tested with Claude Code 2.1.299). Each WebSearch call is one search; Claude Code's WebFetch reads pages on your machine (no search fee; the page text it gives the model costs tokens as usual).
  • Codex: with web_search set to cached, indexed or live (cached is Codex's default), Codex sends its web search tool with the models it knows to support it, and Vani runs each search, always as a live search. Codex 0.159.2 does so with gpt-5.5 and gpt-5.4, for example, but sends no web search tool with gpt-6-sol or a model id it does not know. Keep it disabled if you do not want search fees.
  • The Anthropic and OpenAI SDKs read these blocks, items and annotations with their own types.

Claude Code and other client guidesAnthropic-compatible APIOpenAI-compatible API

More reference: OpenAI-compatible API · Anthropic-compatible API · Model ids, limits, headers and usage · MCP tools on the API · Media API: images and videos · Artifacts API · Responses API: scope and limits · API overview · Docs and quickstart