Research
Async deep research: Claude plans Google searches, reads and ranks the pages, fills gaps and writes a Markdown report with numbered citations to its sources.
POST
https://api.serpkite.com/v1/research
Credits: 30 (lite), 75 (standard) or 200 (deep) per report, charged only when it is written
Research is an async task for questions one search can't answer. Claude Haiku 5.5 plans Google queries for your input, the pages they find are read and ranked, a decision model (OpenAI's Decisions API) checks whether the notes already cover the task and drops off-topic sources, Claude reviews the gaps and plans follow-up rounds, then writes a Markdown report that cites numbered sources. With output_schema the result also has a JSON value in output.
Effort: lite runs 3 first-round queries in 1 round and reads 2 pages per query, for 30 credits; standard runs 5 queries over 2 rounds with 3 pages each, for 75; deep runs 8 queries over 3 rounds with 4 pages each, for 200. See the Deep research guide.
POST /v1/research returns 202 with a task. Poll GET /v1/research/{id} (progress while it runs, result when it ends; kept 24 hours) or receive the signed research.completed webhook. DELETE /v1/research/{id} cancels it: a queued task is refunded at once, a running one stops at its next round and is charged 1 credit per search already run.
The flat price is reserved when the task is queued and charged only when the report is written; research that fails is refunded in full.
Request body
| Parameter | Type | Default | Description |
|---|---|---|---|
input required | string | The research task in plain words, up to 8,000 characters (q is accepted as an alias). |
|
effort | string | standard | How much to search and read: lite 30, standard 75, deep 200 credits. One of: lite, standard, deep. |
output_schema | object | A JSON Schema (at most 16 KB); the report is also returned as a JSON value in result.output. |
|
country | string | Search from this country (two-letter code). | |
language | string | Search in this language. | |
include_domains | string[] | Search only these domains (up to 20). | |
exclude_domains | string[] | Never use these domains (up to 20). | |
webhook_url | string | Receives the signed research.completed event. Defaults to the account webhook URL. |
Example request
Authenticate with Authorization: Bearer $SERPKITE_API_KEY (GET requests may pass
?api_key= instead). The official SDKs read
SERPKITE_API_KEY for you. See Authentication.
curl https://api.serpkite.com/v1/research \
-H "Authorization: Bearer $SERPKITE_API_KEY" \
-H "Content-Type: application/json" \
-d '{"input":"compare espresso machines under $500 for a small office","effort":"standard"}'Response fields
| Field | Type | Description |
|---|---|---|
id | string | The task's ID. poll_url is https://api.serpkite.com/v1/research/{id}. |
status | string | queued, running, completed, failed or canceled. |
credits_reserved / credits_used | number | The flat price reserved at enqueue, and what was charged when the task ended. |
progress | object | While running: round, rounds, queries, sources, step (searching, reviewing, writing). |
result | object | When it ends: input, effort, report (Markdown with [n] markers), citations[], sources[] (index, title, link, domain, published_at, query), queries[], stats (searches, sources, rounds), llm, and output / output_error with output_schema. |
error | object | null | Set when the task failed (refunded) or was canceled. |
Every billed response also carries credit and latency headers
(X-Credits-Used, X-Credits-Remaining, X-Request-Id…).
Example response
{
"id": "01926a3e-8c4d-7e1f-a2b3-c4d5e6f7a8b9",
"kind": "research",
"status": "completed",
"created_at": "2026-10-24T12:00:00Z",
"started_at": "2026-10-24T12:00:01Z",
"completed_at": "2026-10-24T12:01:38Z",
"credits_reserved": 75,
"credits_used": 75,
"webhook_status": null,
"progress": {
"round": 2,
"rounds": 2,
"queries": 8,
"sources": 14,
"step": "writing"
},
"result": {
"input": "compare espresso machines under $500 for a small office",
"effort": "standard",
"report": "## Summary\n\nFor a small office, a heat-exchanger machine with a 2-litre tank is the safest pick under $500 [1][3]…",
"citations": [
{
"index": 1,
"title": "The best espresso machines under $500",
"link": "https://www.example.com/best-espresso-under-500",
"domain": "example.com"
}
],
"sources": [
{
"index": 1,
"title": "The best espresso machines under $500",
"link": "https://www.example.com/best-espresso-under-500",
"domain": "example.com",
"query": "best espresso machine under $500 office"
}
],
"queries": [
"best espresso machine under $500 office",
"office espresso machine tank size"
],
"stats": {
"searches": 8,
"sources": 14,
"rounds": 2
},
"llm": {
"provider": "anthropic",
"model": "claude-haiku-5-5",
"input_tokens": 41200,
"output_tokens": 1650
}
},
"error": null
}Errors
Errors use one shape: {"error":{"code","message","request_id"}}. Errors are never billed.
Full list in Errors.
| Status | Code | Meaning |
|---|---|---|
| 400 | invalid_request | A parameter is missing or invalid. |
| 401 | unauthorized | The API key is missing, invalid or revoked. |
| 402 | insufficient_credits | Your balance is too low. Buy a pack or wait for the monthly free grant. |
| 429 | rate_limited | Too many requests per second for your plan. Retry after the Retry-After header. |
| 503 | upstream_error | Google could not be fetched or parsed. Not billed; retry after Retry-After. |
| 503 | ai_unavailable | An AI step (answer, summary, schema extraction, research) could not run. The model part is not billed; on /v1/answer the search that ran is. |
Notes
- Research tasks share the per-account task limit with crawls: at most 20 queued or running at once (
429beyond that). - The input, the planned queries and the page text are sent to Anthropic (writing) and OpenAI (decision checks) under their API terms, which exclude training on API data. See Privacy and data retention.
- The remote MCP server has
researchandresearch_resulttools.