Skip to content
Rapid Router
Guides · Build

Web search

Ground any model in live web results with the web plugin or the :online suffix, with citations.

Ground any model with live web results. Attach the web plugin, or append :online to the model name for the same thing with defaults. The last user message becomes the search query, the results are handed to the model as numbered sources it is asked to cite, and the response carries one url_citation annotation per source plus a top-level web_search field with the engine used and the result count.

The plugin accepts max_results (default 5, capped at 10), search_prompt to replace the instruction that introduces the sources, and engine to pin one. Engines: exa and serper are the real search APIs and add a search fee on top of token cost, included in usage.cost. An exa search is billed what it costs: $0.007 plus $0.001 per result returned (5 results $0.012, 10 results $0.017), never less than the flat per-search fee; serper bills that flat fee ($0.004 per searched request unless it is changed). ddg is a free keyless fallback of noticeably lower quality, used automatically when no engine key is configured, and carries no fee.

Web search needs a paid model. A :free model bills nothing, so a request that asks for search on one (the web plugin or :online) is refused with a 400 before anything runs.

A broken search never breaks the completion: if the engine fails or times out (8s), the request proceeds without results, nothing extra is billed, and the response says "web_search": { "error": "search_failed" }. Annotations are returned on non-streamed responses; a streamed request is still searched and billed the same way. Batch items are not searched.

curl https://rapidrouter.ai/api/v1/chat/completions \
  -H "Authorization: Bearer $RAPIDROUTER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "google/gemini-3.6-flash",
    "plugins": [{ "id": "web", "max_results": 5 }],
    "messages": [{ "role": "user", "content": "What changed in the latest Node.js release?" }]
  }'

# -> ..., "web_search": { "engine": "exa", "results_count": 5 },
#    choices[0].message.annotations: [{ "type": "url_citation", "url": "...", "title": "..." }]