Agent search & AI answers
POST /v1/ai-search — cited results and, where the source writes one, an answer: from agent search APIs (DeepSeek, Yuanbao, Tavily, Exa) or ChatGPT's own answers. Automatic failover; ChatGPT runs as an async job.
POST https://api.serphubapi.com/v1/ai-search
One endpoint, answer-first, for two kinds of source:
- Agent search APIs —
deepseek,yuanbao,tavily,exa: search built for agents. They return cited results; DeepSeek and Tavily add a short synthesized answer. - AI answers —
chatgpt(Perplexity and Gemini coming): the answer an AI assistant actually gives, with the sources it cites, collected live.
Pick a source with provider, or leave it on auto and SerpHubAPI tries them from cheapest up, moving on automatically if one fails. You are charged at most once, and nothing if every source fails.
Request
| Parameter | Type | Default | Description |
|---|---|---|---|
q | string | — | Required. The question or query (1–2048 characters). |
provider | string | auto | An agent search API (deepseek, yuanbao, exa, tavily) or an AI answer source (chatgpt). auto tries the available ones in cost order. The live list is in GET /v1/services (categories agent and ai). |
num | integer | 10 | Maximum number of citations, 1–100. Each source caps this at its own limit. |
mode | string | live | live always asks the source. cache_first may return an answer cached within the last hour, at half price — and free on a cache hit. |
curl https://api.serphubapi.com/v1/ai-search \
-H "X-API-Key: shapi_xxxxxxxx" \
-H "Content-Type: application/json" \
-d '{"q": "What changed in the latest EU AI Act guidance?", "provider": "auto"}'
Response (200)
Fast sources (deepseek, yuanbao, exa, tavily) answer in the same request:
{
"meta": {
"id": "sch_01J9Z3KQ8W",
"status": "success",
"provider": "deepseek",
"cached": false,
"credits_charged": 5,
"time_ms": 2410
},
"params": { "q": "What changed in the latest EU AI Act guidance?", "provider": "auto", "num": 10, "mode": "live" },
"answer": "The Commission's latest guidance clarifies ...",
"citations": [
{ "position": 1, "title": "Guidelines on the AI Act", "link": "https://example.eu/ai-act", "snippet": "...", "source": "example.eu", "date": "2026-10-30" }
]
}
| Field | Type | Description |
|---|---|---|
meta.provider | string | The source that answered. With provider=auto this tells you which one was used. |
meta.credits_charged | integer | Credits deducted: the source's catalog price, half with cache_first, 0 on a cache hit or an empty result. |
answer | string | null | The written answer. null when the source returns citations only (Yuanbao and Exa do not write answers). |
citations | array | Sources behind the answer: position, title, link, and when available snippet, source, date, score. |
auto only moves on when a source fails outright. A source that returns citations without an answer counts as a result, so auto stops there.
Async jobs (202)
Some sources collect their answer live from a chat interface — ChatGPT today, Perplexity and Gemini once they launch. That takes about 1–2 minutes, sometimes longer, which is too long for one HTTP request. For those sources the call returns 202 Accepted with a job:
{
"job_id": "aij_01J9Z3KQ8W",
"status": "pending",
"provider": "chatgpt",
"result_url": "/v1/ai-search/jobs/aij_01J9Z3KQ8W"
}
Poll the job until it finishes:
GET https://api.serphubapi.com/v1/ai-search/jobs/{job_id}
curl https://api.serphubapi.com/v1/ai-search/jobs/aij_01J9Z3KQ8W \
-H "X-API-Key: shapi_xxxxxxxx"
status is one of:
status | Meaning |
|---|---|
pending | Still collecting. Poll again in about 5 seconds. answer is null and citations is empty. |
done | Finished. answer, citations and meta have the same shape as the 200 response above. |
failed | Could not be completed. The body carries an error with code and message. A failed job is not charged. |
{
"job_id": "aij_01J9Z3KQ8W",
"status": "done",
"provider": "chatgpt",
"answer": "...",
"citations": [ { "position": 1, "title": "...", "link": "https://..." } ],
"meta": { "id": "aij_01J9Z3KQ8W", "status": "done", "provider": "chatgpt", "cached": false, "credits_charged": 10, "time_ms": 96400 }
}
How jobs are billed and kept:
- The credits are reserved when the job is created and settled once: charged the catalog price on
done, released onfailed. - Polling is free. A finished job returns its stored result with no further upstream call or charge.
- Async jobs always run live;
cache_firsthas no cache to hit for them. - A job can only be polled with the same API key that created it, and is kept for at least 24 hours.
Polling example (Python)
import time, requests
API = "https://api.serphubapi.com"
H = {"X-API-Key": "shapi_xxxxxxxx"}
r = requests.post(f"{API}/v1/ai-search", headers=H, json={"q": "best CRM for startups", "provider": "chatgpt"})
body = r.json()
if r.status_code == 202:
while body["status"] == "pending":
time.sleep(5)
body = requests.get(f"{API}{body['result_url']}", headers=H).json()
print(body.get("answer"), body.get("citations"))
Polling example (JavaScript)
const API = "https://api.serphubapi.com";
const H = { "X-API-Key": "shapi_xxxxxxxx", "Content-Type": "application/json" };
let r = await fetch(`${API}/v1/ai-search`, { method: "POST", headers: H, body: JSON.stringify({ q: "best CRM for startups", provider: "chatgpt" }) });
let body = await r.json();
while (r.status === 202 && body.status === "pending") {
await new Promise((ok) => setTimeout(ok, 5000));
body = await (await fetch(`${API}${body.result_url}`, { headers: H })).json();
}
console.log(body.answer, body.citations);
With provider=auto, the call returns 200 when a fast source answers, and switches to a 202 job only if it has to fall back to a slow one — so always handle both.
Errors
| HTTP | Code | When |
|---|---|---|
| 400 | validation_error | Missing q, or provider is not an agent search or AI answer source |
| 401 | invalid_api_key | Missing, invalid or disabled key |
| 402 | insufficient_balance | Not enough credits for the source's price |
| 404 | not_found | Polling a job that does not exist or was created with a different API key |
| 429 | rate_limited | Rate limit or key credit limit reached |
| 502 | all_upstreams_failed | No AI source could answer. Not charged |
| 503 | engine_unavailable | The chosen source is not launched or temporarily unavailable |
Details in Errors. Prices per source are on the services & pricing page.