Web search
A model answers from the data it was trained on, so about yesterday’s news, today’s exchange rate or last week’s release it will either stay silent or invent something. The web_search parameter on POST /v1/chat/completions turns search on: the model decides on its own when to search, and returns an answer with links to the sources.
Values
Section titled “Values”| Value | What it does |
|---|---|
true or "auto" |
The provider’s native search where the model has one, Exa otherwise |
"native" |
The provider’s built-in search only |
"exa" |
Neutral Exa search regardless of the model |
absent or false |
No search |
Native search exists for OpenAI, Anthropic, Google and xAI models — except the older GPTs (gpt-4o, chatgpt-4o, gpt-4-turbo), which fall back to Exa. Do not infer it from the name: GET /v1/models reports capabilities.native_search per model.
"native" on a model without built-in search is not an error — the value is silently downgraded to "auto" and the request goes to Exa. That is deliberate: the engine choice usually lives in client settings and outlives a model switch, so a hard error would break a conversation for no good reason.
Sources in the response
Section titled “Sources in the response”Links arrive in message.annotations, in the OpenAI format:
{ "message": { "role": "assistant", "content": "The ECB left rates unchanged at its September meeting.", "annotations": [ {"type": "url_citation", "url_citation": {"url": "https://www.ecb.europa.eu/press/", "title": "ECB press release"}} ] }}When streaming, sources arrive in their own chunk carrying delta.annotations before the final chunk with finish_reason — a client that reads the stream to the end will not miss them. Nothing is mixed into the prose: content stays clean and the links stay structured.
Perplexity Sonar
Section titled “Perplexity Sonar”perplexity/sonar, sonar-pro and sonar-deep-research always search, regardless of web_search: search is part of the model and there is nothing to switch off. You do not need to pass the parameter, and the engine choice does not apply to them — which is exactly why their capabilities.native_search is false. Sources come back the same way, in annotations.
Pricing
Section titled “Pricing”Search is billed per request, separately from tokens, on top of the usual charge for the answer. Each model declares its own native-search price — it is in the catalog as pricing.web_search_rub_per_request (and web_search_usd_per_request). Exa has a single price across all models, so it does not appear on a model card; the actual charge for a given request is visible in GET /v1/history.
curl -s https://api.mixen.ai/v1/models \ -H "Authorization: Bearer $MIXEN_API_KEY" \| python -c "import json,sys; [print(m['id'], m['pricing'].get('web_search_rub_per_request')) for m in json.load(sys.stdin)['data'] if m['pricing'].get('web_search_rub_per_request')]"Before generating with search enabled we reserve the cost of the search and of the retrieved context on your balance — a request will not start if the money only covers the answer itself. A reserve is not a charge: whatever is not used stays on the balance, and you are billed for actual usage.
Examples
Section titled “Examples”from openai import OpenAI
client = OpenAI(base_url="https://api.mixen.ai/v1", api_key=MIXEN_API_KEY)
resp = client.chat.completions.create( model="gemini-3.1-pro", messages=[{"role": "user", "content": "What did OpenAI ship this week?"}], extra_body={"web_search": "native"},)
print(resp.choices[0].message.content)for a in resp.choices[0].message.annotations or []: print("—", a["url_citation"]["url"])curl https://api.mixen.ai/v1/chat/completions \ -H "Authorization: Bearer $MIXEN_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "gemini-3.1-pro", "web_search": "native", "messages": [{"role": "user", "content": "What did OpenAI ship this week?"}] }'Things to keep in mind
Section titled “Things to keep in mind”- The model searches, not you.
web_searchonly permits search; whether to go online is the model’s call. For a question it already knows the answer to there will be no search — and no charge for one. - Results arrive as input tokens. What is found is injected into the context, so such a request costs more than usual even beyond the search fee itself.
web_searchis not an OpenAI field. Official SDKs take it viaextra_body(Python) or as an extra body field (TypeScript, cURL).