webref/docs

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_here

Get keys from your dashboard.

Research

Send a question, URL, or both:

bash
curl -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:

json
{
  "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.

bash
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:

bash
curl -X PUT https://webref.ai/api/receipts/rec_CiBzgzrTfNNWQjBrNgQ8LiW_MIOhKXfV/publication \
  -H "Authorization: Bearer wbrf_your_key"
json
{
  "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:

bash
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:

bash
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:

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:

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:

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