WebCite API
API documentation for WebCite public API endpoints. Use these endpoints to verify claims, search for sources, and manage citations.
Overview
https://api.webcite.co/apix-api-key: your-api-key-hereYou can create and manage API keys from the API Keys page.
Credit System
WebCite uses a credit-based billing system. Each API operation consumes credits from your monthly allocation. Credits are charged per claim, not per citation - each API call verifies 1 claim and returns multiple citations.
{ "...": "the endpoint's own result", "operation_id": "op_2f9c...", "usage": { "credits": 4 }}operation_id identifies this billed operation. It is null when the operation could not be recorded; the work still ran and the result is still yours, but there is nothing to reconcile against, so it reports no id rather than a fabricated one.
usage.credits is number | null. It is the number of credits actually deducted, or 0 only when the endpoint is genuinely priced at zero.
It is null when the call was not metered — for example a caller with no credits record, or an accounting write that failed after the work completed. Those cases previously reported 0, which told you the call was free when in fact it was simply never counted.
Handle it as credits ?? null rather than credits || 0. Coercing null to zero re-creates exactly the ambiguity this field exists to remove, and a ledger that books zeros for unmetered calls will not reconcile.
| Operation | Credits | Description |
|---|---|---|
Citation/Search | 2 | Search web sources for a claim. Returns multiple citations. |
Stance Analysis | 1 | Analyze if citations support or contradict the claim. Optional |
Verdict | 1 | Generate overall verification verdict. Optional |
| Full Verification | 4 | Citation + Stance + Verdict (default) |
// Citation only (2 credits){ "prompt": "Your claim here", "include_stance": false, "include_verdict": false} // Citation + Stance (3 credits){ "prompt": "Your claim here", "include_verdict": false} // Full verification (3 credits) - default{ "prompt": "Your claim here"}| Plan | Credits/Month | Price |
|---|---|---|
| Free | 100 | $0 |
| Builder | 500 | $20 |
| Enterprise | Custom | Custom |
/v1/payment/subscription/credits{ "credits": { "used": 12, "remaining": 88, "total": 100 }, "usage_breakdown": { "citations": 8, "stances": 3, "verdicts": 1 }, "allow_overage": true, "billing_period_start": "2026-01-01T00:00:00.000Z", "billing_period_end": "2026-01-31T23:59:59.000Z"}Get Current Setting
/v1/payment/subscription/overage-setting{ "allow_overage": true, "plan_type": "builder", "can_toggle": true}Toggle Overage Billing
/v1/payment/subscription/overage-setting// Request{ "allow_overage": false } // Response{ "allow_overage": false, "message": "Overage billing disabled. Requests will be blocked when credits are exhausted."}When overage is disabled, API requests return 400 error when credits are exhausted. When enabled, overages are billed at $0.03/credit.
// Metadata event in stream response{ "type": "metadata", "data": { "thread_id": "...", "citation_id": "...", "creditUsage": { "credits_used": 3, "credits_remaining": 47 } }}Important Notes
- Credits are charged per claim, not per citation
- Each API call verifies 1 claim and returns multiple citations
- All citations for a claim are covered by the credit cost
- Credits reset at the start of each billing period
Verify Claim
Verify a factual claim against authoritative sources. Returns sources with stance analysis and an overall verdict.
/api/v1/verifyRequest
curl -X POST 'https://api.webcite.co/api/api/v1/verify' \ -H 'Content-Type: application/json' \ -H 'x-api-key: YOUR_API_KEY' \ -d '{ "claim": "The Eiffel Tower is 330 meters tall", "include_stance": true, "include_verdict": true }'Parameters
| Parameter | Type | Description |
|---|---|---|
claimrequired | string | The factual claim to verify |
thread_idoptional | string | Thread ID to continue a conversation |
include_stanceoptional | boolean | Include stance analysis for each source (supports/contradicts/neutral). Adds 1 credit. Default: |
include_verdictoptional | boolean | Generate an overall verdict with confidence score. Adds 1 credit. Default: |
decompose_claimoptional | boolean | Break complex claims into atomic sub-claims and verify each independently. Default: |
Response
{ "citations": [ { "title": "TypeScript Official Documentation", "url": "https://www.typescriptlang.org/docs/", "snippet": "TypeScript is a strongly typed programming language...", "id": "1", "author": "typescriptlang", "status": "verified", "source_type": "Article" } ], "totalResults": 5, "thread_id": "123e4567-e89b-12d3-a456-426614174000"}Streaming Verification (SSE)
Stream verification results in real-time using Server-Sent Events. Citations are streamed as they are processed, followed by groups, verdict, and metadata.
/api/v1/verify/streamEvent Types
citationIndividual citations as they are processedgroupsCitation groups by domain (if useEnhancedAnalysis)verdictOverall verdict result (if useEnhancedAnalysis)decompositionClaim broken into sub-claims (if useClaimDecomposition)sub-claim-startStarting verification of a sub-claimsub-claim-resultResult for a sub-claim verificationmetadataThread ID, citation ID, totals, processing timedoneStream completeerrorError occurred (if applicable)JavaScript Example
const response = await fetch('https://api.webcite.co/api/api/v1/verify/stream', { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-api-key': 'YOUR_API_KEY' }, body: JSON.stringify({ claim: 'The Eiffel Tower is 330 meters tall' })}); const reader = response.body.getReader();const decoder = new TextDecoder(); while (true) { const { done, value } = await reader.read(); if (done) break; const chunk = decoder.decode(value); const lines = chunk.split('\n').filter(line => line.startsWith('data: ')); for (const line of lines) { const event = JSON.parse(line.slice(6)); switch (event.type) { case 'citation': console.log('New citation:', event.data);Search Sources
Search for authoritative sources related to a query. Returns raw citations without stance analysis or verdict. Use this for cheaper, faster searches when you don't need verification.
/api/v1/sources/searchRequest
curl -X POST 'https://api.webcite.co/api/api/v1/sources/search' \ -H 'Content-Type: application/json' \ -H 'x-api-key: YOUR_API_KEY' \ -d '{ "query": "climate change effects on coral reefs", "limit": 10 }'Parameters
| Parameter | Type | Description |
|---|---|---|
queryrequired | string | Search query to find sources for |
limitoptional | number | Maximum number of sources to return (1-20) Default: |
Enhanced Analysis
When useEnhancedAnalysis: true is set, the API returns additional fields that help you understand whether sources support or contradict the claim, and an overall verdict.
{ "title": "Example Source", "url": "https://example.com/article", "snippet": "The research confirms that...", "credibility_score": 92, // Enhanced Analysis Fields "stance": "supports", "stance_confidence": 88, "stance_explanation": "Source directly confirms the claim with data.", "highlight_terms": ["research confirms", "data shows"], "source_metadata": { "domain": "example.gov", "domain_category": "government", "is_primary_source": true, "is_fact_check_site": false }, // Verification Stamp (neuro-symbolic) "verification": {Fields
| Parameter | Type | Description |
|---|---|---|
layerrequired | string | Provenance tier: deterministic (exact bind-back to a document page/cell) > bound (normalized bind-back, or exact against a web page) > model (source exists but quote not bound back) > unbound (no source). |
bandrequired | string | Trust band to act on: verified / needs_review / unverified. |
confidencerequired | number | 0–100, capped by layer (deterministic 100, bound 90, model 70, unbound 40). |
groundedrequired | boolean | Whether the cited quote was bound back to its source. |
binding_methodoptional | string | exact / normalized / fuzzy / unbound. |
review_reasonoptional | string | Why the band was capped below verified, when applicable. |
Tip: filter on verification.band === "verified" to surface only citations whose quote is bound to a source with sufficient confidence.
{ "verdict": { "claim": "AI is transforming healthcare", "result": "supported", "confidence": 85, "summary": "Based on 4 authoritative sources, the claim is well-supported.", "stance_breakdown": { "supports": 3, "partially_supports": 1, "contradicts": 0, "neutral": 1, "inconclusive": 0, "irrelevant": 0, "unknown": 0 }, "origin_count": 4, "document_count": 5, "key_findings": [ { "finding": "AI diagnostic tools show 95% accuracy",Usage Notes
- Enhanced analysis adds processing time and token usage
- All enhanced fields are optional and only present when
useEnhancedAnalysis: true - If enhanced analysis fails, the API returns basic response
Claim Decomposition
Optional feature. When verifying complex claims containing multiple facts, set useClaimDecomposition: true to automatically break the claim into atomic sub-claims and verify each independently. This provides more accurate verification and identifies exactly which parts of a claim are true or false. Default is false (standard single-claim verification).
{ "prompt": "Tesla is the best-selling EV company founded by Elon Musk", "useEnhancedAnalysis": true, "useClaimDecomposition": true}{ "type": "decomposition", "data": { "original_claim": "Tesla is the best-selling EV company founded by Elon Musk", "sub_claims": [ { "id": "sub-1", "claim": "Tesla is the best-selling EV company", "status": "pending" }, { "id": "sub-2", "claim": "Elon Musk founded Tesla", "status": "pending" } ], "decomposition_reasoning": "The claim contains two distinct verifiable facts..." }}{ "type": "sub-claim-result", "data": { "sub_claim_id": "sub-2", "claim": "Elon Musk founded Tesla", "result": "contradicted", "confidence": 68, "summary": "5 of 8 sources contradict this claim.", "citation_count": 8, "supporting_count": 0, "contradicting_count": 5, "top_citations": [ { "id": "1", "title": "wikipedia.org", "url": "https://en.wikipedia.org/wiki/Tesla,_Inc.", "stance": "contradicts", "credibility_score": 69 } ] }}{ "type": "verdict", "data": { "claim": "Tesla is the best-selling EV company founded by Elon Musk", "result": "partially_false", "confidence": 75, "summary": "Analyzed 2 sub-claims: 1 verified, 1 contradicted.", "stance_breakdown": { "supports": 1, "partially_supports": 0, "contradicts": 1, "neutral": 0 }, "corrections": [ { "claimed": "Elon Musk founded Tesla", "actual": "Evidence contradicts this claim", "citation_ids": ["1", "2"] } ] }}When to Use Claim Decomposition
- Claims containing multiple facts (e.g., "X was founded by Y in Z")
- Statements with conjunctions (and, but, while, because)
- Complex assertions that need granular verification
- When you need to know exactly which parts are true vs false
Unified Response Structure
All responses use a unified tree structure with claim_groups as the single source of truth. Each claim contains its citations, domain groups, and verdict - no duplication.
{ "claim_groups": [ { "claim_id": "claim-1", "claim_index": 1, "claim": "Tesla was founded by Elon Musk", "stance_summary": "contradicted", "citation_count": 5, "citations": [ { "id": "1", "title": "Wikipedia - Tesla, Inc.", "url": "https://en.wikipedia.org/wiki/Tesla,_Inc.", "snippet": "Tesla was founded by Martin Eberhard and Marc Tarpenning...", "stance": "contradicts", "credibility_score": 85 } ], "domain_groups": [ { "group_id": "group-wikipedia-org", "domain": "wikipedia.org", "domain_category": "encyclopedia", "group_stance": "contradicts", "citation_ids": ["1"], "primary_citation_id": "1" } ], "verdict": { "claim": "Tesla was founded by Elon Musk", "result": "contradicted", "confidence": 85, "summary": "Tesla was founded by Eberhard and Tarpenning, not Musk.", "stance_breakdown": { "supports": 0, "partially_supports": 1, "contradicts": 4, "neutral": 0 } } } ], "totalResults": 5, "thread_id": "123e4567-e89b-12d3-a456-426614174000", "generated_prompts": []Key Benefits
- No duplication: Citations only appear in their claim_group
- Parallel verdicts: Each claim's verdict streams as its citations complete
- Single tree: claim_groups → citations + domain_groups + verdict
- Consistent structure: Same format for single and multi-claim queries
citations → Use claim_groups[n].citations
verdict → Use claim_groups[n].verdict
citation_groups → Use claim_groups[n].domain_groups
List Citations
Retrieves a paginated list of citations generated by the authenticated user.
/api/v1/citationsParameters
| Parameter | Type | Description |
|---|---|---|
pageoptional | number | Page number (starts from 1) Default: |
limitoptional | number | Number of items per page (max 100) Default: |
thread_idoptional | string | Filter citations by thread ID |
fieldsoptional | enum | Field set: minimal, basic, detailed, with_relations, all Default: |
Response
{ "statusCode": 200, "message": "Citations fetched successfully", "data": [ { "id": "123e4567-e89b-12d3-a456-426614174000", "thread_id": "thread-123", "citation": "[{\"title\":\"Example\",\"url\":\"https://example.com\"}]", "prompt": "Latest trends in AI", "is_active": true, "created_at": "2024-01-01T00:00:00.000Z" } ], "pagination": { "total": 100, "page": 1, "limit": 20, "totalPages": 5, "hasNextPage": true, "hasPreviousPage": falseGet Citation by ID
Retrieves a specific citation by its ID for the authenticated user.
/api/v1/citations/:idPath Parameters
| Parameter | Type | Description |
|---|---|---|
idrequired | string | The unique identifier of the citation |
Response
{ "statusCode": 200, "message": "Citation fetched successfully", "data": { "prompt": "Latest trends in AI", "citation": "[{\"title\":\"Example\",\"url\":\"https://example.com\"}]" }}Error Response (404)
{ "statusCode": 404, "message": "Citation not found or does not belong to the user"}Source Preview
Resolve a citation back to its exact source and render it, so you can show the evidence behind a claim. Web sources return a text-fragment deep link that scrolls to the quote; document sources return the cited page's text and a #page=N link.
Every preview includes a bindBack result: whether the cited quote is present in the source (grounded), how it matched (exact, normalized, fuzzy, or unbound), a similarity score, and the best-matching passage (matched_text) returned even when unbound so you always see the closest evidence. A fuzzy (paraphrase) match is never reported as verified; a citation that cannot be bound back is never reported as grounded.
/api/v1/citations/source-previewBody Parameters
Provide either url (web source) or asset_id (uploaded document).
| Parameter | Type | Description |
|---|---|---|
urloptional | string | Web source URL to preview. Provide this OR asset_id. |
asset_idoptional | string | Uploaded asset ID (from Upload File). Provide this OR url. Also accepts an asset://<id> citation url. |
pageoptional | number | 1-based page (PDF) or sheet index (spreadsheet). Default: 1 |
quoteoptional | string | The cited quote. It is bound back against the source text and highlighted. |
Request Example
{ "asset_id": "123e4567-e89b-12d3-a456-426614174000", "page": 2, "quote": "revenue grew 18% year over year"}Response — document page
{ "kind": "page", "asset_id": "123e4567-e89b-12d3-a456-426614174000", "page": 2, "text": "... revenue grew 18% year over year ...", "quote": "revenue grew 18% year over year", "deep_link": "https://cdn.webcite.co/doc.pdf#page=2", "binding": { "grounded": true, "method": "exact", "score": 1, "matched_quote": "revenue grew 18% year over year", "matched_text": "revenue grew 18% year over year" }}Response — web source
{ "kind": "web", "url": "https://en.wikipedia.org/wiki/Eiffel_Tower", "quote": "the Eiffel Tower is 330 metres tall", "deep_link": "https://en.wikipedia.org/wiki/Eiffel_Tower#:~:text=the%20Eiffel%20Tower%20is%20330%20metres%20tall", "binding": { "grounded": true, "method": "normalized" }}Error Response (400)
{ "statusCode": 400, "message": "Provide a web url (http/https) or an asset_id to preview."}Batch Verify
Check every claim in a document in one call. Each item is a quote plus its source (inline text, a url, or an uploaded asset). Per item you get whether the quote is grounded, how it matched, the best-matching passage and a score even when unbound, the verification tier, and a feedback token.
A fuzzy (paraphrase-level) match is capped at needs_review, never verified. A negated claim will not ground against an affirmative passage.
/api/v1/verify/batchBody Parameters
| Parameter | Type | Description |
|---|---|---|
itemsrequired | Item[] | Up to 200 items. Each: quote (the claim), plus its source as source_text (inline), url, or asset_id (with optional page), and an optional id echoed back. |
Request Example
{ "items": [ { "id": "1", "quote": "reduced HbA1c by 1.2%", "source_text": "A 1.2% reduction in HbA1c was observed versus placebo." } ]}Response (per item)
[ { "id": "1", "quote": "reduced HbA1c by 1.2%", "binding": { "grounded": true, "method": "fuzzy", "score": 0.67, "matched_text": "A 1.2% reduction in HbA1c was observed versus placebo." }, "verification": { "layer": "bound", "band": "needs_review", "confidence": 80 }, "feedback_token": "eyJxIjoi..." }]Cost: 1 credit per item. The work is per item — a 200-claim batch binds 200 quotes against 200 sources. BindBack is deterministic (no LLM calls), but a batch can be large and url/asset items fetch their source, so this endpoint is rate-limited more strictly than compute-only endpoints.
Feedback
Record a human verdict on a verification result using its feedback_token. The token carries the result summary, so token plus verdict is enough. Feedback is stored so corrections accumulate over time.
/api/v1/verify/feedbackBody Parameters
| Parameter | Type | Description |
|---|---|---|
tokenrequired | string | The feedback_token from a batch result. |
verdictrequired | string | correct, incorrect, or unsure. |
noteoptional | string | An optional note or correction. |
Response
{ "recorded": true }Cost: 1 credit. No LLM calls; records a single row. Subject to your plan's rate limits.
Conflict Analysis
Verify numbers, not just text. Given figures extracted across one or more documents, the engine recomputes derivable metrics from their primitives, detects cross-document conflicts, flags semantic contradictions, and returns a review flag: whether a human should look, and the concrete reasons (a conflict, a recompute mismatch, or model-read inputs). The findings are deterministic, so this is a flag with reasons, not a probability score.
/api/v1/analyze/conflictsBody Parameters
| Parameter | Type | Description |
|---|---|---|
figuresrequired | Figure[] | Extracted figures. Each: metric (dictionary key e.g. gross_margin), value (number), unit (percent|currency|multiple|ratio|count|months), optional entity/period, and provenance { assetId, documentName, page?, sheet?, cell?, method: rule|model }. |
Request Example
{ "figures": [ { "metric": "revenue", "value": 100, "unit": "currency", "provenance": { "assetId": "a", "documentName": "Data Room", "cell": "C5", "method": "rule" } }, { "metric": "cogs", "value": 40, "unit": "currency", "provenance": { "assetId": "a", "documentName": "Data Room", "cell": "C6", "method": "rule" } }, { "metric": "gross_margin", "value": 45, "unit": "percent", "provenance": { "assetId": "deck", "documentName": "Pitch Deck", "page": 7, "method": "model" } } ]}Response
{ "conflicts": [ /* cross-source or semantic disagreements */ ], "recomputations": [ { "metric": "gross_margin", "stated": 45, "computed": 60, "unit": "percent", "withinTolerance": false, "inputs": [ { "key": "revenue", "value": 100, "provenance": { "cell": "C5" } }, { "key": "cogs", "value": 40, "provenance": { "cell": "C6" } } ] } ], "review": { "needs_review": true, "reasons": ["a recomputed value does not match the stated value"] }}Deterministic compute, no LLM calls. Cost: 1 credit. Deterministic compute over the figures you send. Still subject to your plan's rate limits, since the request uses server compute.
Analyze Document
Document-in numeric analysis. Give an uploaded asset id; the document is downloaded, its figures are extracted, then recomputed and cross-checked. Returns the extracted figures alongside conflicts, recomputations, and a review flag.
Spreadsheets (xlsx/xls/csv) are extracted deterministically with exact cell provenance; these are rule reads. PDFs use a vision model that reads the printed figures without computing; these are model reads, capped at needs_review and never presented as verified. The value is cross-source: a deck figure that disagrees with the spreadsheet surfaces as a conflict.
/api/v1/analyze/documentBody Parameters
| Parameter | Type | Description |
|---|---|---|
asset_idrequired | string | An uploaded asset id (from POST /upload). Supported types: xlsx, xls, csv, pdf. |
Response
{ "figures": [ { "metric": "revenue", "value": 12400000, "unit": "currency", "provenance": { "sheet": "P&L", "cell": "B1", "method": "rule" } }, { "metric": "gross_margin", "value": 45, "unit": "percent", "provenance": { "sheet": "P&L", "cell": "B4", "method": "rule" } } ], "recomputations": [ { "metric": "gross_margin", "stated": 45, "computed": 60, "withinTolerance": false } ], "conflicts": [], "review": { "needs_review": true, "reasons": ["a recomputed value does not match the stated value"] }}Cost: 3 credits. The document is downloaded, parsed and (for PDFs) read page by page by a vision model.
Extract Figures
Extract every number in a document as a tagged, source-grounded figure. Each figure carries what it means (metric), its unit, an optional period (FY2023 vs FY2024 kept apart) and entity, a confidence band, whether it was confirmed against the cited cell (bound), and full provenance down to the sheet or page and cell.
Fully deterministic (no model calls). Works on spreadsheets (cell-level discovery, header scale, accounting negatives, unit-declaration checks), PDFs with a text layer (grounded and cited per page), and every other text-bearing format (docx, pptx, html, txt). Scanned image-only pages carry no machine-readable text and yield no figures.
/api/v1/extract/figuresBody Parameters
| Parameter | Type | Description |
|---|---|---|
asset_idoptional | string | An uploaded asset id (from POST /upload). Provide this or asset_url. |
asset_urloptional | string | A direct URL to your own file (e.g. a signed storage URL); the engine downloads it. Provide this or asset_id. |
Response
{ "figures": [ { "metric": "revenue", "value": 12500000, "unit": "currency", "period": "FY2023", "band": "verified", "bound": true, "provenance": { "sheet": "P&L", "cell": "B2", "method": "rule" } }, { "metric": "gross_margin", "value": 68, "unit": "percent", "period": "FY2023", "band": "verified", "bound": true, "provenance": { "sheet": "P&L", "cell": "B3", "method": "rule" } } ]}Cost: 2 credits. Deterministic (no LLM calls); downloads and runs the full figure engine over every sheet and page.
Extract Text
All-formats extraction into a normalized document: whole-doc markdown, per-page or per-sheet units with page/sheet provenance, and (for spreadsheets) sheet names. Deterministic for text-layer documents; an unreadable asset returns empty text rather than failing.
/api/v1/extractBody Parameters
| Parameter | Type | Description |
|---|---|---|
asset_idoptional | string | An uploaded asset id (from POST /upload). Provide this or asset_url. |
asset_urloptional | string | A direct URL to your own file; the engine downloads it. Provide this or asset_id. |
Response
{ "format": "pdf", "markdown": "# Financials\n\nRevenue grew ...", "extraction_method": "text_layer", "units": [ { "kind": "page", "index": 1, "text": "...", "extraction_method": "text_layer", "provenance": { "page": 1 } } ], "operation_id": "op_2f9c...", "usage": { "credits": 1 }}extraction_method says how the text was produced: text_layer (read directly from the file), ocr (transcribed from an image), or none (nothing could be extracted). The per-unit value is exact for that page or sheet; the top-level value is the dominant path across the document. A document that mixes both reports ocr on a tie, because calling a half-transcribed document a text-layer read overstates it.
This matters if you store extracted text as evidence: a vision transcription of a scan is a weaker claim than a deterministic text-layer read, and without this field the two are indistinguishable.
Cost: 1 credit. Deterministic for text-layer documents; downloads and parses a file.
Anchored Chunks
The same extraction, cut into retrieval-sized chunks that each carry where they came from. Use this instead of chunking markdown yourself when you intend to cite what you retrieve: a chunk you split client-side has no page, sheet or section to point back at, so a citation built on it cannot be checked.
/api/v1/extract/pagesBody Parameters
| Parameter | Type | Description |
|---|---|---|
asset_idoptional | string | An uploaded asset id (from POST /upload). Provide this or asset_url. |
asset_urloptional | string | A direct URL to your own file; the engine downloads it. Provide this or asset_id. |
Response
{ "chunks": [ { "text": "Revenue grew 18% year over year ...", "page": 4, "section": "Financial Review", "ordinal": 0, "extraction_method": "text_layer" }, { "text": "Segment margin by region ...", "sheet": "Q3 Summary", "ordinal": 1, "extraction_method": "text_layer" } ], "operation_id": "op_5a71...", "usage": { "credits": 1 }}Each chunk carries the anchors that apply to it: page for paginated documents, sheet for spreadsheets, section for the heading it falls under, and ordinal for its order within the document.
Anchors are omitted rather than guessed. A chunk from a document with no page structure has no page key at all, instead of a placeholder like 0 that would compare equal to every other unknown.
extraction_method is carried from the page the chunk was cut from, so it survives into whatever you store.
Cost: 1 credit.
Classify Document
Deterministic, model-free classification. Returns a coarse category plus the fine multi-type covers the document holds (a bundled workbook covers several). Pass an optional taxonomy preset (vc = venture data room, ma = M&A; default vc).
/api/v1/classifyBody Parameters
| Parameter | Type | Description |
|---|---|---|
asset_idoptional | string | An uploaded asset id. Provide this or asset_url. |
asset_urloptional | string | A direct URL to your own file. Provide this or asset_id. |
taxonomyoptional | string | "vc" (default) or "ma". |
Response
{ "category": "financials", "covers": ["Financials (P&L)", "Cap table"]}Cost: 1 credit. Deterministic, no LLM calls (air-gapped safe); downloads and parses a file.
Document Checklist
Given the documents already filed in a category, returns each expected document type flagged present or absent. An item is present when any document matches it by filename, category, or covered type. Advisory and deterministic; no I/O. Pass an optional taxonomy and stage (early/growth) to tailor the list.
/api/v1/gapsBody Parameters
| Parameter | Type | Description |
|---|---|---|
categoryrequired | string | The category to build the checklist for (e.g. "financials", "legal"). |
docsrequired | array | The documents already filed: [{ filename?, category?, covers?[] }]. May be empty. |
taxonomyoptional | string | "vc" (default) or "ma". |
stageoptional | string | "early" or "growth". |
Response
{ "items": [ { "name": "P&L / income statement", "present": true }, { "name": "Cap table", "present": true }, { "name": "Balance sheet", "present": false } ]}Cost: 1 credit. Pure and deterministic; no LLM calls or I/O.
Accuracy
The engine's measured accuracy against a gold-set corpus: conflict-detection recall and precision, and recompute correctness. Reproducible and gated on every build, so an accuracy regression cannot ship.
/api/v1/accuracyResponse
{ "deals": [ { "name": "Vantage Retail (Series A)", "pass": true, "conflicts": { "detectionRate": 1, "precision": 1 }, "recompute": { "checked": 1, "correct": 1 } } ], "totals": { "conflicts": { "expected": 4, "found": 4, "flagged": 4, "falsePositives": 0, "detectionRate": 1, "precision": 1 }, "recompute": { "checked": 4, "correct": 4 } }, "pass": true}Cost: 1 credit. No LLM calls; the report runs the deterministic gold-set eval on the server, so it is subject to your plan's rate limits.
Upload File
Uploads a file to storage and creates an asset record. Files are automatically sanitized and preserved as private evidence; the response includes an asset URL for downstream use.
/api/v1/uploadmultipart/form-dataRequest
curl -X POST 'https://api.webcite.co/api/api/v1/upload' \ -H 'x-api-key: YOUR_API_KEY' \ -F 'file=@/path/to/your/file.pdf'Response
{ "successCode": 200, "message": "File uploaded successfully", "data": { "asset_id": "123e4567-e89b-12d3-a456-426614174000", "asset_url": "https://storage.googleapis.com/bucket-name/path/to/file.pdf", "source_version_id": "123e4567-e89b-12d3-a456-426614174001" }}Errors
The endpoint mirrors the outcome in the HTTP status, so failures are never served as 2xx. Downstream 4xx errors (for example 400 or 404) are rethrown as-is in Nest's default { statusCode, message } shape, not successCode.
{ "successCode": 503, "message": "Private evidence storage required: set EVIDENCE_STORAGE_ROOT or EVIDENCE_BUCKET_NAME (I1; never public-first)"}Data Structures
{ // Required fields "title": "TypeScript Official Documentation", "url": "https://www.typescriptlang.org/docs/", "snippet": "TypeScript is a strongly typed programming language...", "id": "1", "author": "typescriptlang", "status": "verified", "credibility_score": 95, // Optional fields "source_type": "Article", "publication_year": 2024, // Enhanced Analysis fields (only with useEnhancedAnalysis: true) "stance": "supports", "stance_confidence": 90, "stance_explanation": "Source directly confirms the claim"}source_type can be: Government Document, Dataset, Journal, Report, Trusted Media, Article, Reddit, Social Media
stance can be: supports, contradicts, partially_supports, neutral, inconclusive, irrelevant
In verdict.stance_breakdown these are separate counts. neutral means the neutral stance and nothing else: a source that looked and took no side. It used to also absorb inconclusive (a source that looked and could not tell) and unscored sources, which made three different situations read as one. Those are now inconclusive and unknown. irrelevant is off-topic and is excluded from every verdict denominator. If you were reading neutral as “everything undecided”, sum the three.
credibility_basis says whether credibility_score rests on a measurement (measured) or on nothing (unknown). An unmeasured source previously scored 100, the maximum, which ranked the least-grounded citation highest. If you filter on a credibility threshold, check this field — an unknown basis means the score carries no evidence, not that the source is bad.
snippet_source says where the snippet text came from: fetched (the page was read), grounding (a search-provider segment), or fallback. snippet_extraction reports whether a relevant passage was found at all.
{ "total": 100, "page": 1, "limit": 20, "totalPages": 5, "hasNextPage": true, "hasPreviousPage": false}Integrations
WebCite integrates with popular AI platforms and automation tools. Use these integrations to add fact-verification to your workflows.
Claude Desktop Configuration
Add to ~/Library/Application Support/Claude/claude_desktop_config.json:
{ "mcpServers": { "webcite": { "command": "npx", "args": ["-y", "webcite-mcp-server"], "env": { "WEBCITE_API_KEY": "webcite_your_api_key_here" } } }}Claude Code
claude mcp add webcite -- npx -y webcite-mcp-serverexport WEBCITE_API_KEY=webcite_your_api_key_hereAvailable Tools
verify_claimFull verification with stance analysis and verdictverify_claim_streamStreaming verification for long-running claimssearch_sourcesSearch for authoritative sources (citations only)list_citationsList your past verification resultsget_citationGet details of a specific verificationupload_fileUpload a document to use as verification contextget_source_previewResolve a citation to its source, with a bindBack checkverify_batchCheck up to 200 quotes against their sources in one callverify_feedbackAccept, reject or flag a batch resultanalyze_conflictsRecompute and cross-check figures you already extractedanalyze_documentExtract, recompute and cross-check a spreadsheet or PDFclassify_documentCategory and covered types for an uploaded documentdocument_gaps“Usually also here” checklist for a categoryextract_documentAny format to normalized text and units with provenanceextract_figuresEvery number as a tagged, source-grounded figureaccuracy_reportThe engine’s measured accuracy against its gold setExample Usage
In Claude, say: "Use WebCite to verify: The Eiffel Tower is 330 meters tall"
Setup Instructions
- Go to ChatGPT → Explore GPTs → Create
- In the "Configure" tab, scroll to "Actions"
- Click "Create new action"
- Import the OpenAPI schema below
- Add your WebCite API key as authentication
OpenAPI Schema URL
https://api.webcite.co/openapi/gpt-actions.yamlAuthentication
In the Actions configuration, set:
- Authentication type:
API Key - Auth Type:
Custom - Custom Header Name:
x-api-key
Example Usage
Ask your GPT: "Fact check this: Electric vehicles produce more CO2 than gas cars"
Available Actions
Full verification with sources and verdict
Find authoritative sources for a topic
Verify multiple claims from a spreadsheet row
Example Workflows
- Slack channel → WebCite verify → Post result back
- Google Sheet row → Batch verify claims → Update sheet
- Email received → Extract claims → Verify → Reply
Rate Limits
API rate limits vary by plan. Exceeding limits returns a 429 error with retry information.
| Plan | Requests/Min | Requests/Day | Concurrent |
|---|---|---|---|
| Free | 10 | 100 | 2 |
| Builder | 30 | 1,000 | 5 |
| Enterprise | 100+ | Custom | Custom |
X-RateLimit-Limit: 30X-RateLimit-Remaining: 28X-RateLimit-Reset: 1706659200X-Credits-Used: 4X-Credits-Remaining: 496{ "statusCode": 429, "message": "Rate limit exceeded. Please wait 45 seconds.", "error": "Too Many Requests", "retryAfter": 45}Best Practices
- Implement exponential backoff when receiving 429 errors
- Use batch_verify for multiple claims instead of individual calls
- Cache verification results to avoid redundant API calls
- Monitor
X-RateLimit-Remainingto proactively manage usage
For more information, visit WebCite