# Search sources

Find sources for a query without requesting stance analysis or a verdict.

Documentation index: https://webcite.co/llms.txt
Canonical page: https://webcite.co/api-docs/search
API origin: https://api.webcite.co
Authentication: x-api-key header. Keep keys on your server.

## When to use it

`limit` is the maximum number of returned sources (1-20), not a guarantee. Filters guide retrieval and filter returned metadata. A source with unknown required metadata does not match.

Filter by `source_type`, `is_primary_source`, `publication_year` (`from`, `to`), or `domain`. Domain filters include subdomains. Explicit `is_primary_source: false` is a filter, not an omitted value.

## Request

POST /api/v1/sources/search

2 credits.

### curl

```curl
curl --fail-with-body -X POST 'https://api.webcite.co/api/v1/sources/search' \
  -H "x-api-key: $WEBCITE_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{
  "query": "climate change effects on coral reefs",
  "limit": 10
}'
```

### Node.js

```javascript
const response = await fetch("https://api.webcite.co/api/v1/sources/search", {
  method: "POST",
  headers: {
    "x-api-key": process.env.WEBCITE_API_KEY,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
  "query": "climate change effects on coral reefs",
  "limit": 10
}),
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());
```

### python

```python
import os
import json
import requests

payload = json.loads("{\n  \"query\": \"climate change effects on coral reefs\",\n  \"limit\": 10\n}")
response = requests.post(
    "https://api.webcite.co/api/v1/sources/search",
    headers={"x-api-key": os.environ["WEBCITE_API_KEY"]},
    json=payload,
    timeout=(10, 300),
)
response.raise_for_status()
print(response.json())
```

## Response

Returns source results using the shared search response schema. Analysis fields from verification may be absent.

## Errors

For 400, check the request fields and source identifiers. For 401, check your API key. For 429, wait for the retry interval. See the errors guide before retrying a billable request.

## OpenAPI operation

```json
{
  "path": "/api/v1/sources/search",
  "method": "POST",
  "operation": {
    "description": "Search for authoritative sources related to a query. Returns raw citations without stance analysis or verdict.\n\n**Credits: 2** (search only)",
    "operationId": "ApiV1Controller_searchSources",
    "parameters": [],
    "requestBody": {
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/SearchSourcesDto"
          }
        }
      },
      "required": true
    },
    "responses": {
      "200": {
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/SearchResponseDto"
            }
          }
        },
        "description": "Sources found"
      },
      "401": {
        "description": "Unauthorized - API key required"
      },
      "429": {
        "description": "Rate limit exceeded"
      }
    },
    "security": [
      {
        "x-api-key": []
      },
      {
        "bearer": []
      }
    ],
    "summary": "Search for sources",
    "tags": [
      "Public API"
    ]
  },
  "schemas": {
    "SearchSourcesDto": {
      "properties": {
        "filters": {
          "additionalProperties": false,
          "description": "Applied to retrieval query and retained source metadata. Domain includes subdomains; false primary-source is an explicit filter. Unknown required metadata does not match.",
          "properties": {
            "domain": {
              "items": {
                "type": "string"
              },
              "maxItems": 20,
              "minItems": 1,
              "type": "array"
            },
            "is_primary_source": {
              "type": "boolean"
            },
            "publication_year": {
              "additionalProperties": false,
              "properties": {
                "from": {
                  "maximum": 9999,
                  "minimum": 1000,
                  "type": "integer"
                },
                "to": {
                  "maximum": 9999,
                  "minimum": 1000,
                  "type": "integer"
                }
              },
              "type": "object"
            },
            "source_type": {
              "items": {
                "type": "string"
              },
              "maxItems": 20,
              "minItems": 1,
              "type": "array"
            }
          },
          "type": "object"
        },
        "limit": {
          "default": 10,
          "description": "Maximum number of sources to return (1-20)",
          "maximum": 20,
          "minimum": 1,
          "type": "number"
        },
        "query": {
          "description": "Search query to find sources for",
          "example": "climate change effects on coral reefs",
          "type": "string"
        }
      },
      "required": [
        "query"
      ],
      "type": "object"
    },
    "SearchResponseDto": {
      "properties": {
        "citations": {
          "deprecated": true,
          "description": "[DEPRECATED] Use claim_groups[0].citations instead. Legacy citations array.",
          "items": {
            "$ref": "#/components/schemas/CitationDto"
          },
          "type": "array"
        },
        "claim_groups": {
          "description": "Unified tree: All data organized by claim. Each claim_group contains citations, domain_groups, and verdict.",
          "items": {
            "$ref": "#/components/schemas/ClaimGroupDto"
          },
          "type": "array"
        },
        "content": {
          "description": "Text content from agent (for non-citation responses)",
          "type": "string"
        },
        "domain_groups": {
          "deprecated": true,
          "description": "[DEPRECATED] Use claim_groups[n].domain_groups instead. Legacy domain grouping.",
          "items": {
            "$ref": "#/components/schemas/DomainGroupDto"
          },
          "type": "array"
        },
        "generated_prompts": {
          "description": "Generated sub-prompts when useMultiplePrompt is enabled",
          "example": [
            "What are the latest AI trends?",
            "What are emerging AI technologies?"
          ],
          "items": {
            "type": "string"
          },
          "type": "array"
        },
        "operation_id": {
          "description": "Billing operation identifier on public v1 responses; null when no operation was recorded.",
          "nullable": true,
          "type": "string"
        },
        "search_metadata": {
          "allOf": [
            {
              "$ref": "#/components/schemas/SearchMetadataDto"
            }
          ],
          "description": "Metadata about the search and analysis process"
        },
        "thread_id": {
          "description": "Thread ID for conversation continuity",
          "example": "123e4567-e89b-12d3-a456-426614174000",
          "type": "string"
        },
        "totalResults": {
          "description": "Total number of citations across all claims",
          "example": 5,
          "type": "number"
        },
        "usage": {
          "allOf": [
            {
              "$ref": "#/components/schemas/BillingUsageDto"
            }
          ],
          "description": "Billing usage on public v1 responses."
        },
        "verdict": {
          "allOf": [
            {
              "$ref": "#/components/schemas/VerdictDto"
            }
          ],
          "deprecated": true,
          "description": "[DEPRECATED] Use claim_groups[n].verdict instead. Legacy overall verdict."
        }
      },
      "type": "object"
    },
    "CitationDto": {
      "properties": {
        "author": {
          "description": "Author or domain name",
          "example": "example",
          "type": "string"
        },
        "credibility_basis": {
          "description": "Whether credibility_score rests on an actual measurement ('measured') or is a placeholder because no check has run yet ('unknown', e.g. no grounding signal or the citation has not been analysed). Absent means the same as \"measured\" for citations produced before this field existed.",
          "enum": [
            "measured",
            "heuristic",
            "unknown"
          ],
          "example": "measured",
          "type": "string"
        },
        "credibility_score": {
          "description": "Credibility/relevance score from 1-100 (higher = more credible/relevant/authoritative)",
          "example": 95,
          "type": "number"
        },
        "evidence": {
          "description": "Publisher evidence receipt v1: state, originalUrl, finalUrl, contentHash, retrievedAt, quoteMatch, typed publisher dates, retention, replayable and failureReason. Missing on legacy records means unknown provenance.",
          "type": "object"
        },
        "group_id": {
          "description": "Group ID for citations from the same domain",
          "example": "group-example-com",
          "type": "string"
        },
        "highlight_ranges": {
          "description": "Character ranges [start, end] in snippet that are most relevant to the claim",
          "example": [
            [
              10,
              25
            ],
            [
              40,
              55
            ]
          ],
          "items": {
            "type": "string"
          },
          "type": "array"
        },
        "id": {
          "description": "Unique citation identifier",
          "example": "1",
          "type": "string"
        },
        "is_group_primary": {
          "description": "Whether this is the primary (highest-ranked) citation from its domain group",
          "example": true,
          "type": "boolean"
        },
        "publication_year": {
          "description": "Publication year of the cited source",
          "example": 2024,
          "type": "number"
        },
        "rank": {
          "description": "Sequential rank (1, 2, 3...) where rank 1 is the highest/best citation, based on credibility_score and verified status",
          "example": 1,
          "type": "number"
        },
        "ranking_factors": {
          "allOf": [
            {
              "$ref": "#/components/schemas/RankingFactorsDto"
            }
          ],
          "description": "Breakdown of how the ranking score was calculated"
        },
        "snippet": {
          "description": "Relevant excerpt from the source",
          "example": "This is a snippet from the article...",
          "type": "string"
        },
        "source_metadata": {
          "allOf": [
            {
              "$ref": "#/components/schemas/SourceMetadataDto"
            }
          ],
          "description": "Additional metadata about the source"
        },
        "source_type": {
          "description": "Source type: Government Document, Dataset, Journal, Report, Trusted Media, Article, Reddit, Social Media",
          "enum": [
            "Government Document",
            "Dataset",
            "Journal",
            "Report",
            "Trusted Media",
            "Article",
            "Reddit",
            "Social Media"
          ],
          "example": "Article",
          "type": "string"
        },
        "stance": {
          "description": "Whether this citation supports or contradicts the claim (only with useEnhancedAnalysis)",
          "enum": [
            "supports",
            "contradicts",
            "partially_supports",
            "neutral",
            "inconclusive"
          ],
          "example": "supports",
          "type": "string"
        },
        "stance_confidence": {
          "description": "Confidence in the stance assessment (0-100)",
          "example": 90,
          "type": "number"
        },
        "stance_explanation": {
          "description": "Brief explanation of the stance determination",
          "example": "The source directly confirms the key claim with supporting data.",
          "type": "string"
        },
        "status": {
          "description": "Verification status of the citation",
          "example": "verified",
          "type": "string"
        },
        "title": {
          "description": "Title of the cited source",
          "example": "Example Article Title",
          "type": "string"
        },
        "url": {
          "description": "URL of the cited source",
          "example": "https://example.com/article",
          "type": "string"
        }
      },
      "required": [
        "title",
        "url",
        "snippet",
        "id",
        "author",
        "status",
        "credibility_score",
        "rank"
      ],
      "type": "object"
    },
    "RankingFactorsDto": {
      "properties": {
        "content_relevance": {
          "description": "How well the content matches the claim being verified (0-100).",
          "example": 85,
          "type": "number"
        },
        "recency": {
          "description": "Publication freshness score (0-100). Current year = 100, decreases with age.",
          "example": 100,
          "type": "number"
        },
        "source_authority": {
          "description": "Domain reputation score (0-100). Higher scores for government, academic, major news sources.",
          "example": 90,
          "type": "number"
        }
      },
      "required": [
        "source_authority",
        "content_relevance",
        "recency"
      ],
      "type": "object"
    },
    "SourceMetadataDto": {
      "properties": {
        "domain": {
          "description": "Extracted domain from URL",
          "example": "example.gov",
          "type": "string"
        },
        "domain_category": {
          "description": "Category of the source domain",
          "enum": [
            "government",
            "academic",
            "news",
            "organization",
            "encyclopedia",
            "social",
            "other"
          ],
          "example": "government",
          "type": "string"
        },
        "is_fact_check_site": {
          "description": "Whether this is a fact-checking website (snopes, politifact, etc.)",
          "example": false,
          "type": "boolean"
        },
        "is_primary_source": {
          "description": "Whether this is a primary source (government, official, press release)",
          "example": true,
          "type": "boolean"
        }
      },
      "required": [
        "domain",
        "domain_category",
        "is_primary_source",
        "is_fact_check_site"
      ],
      "type": "object"
    },
    "ClaimGroupDto": {
      "properties": {
        "citation_count": {
          "description": "Number of citations for this claim",
          "example": 5,
          "type": "number"
        },
        "citations": {
          "description": "All citations for this claim (full objects with stance, ranking, etc.)",
          "items": {
            "$ref": "#/components/schemas/CitationDto"
          },
          "type": "array"
        },
        "claim": {
          "description": "The claim/sub-prompt text",
          "example": "What are the AI trends in healthcare?",
          "type": "string"
        },
        "claim_id": {
          "description": "Unique identifier for this claim group",
          "example": "claim-1",
          "type": "string"
        },
        "claim_index": {
          "description": "Index of the claim (1-based)",
          "example": 1,
          "type": "number"
        },
        "domain_groups": {
          "description": "Citations grouped by domain (lightweight, for deduplication UI)",
          "items": {
            "$ref": "#/components/schemas/DomainGroupDto"
          },
          "type": "array"
        },
        "stance_summary": {
          "description": "Overall stance summary based on citations",
          "enum": [
            "supported",
            "contradicted",
            "mixed",
            "unverifiable"
          ],
          "example": "supported",
          "type": "string"
        },
        "verdict": {
          "allOf": [
            {
              "$ref": "#/components/schemas/VerdictDto"
            }
          ],
          "description": "Verdict for this claim (streamed as citations complete)"
        }
      },
      "required": [
        "claim_id",
        "claim_index",
        "claim",
        "stance_summary",
        "citation_count",
        "citations"
      ],
      "type": "object"
    },
    "DomainGroupDto": {
      "properties": {
        "domain": {
          "description": "Domain that groups these citations",
          "example": "example.com",
          "type": "string"
        },
        "domain_category": {
          "description": "Category of this domain",
          "enum": [
            "government",
            "academic",
            "news",
            "organization",
            "encyclopedia",
            "social",
            "other"
          ],
          "example": "news",
          "type": "string"
        },
        "group_id": {
          "description": "Unique identifier for this domain group",
          "example": "group-example-com",
          "type": "string"
        },
        "group_stance": {
          "description": "Overall stance of citations from this domain",
          "enum": [
            "supports",
            "contradicts",
            "mixed",
            "neutral"
          ],
          "example": "supports",
          "type": "string"
        },
        "primary_citation_id": {
          "description": "ID of the primary (highest-ranked) citation from this domain",
          "example": "1",
          "type": "string"
        }
      },
      "required": [
        "group_id",
        "domain",
        "domain_category",
        "group_stance",
        "primary_citation_id"
      ],
      "type": "object"
    },
    "VerdictDto": {
      "properties": {
        "aggregation_score": {
          "description": "Legacy aggregate score retained for compatibility",
          "type": "number"
        },
        "calibrated_confidence": {
          "nullable": true,
          "type": "number"
        },
        "claim": {
          "description": "The original prompt/claim that was analyzed",
          "example": "User query or claim being verified",
          "type": "string"
        },
        "confidence": {
          "description": "Legacy aggregation score (0-100); use confidence_available and calibrated_confidence for calibration status",
          "example": 88,
          "type": "number"
        },
        "confidence_available": {
          "description": "True only when calibrated confidence is available",
          "type": "boolean"
        },
        "confidence_basis": {
          "enum": [
            "unknown",
            "heuristic",
            "calibrated"
          ],
          "type": "string"
        },
        "conflict": {
          "allOf": [
            {
              "$ref": "#/components/schemas/NamedConflictDto"
            }
          ],
          "description": "The quoted, named pair of sources behind a \"mixed\" verdict. Null for every other verdict.",
          "nullable": true,
          "type": "object"
        },
        "correction_status": {
          "description": "Whether a source-backed replacement statement is available",
          "enum": [
            "available",
            "not_established",
            "conflicted",
            "not_needed"
          ],
          "type": "string"
        },
        "corrections": {
          "description": "Corrections when the claim contains inaccuracies",
          "items": {
            "$ref": "#/components/schemas/CorrectionDto"
          },
          "type": "array"
        },
        "document_breakdown": {
          "allOf": [
            {
              "$ref": "#/components/schemas/StanceBreakdownDto"
            }
          ],
          "description": "Stance counts over every document analysed, before syndicated copies of one telling were collapsed into a single origin."
        },
        "document_count": {
          "description": "Documents analysed. Reported for transparency; origin_count is what the verdict counts.",
          "example": 5,
          "type": "number"
        },
        "insufficient_evidence": {
          "description": "True when the counts were split but no two sources could be quoted disagreeing, so the split was reported as unverifiable rather than as a controversy.",
          "example": false,
          "type": "boolean"
        },
        "key_findings": {
          "description": "Key facts extracted from citations (only with useEnhancedAnalysis)",
          "items": {
            "$ref": "#/components/schemas/KeyFindingDto"
          },
          "type": "array"
        },
        "origin_count": {
          "description": "Distinct origins behind those documents. Four outlets running one wire story are four documents and one origin, and only this number votes.",
          "example": 2,
          "type": "number"
        },
        "result": {
          "description": "Overall verdict based on citation analysis",
          "enum": [
            "supported",
            "partially_supported",
            "contradicted",
            "mixed",
            "unverifiable"
          ],
          "example": "supported",
          "type": "string"
        },
        "stance_breakdown": {
          "allOf": [
            {
              "$ref": "#/components/schemas/StanceBreakdownDto"
            }
          ],
          "description": "Breakdown of citation stances over distinct ORIGINS, which is what the verdict is computed from. For the raw per-document counts before origins were collapsed, see document_breakdown."
        },
        "summary": {
          "description": "Human-readable summary of the findings",
          "example": "Based on 4 authoritative sources, the claim appears to be well-supported by available evidence.",
          "type": "string"
        },
        "unverified_claims": {
          "description": "Parts of the claim that could not be verified by any source",
          "example": [
            "Aspect of claim that could not be verified"
          ],
          "items": {
            "type": "string"
          },
          "type": "array"
        }
      },
      "required": [
        "claim",
        "result",
        "confidence",
        "summary",
        "stance_breakdown"
      ],
      "type": "object"
    },
    "NamedConflictDto": {
      "properties": {
        "contradicting": {
          "$ref": "#/components/schemas/ConflictSideDto"
        },
        "supporting": {
          "$ref": "#/components/schemas/ConflictSideDto"
        }
      },
      "required": [
        "supporting",
        "contradicting"
      ],
      "type": "object"
    },
    "ConflictSideDto": {
      "properties": {
        "citation_id": {
          "description": "Id of the citation taking this side",
          "example": "cit_3",
          "type": "string"
        },
        "quote": {
          "description": "The text this source actually carries, quoted rather than summarised, so a reader can check the disagreement themselves",
          "example": "The review concluded the figure was 3.1 billion.",
          "type": "string"
        },
        "source": {
          "description": "The source, by url where known and by domain otherwise",
          "example": "ministry.example.gov",
          "type": "string"
        }
      },
      "required": [
        "citation_id",
        "source",
        "quote"
      ],
      "type": "object"
    },
    "CorrectionDto": {
      "properties": {
        "actual": {
          "deprecated": true,
          "description": "Deprecated v1 alias of corrected_statement",
          "type": "string"
        },
        "citation_ids": {
          "description": "IDs of citations that support this correction",
          "example": [
            "2"
          ],
          "items": {
            "type": "string"
          },
          "type": "array"
        },
        "claimed": {
          "description": "What the user originally claimed",
          "example": "The original claimed value",
          "type": "string"
        },
        "corrected_statement": {
          "description": "A standalone replacement statement supported by the cited evidence",
          "example": "The CAA operates under the UAE Ministry of Higher Education and Scientific Research.",
          "type": "string"
        },
        "proof": {
          "items": {
            "$ref": "#/components/schemas/CorrectionProofDto"
          },
          "type": "array"
        }
      },
      "required": [
        "claimed",
        "corrected_statement",
        "citation_ids",
        "proof"
      ],
      "type": "object"
    },
    "CorrectionProofDto": {
      "properties": {
        "citation_id": {
          "example": "caa-mohesr-2025",
          "type": "string"
        },
        "quote": {
          "description": "Exact passage copied from the cited source excerpt",
          "type": "string"
        }
      },
      "required": [
        "citation_id",
        "quote"
      ],
      "type": "object"
    },
    "StanceBreakdownDto": {
      "properties": {
        "contradicts": {
          "description": "Number of citations that contradict the claim",
          "example": 0,
          "type": "number"
        },
        "inconclusive": {
          "description": "Number of citations that looked at the claim and could not tell. Distinct from neutral, which is a source that took no side.",
          "example": 1,
          "type": "number"
        },
        "irrelevant": {
          "description": "Number of citations judged off-topic. Excluded from every verdict denominator.",
          "example": 0,
          "type": "number"
        },
        "neutral": {
          "description": "Number of citations that took no side. This counts the neutral stance only. It previously also absorbed inconclusive and unscored citations, which are now reported in their own fields below.",
          "example": 1,
          "type": "number"
        },
        "partially_supports": {
          "description": "Number of citations that partially support the claim",
          "example": 1,
          "type": "number"
        },
        "supports": {
          "description": "Number of citations that fully support the claim",
          "example": 3,
          "type": "number"
        },
        "unknown": {
          "description": "Number of citations with no stance recorded. Never treated as agreement or as neutral: these were not scored, not scored as undecided.",
          "example": 0,
          "type": "number"
        }
      },
      "required": [
        "supports",
        "partially_supports",
        "contradicts",
        "neutral"
      ],
      "type": "object"
    },
    "KeyFindingDto": {
      "properties": {
        "citation_ids": {
          "description": "IDs of citations that support this finding",
          "example": [
            "1",
            "3",
            "4"
          ],
          "items": {
            "type": "string"
          },
          "type": "array"
        },
        "confidence": {
          "description": "Legacy model finding score (0-100); not calibrated truth confidence",
          "example": 92,
          "type": "number"
        },
        "confidence_available": {
          "description": "True only when calibrated confidence is available",
          "type": "boolean"
        },
        "confidence_basis": {
          "enum": [
            "unknown",
            "heuristic",
            "calibrated"
          ],
          "type": "string"
        },
        "finding": {
          "description": "A key fact extracted from the citations",
          "example": "The event occurred on the stated date according to official records",
          "type": "string"
        }
      },
      "required": [
        "finding",
        "citation_ids",
        "confidence"
      ],
      "type": "object"
    },
    "SearchMetadataDto": {
      "properties": {
        "analysis_model": {
          "description": "AI model used for analysis",
          "example": "claude-3-5-sonnet-v2@20241022",
          "type": "string"
        },
        "processing_time_ms": {
          "description": "Total processing time in milliseconds",
          "example": 2340,
          "type": "number"
        },
        "relevant_sources_found": {
          "description": "Number of relevant sources found and included",
          "example": 5,
          "type": "number"
        },
        "total_sources_searched": {
          "description": "Total number of sources searched",
          "example": 12,
          "type": "number"
        }
      },
      "required": [
        "total_sources_searched",
        "relevant_sources_found",
        "processing_time_ms",
        "analysis_model"
      ],
      "type": "object"
    },
    "BillingUsageDto": {
      "properties": {
        "credits": {
          "description": "Credits actually deducted; null when a priced operation was not metered. Zero denotes a genuinely free operation.",
          "nullable": true,
          "type": "number"
        }
      },
      "required": [
        "credits"
      ],
      "type": "object"
    }
  }
}
```
