HTTP API
The REST API gives you direct HTTP access to webref from any language or environment. No SDK is required.
Authentication
Include your API key in the Authorization header:
Authorization: Bearer wbrf_your_key_herecurl -X POST https://webref.ai/api/research \
-H "Authorization: Bearer wbrf_your_key" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: research-20260821-001" \
-d '{"query": "how to use React hooks"}'Use a unique Idempotency-Key for each logical request. Reuse that key when retrying the same request so a network failure cannot start or charge the research twice.
Research runs asynchronously. The initial response is 202 Accepted:
{
"receiptId": "rec_CiBzgzrTfNNWQjBrNgQ8LiW_MIOhKXfV",
"privateUrl": "https://webref.ai/r/rec_CiBzgzrTfNNWQjBrNgQ8LiW_MIOhKXfV",
"statusUrl": "https://webref.ai/api/research/progress/rec_CiBzgzrTfNNWQjBrNgQ8LiW_MIOhKXfV",
"state": "queued"
}Poll statusUrl with the same API key until state is completed or failed. A completed response contains content, trust, source URLs, privateUrl, an optional shareUrl, credits used, and duration.
curl https://webref.ai/api/research/progress/rec_CiBzgzrTfNNWQjBrNgQ8LiW_MIOhKXfV \
-H "Authorization: Bearer wbrf_your_key"The status and private receipt URLs belong to the account that created the research. Another account, or a request without authentication, receives 404. Keep privateUrl for later follow-ups and management, but do not cite or share it.
Publish a receipt
Research is private by default. Publish it only when you want a read-only link that anyone can open:
curl -X PUT https://webref.ai/api/receipts/rec_CiBzgzrTfNNWQjBrNgQ8LiW_MIOhKXfV/publication \
-H "Authorization: Bearer wbrf_your_key"{
"visibility": "published",
"shareUrl": "https://webref.ai/s/shr_t7hKRdp1YLc_nKWL7hvxYhB-jP4njKiO"
}Publishing twice returns the same active link. The shared page follows the latest state of the receipt, including later follow-ups. Unpublish to revoke every public representation of that link:
curl -X DELETE https://webref.ai/api/receipts/rec_CiBzgzrTfNNWQjBrNgQ8LiW_MIOhKXfV/publication \
-H "Authorization: Bearer wbrf_your_key"Publishing again after revocation creates a new shareUrl. The old link stays unavailable.
Research costs 1–3 credits, based on the number of research rounds used. Failed work is refunded.
Wait for the result
Add ?wait=true when a blocking response is more convenient:
curl -X POST "https://webref.ai/api/research?wait=true" \
-H "Authorization: Bearer wbrf_your_key" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: research-20260821-002" \
-d '{"query": "what changed in the latest Next.js release?"}'This returns 200 OK with the finished research when it completes within the wait window. Long-running work returns 202 Accepted with the same durable status URL instead, so clients must still handle both responses.
Quick examples
Python:
import time
import uuid
import requests
response = requests.post(
"https://webref.ai/api/research",
headers={
"Authorization": "Bearer wbrf_your_key",
"Idempotency-Key": str(uuid.uuid4()),
},
json={"query": "Python async patterns"},
)
response.raise_for_status()
result = response.json()
while result["state"] not in {"completed", "failed"}:
time.sleep(2)
poll_response = requests.get(
result["statusUrl"],
headers={"Authorization": "Bearer wbrf_your_key"},
)
poll_response.raise_for_status()
result = poll_response.json()
if result["state"] == "failed":
raise RuntimeError(result["failure"]["message"])
print(result["content"])JavaScript:
const response = await fetch("https://webref.ai/api/research", {
method: "POST",
headers: {
"Authorization": "Bearer wbrf_your_key",
"Content-Type": "application/json",
"Idempotency-Key": crypto.randomUUID()
},
body: JSON.stringify({ query: "JavaScript promises" })
});
if (!response.ok) throw new Error(await response.text());
let result = await response.json();
while (result.state !== "completed" && result.state !== "failed") {
await new Promise((resolve) => setTimeout(resolve, 2000));
const pollResponse = await fetch(result.statusUrl, {
headers: { "Authorization": "Bearer wbrf_your_key" }
});
if (!pollResponse.ok) throw new Error(await pollResponse.text());
result = await pollResponse.json();
}
if (result.state === "failed") throw new Error(result.failure.message);
console.log(result.content);Go:
req, _ := http.NewRequest("POST", "https://webref.ai/api/research",
strings.NewReader(`{"query": "Go error handling"}`))
req.Header.Set("Authorization", "Bearer wbrf_your_key")
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Idempotency-Key", "research-20260821-003")
resp, _ := http.DefaultClient.Do(req)The Go response is 202 Accepted; decode its statusUrl and poll it with the same Authorization header. In production code, check request, response, decode, and timeout errors.
What's next
- API Reference — Full endpoint documentation with all fields and error codes
- MCP integration — Connect webref to your AI agent in one paste