API Reference
Complete reference for the Helix Fact Checking API.
Base URL
https://api.feeds.onhelix.ai
Authentication
All requests require API key authentication using the Bearer token scheme:
Authorization: Bearer YOUR_API_KEY
See the Authentication Guide for details on obtaining and using API keys.
Create Fact-Check
Submit text for fact-checking with optional source URLs for verification.
POST /fact-check
Request
Headers:
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
Body:
{
"text": "The Moon landing occurred in 1969. Neil Armstrong was the first person to walk on the Moon.",
"sourceUrls": [
"https://www.nasa.gov/mission_pages/apollo/missions/apollo11.html",
"https://en.wikipedia.org/wiki/Apollo_11"
]
}
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
text | string | Yes | Text content to fact-check (minimum 1 character) |
sourceUrls | string[] | No | URLs to use for verification (max 100) |
Response
Status: 201 Created
{
"success": true,
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"text": "The Moon landing occurred in 1969...",
"sourceUrls": [
"https://www.nasa.gov/mission_pages/apollo/missions/apollo11.html",
"https://en.wikipedia.org/wiki/Apollo_11"
],
"status": "pending",
"finalDetermination": null,
"finalConfidence": null,
"processingTimeMs": null,
"retryCount": 0,
"error": null,
"createdAt": "2024-01-15T10:30:00.000Z",
"updatedAt": "2024-01-15T10:30:00.000Z",
"completedAt": null,
"aggregatedStats": null,
"metadata": null
}
}
Response Fields:
| Field | Type | Description |
|---|---|---|
id | string (UUID) | Unique fact-check identifier |
text | string | Original text that was submitted |
sourceUrls | string[] | Provided source URLs |
status | string | Current status: pending, processing, completed, failed |
finalDetermination | string|null | Overall assessment when complete (see below) |
finalConfidence | number|null | Confidence in determination (0.0-1.0) |
processingTimeMs | number|null | Processing time in milliseconds |
retryCount | number | Number of retry attempts |
error | string|null | Error message if failed |
createdAt | string (ISO 8601) | Creation timestamp |
updatedAt | string (ISO 8601) | Last update timestamp |
completedAt | string|null (ISO 8601) | Completion timestamp |
aggregatedStats | object|null | Statistics summary (see below) |
metadata | object|null | Additional metadata |
Final Determination Values:
mostly_accurate- Most claims verified or supported (≥70%)mostly_inaccurate- Most claims disputed (≥50%)mixed_results- Mix of supporting and contradicting evidenceinsufficient_evidence- Not enough evidence to determine
Aggregated Statistics (when completed):
{
"totalClaims": 5,
"verifiedClaims": 4,
"supportedClaims": 3,
"disputedClaims": 1,
"unverifiedClaims": 1,
"mixedClaims": 0,
"averageConfidence": 0.85,
"totalSources": 3,
"successfulSources": 3,
"restrictedSources": 0,
"failedSources": 0
}
Errors
400 Bad Request:
{
"success": false,
"error": "Text is required"
}
{
"success": false,
"error": "Maximum 100 source URLs allowed"
}
401 Unauthorized:
{
"success": false,
"error": "Invalid or missing API key"
}
Example
curl -X POST https://api.feeds.onhelix.ai/fact-check \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"text": "The Eiffel Tower was completed in 1889 and stands 324 meters tall.",
"sourceUrls": [
"https://www.toureiffel.paris/en/the-monument"
]
}'
List Fact-Checks
Retrieve all fact-checks with pagination and filtering.
GET /fact-check
Request
Headers:
Authorization: Bearer YOUR_API_KEY
Query Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
page | number | No | Page number (min: 1, default: 1) |
pageSize | number | No | Items per page (min: 1, max: 100, default: 20) |
status | string | No | Filter by status: pending, processing, completed, failed |
startDate | string (ISO 8601) | No | Filter by creation date (from) |
endDate | string (ISO 8601) | No | Filter by creation date (to) |
Response
Status: 200 OK
{
"success": true,
"data": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"text": "The Eiffel Tower was completed in 1889...",
"status": "completed",
"finalDetermination": "mostly_accurate",
"finalConfidence": 0.92,
"createdAt": "2024-01-15T10:30:00.000Z",
"completedAt": "2024-01-15T10:30:45.000Z"
}
],
"pagination": {
"page": 1,
"pageSize": 20,
"total": 45,
"totalPages": 3
}
}
Pagination Fields:
| Field | Type | Description |
|---|---|---|
page | number | Current page number |
pageSize | number | Items per page |
total | number | Total number of fact-checks |
totalPages | number | Total number of pages |
Example
# List all fact-checks
curl "https://api.feeds.onhelix.ai/fact-check" \
-H "Authorization: Bearer YOUR_API_KEY"
# Filter by status
curl "https://api.feeds.onhelix.ai/fact-check?status=completed&pageSize=50" \
-H "Authorization: Bearer YOUR_API_KEY"
# Filter by date range
curl "https://api.feeds.onhelix.ai/fact-check?startDate=2024-01-01T00:00:00Z&endDate=2024-01-31T23:59:59Z" \
-H "Authorization: Bearer YOUR_API_KEY"
Get Fact-Check
Retrieve details for a specific fact-check.
GET /fact-check/{factCheckId}
Request
Headers:
Authorization: Bearer YOUR_API_KEY
Path Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
factCheckId | string (UUID) | Yes | Unique fact-check identifier |
Response
Status: 200 OK
{
"success": true,
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"text": "The Eiffel Tower was completed in 1889...",
"sourceUrls": ["https://www.toureiffel.paris/en/the-monument"],
"status": "completed",
"finalDetermination": "mostly_accurate",
"finalConfidence": 0.92,
"processingTimeMs": 45230,
"retryCount": 0,
"error": null,
"createdAt": "2024-01-15T10:30:00.000Z",
"updatedAt": "2024-01-15T10:30:45.230Z",
"completedAt": "2024-01-15T10:30:45.230Z",
"aggregatedStats": {
"totalClaims": 3,
"verifiedClaims": 3,
"supportedClaims": 3,
"disputedClaims": 0,
"unverifiedClaims": 0,
"mixedClaims": 0,
"averageConfidence": 0.92,
"totalSources": 1,
"successfulSources": 1,
"restrictedSources": 0,
"failedSources": 0
},
"metadata": null
}
}
Errors
404 Not Found:
{
"success": false,
"error": "Fact-check not found"
}
Example
curl "https://api.feeds.onhelix.ai/fact-check/550e8400-e29b-41d4-a716-446655440000" \
-H "Authorization: Bearer YOUR_API_KEY"
Retry Fact-Check
Retry a failed fact-check request.
POST /fact-check/{factCheckId}/retry
Request
Headers:
Authorization: Bearer YOUR_API_KEY
Path Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
factCheckId | string (UUID) | Yes | Unique fact-check identifier |
Response
Status: 200 OK
{
"success": true,
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"status": "pending",
"retryCount": 1,
"error": null,
"updatedAt": "2024-01-15T11:00:00.000Z"
}
}
Response Fields:
| Field | Type | Description |
|---|---|---|
id | string (UUID) | Fact-check identifier |
status | string | Reset to pending |
retryCount | number | Incremented retry count |
error | null | Error cleared on retry |
updatedAt | string (ISO 8601) | Updated timestamp |
When to Retry
- Transient network or service errors
- Temporary source inaccessibility
Note: The API does not enforce a maximum retry limit. Implement your own retry logic with exponential backoff.
Errors
400 Bad Request:
{
"success": false,
"error": "Cannot retry fact-check that is not in failed status"
}
404 Not Found:
{
"success": false,
"error": "Fact-check not found"
}
Example
curl -X POST "https://api.feeds.onhelix.ai/fact-check/550e8400-e29b-41d4-a716-446655440000/retry" \
-H "Authorization: Bearer YOUR_API_KEY"
Get Claims
Retrieve extracted claims with optional evidence.
GET /fact-check/{factCheckId}/claims
Request
Headers:
Authorization: Bearer YOUR_API_KEY
Path Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
factCheckId | string (UUID) | Yes | Unique fact-check identifier |
Query Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
includeEvidence | boolean | No | Include evidence for each claim (default: false) |
Response
Status: 200 OK
Without Evidence:
{
"success": true,
"data": [
{
"id": "claim_1",
"claimText": "The Eiffel Tower was completed in 1889",
"claimContext": "Historical construction date",
"claimType": "factual",
"confidence": 0.95,
"textFragment": null,
"verificationResult": "verified",
"evidenceConfidence": 0.98,
"evidenceBalance": 1.0,
"createdAt": "2024-01-15T10:30:10.000Z",
"updatedAt": "2024-01-15T10:30:40.000Z"
}
]
}
With Evidence (?includeEvidence=true):
{
"success": true,
"data": [
{
"id": "claim_1",
"claimText": "The Eiffel Tower was completed in 1889",
"claimContext": "Historical construction date",
"claimType": "factual",
"confidence": 0.95,
"textFragment": null,
"verificationResult": "verified",
"evidenceConfidence": 0.98,
"evidenceBalance": 1.0,
"createdAt": "2024-01-15T10:30:10.000Z",
"updatedAt": "2024-01-15T10:30:40.000Z",
"evidence": [
{
"id": "evidence_1",
"claimId": "claim_1",
"sourceDocumentId": "source_1",
"sourceUrl": "https://www.toureiffel.paris/en/the-monument",
"evidenceText": "The Eiffel Tower was built between 1887 and 1889 as the entrance arch for the 1889 World's Fair.",
"evidenceContext": "Official tower history",
"textFragment": null,
"extractedText": null,
"evidenceType": "supporting",
"relevanceScore": 0.98,
"confidenceScore": 0.99,
"explanation": "Official source confirms the 1889 completion date",
"metadata": null,
"createdAt": "2024-01-15T10:30:35.000Z",
"updatedAt": "2024-01-15T10:30:35.000Z"
}
]
}
]
}
Claim Fields:
| Field | Type | Description |
|---|---|---|
id | string (UUID) | Unique claim identifier |
claimText | string | The factual claim statement |
claimContext | string|null | Additional context for the claim |
claimType | string | Type of claim (factual, statistical, etc.) |
confidence | number | Extraction confidence (0.0-1.0) |
textFragment | string|null | W3C text fragment for source linking |
verificationResult | string | verified, disputed, unverified, mixed |
evidenceConfidence | number|null | Confidence in verification (0.0-1.0) |
evidenceBalance | number | Balance of support/contradiction (-1.0 to 1.0) |
createdAt | string (ISO 8601) | Extraction timestamp |
updatedAt | string (ISO 8601) | Last update timestamp |
Verification Results:
| Result | Description | Evidence Balance |
|---|---|---|
verified | Claim supported by strong evidence | Positive (0.6 to 1.0) |
disputed | Claim contradicted by evidence | Negative (-1.0 to -0.6) |
unverified | Insufficient evidence found | Near zero (-0.2 to 0.2) |
mixed | Both supporting and contradicting evidence | Mixed (-0.6 to 0.6, with evidence) |
Evidence Fields (when includeEvidence=true):
| Field | Type | Description |
|---|---|---|
id | string (UUID) | Unique evidence identifier |
claimId | string (UUID) | Related claim identifier |
sourceDocumentId | string (UUID) | Source document identifier |
sourceUrl | string | Source URL where evidence was found |
evidenceText | string | Relevant text passage from source |
evidenceContext | string|null | Surrounding context for evidence |
textFragment | string|null | W3C text fragment for precise linking |
extractedText | string|null | Actual extracted text from page |
evidenceType | string | supporting, contradicting, neutral |
relevanceScore | number | Relevance to claim (0.0-1.0) |
confidenceScore | number | Confidence in this evidence (0.0-1.0) |
explanation | string|null | Why this evidence matters |
metadata | object|null | Additional evidence metadata |
createdAt | string (ISO 8601) | Discovery timestamp |
updatedAt | string (ISO 8601) | Last update timestamp |
Evidence Types:
| Type | Description | Impact |
|---|---|---|
supporting | Evidence supports the claim | Increases verification confidence |
contradicting | Evidence contradicts the claim | Leads to disputed result |
neutral | Evidence neither clearly supports nor contradicts | Minimal impact on verification |
Example
# Get claims only
curl "https://api.feeds.onhelix.ai/fact-check/550e8400-e29b-41d4-a716-446655440000/claims" \
-H "Authorization: Bearer YOUR_API_KEY"
# Get claims with evidence
curl "https://api.feeds.onhelix.ai/fact-check/550e8400-e29b-41d4-a716-446655440000/claims?includeEvidence=true" \
-H "Authorization: Bearer YOUR_API_KEY"
Get Evidence
Retrieve all evidence for a fact-check across all claims.
GET /fact-check/{factCheckId}/evidence
Request
Headers:
Authorization: Bearer YOUR_API_KEY
Path Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
factCheckId | string (UUID) | Yes | Unique fact-check identifier |
Response
Status: 200 OK
{
"success": true,
"data": [
{
"id": "evidence_1",
"claimId": "claim_1",
"sourceDocumentId": "source_1",
"sourceUrl": "https://www.toureiffel.paris/en/the-monument",
"evidenceText": "The Eiffel Tower was built between 1887 and 1889...",
"evidenceContext": "Official tower history",
"textFragment": null,
"extractedText": null,
"evidenceType": "supporting",
"relevanceScore": 0.98,
"confidenceScore": 0.99,
"explanation": "Official source confirms the 1889 completion date",
"metadata": null,
"createdAt": "2024-01-15T10:30:35.000Z",
"updatedAt": "2024-01-15T10:30:35.000Z"
}
]
}
See Get Claims for field descriptions.
Example
curl "https://api.feeds.onhelix.ai/fact-check/550e8400-e29b-41d4-a716-446655440000/evidence" \
-H "Authorization: Bearer YOUR_API_KEY"
Get Source Documents
Retrieve source documents used for verification.
GET /fact-check/{factCheckId}/sources
Request
Headers:
Authorization: Bearer YOUR_API_KEY
Path Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
factCheckId | string (UUID) | Yes | Unique fact-check identifier |
Response
Status: 200 OK
{
"success": true,
"data": [
{
"id": "source_1",
"factCheckId": "550e8400-e29b-41d4-a716-446655440000",
"sourceUrl": "https://www.toureiffel.paris/en/the-monument",
"sitePageVersionId": "550e8400-e29b-41d4-a716-446655440005",
"metadata": {
"hasAccessRestriction": false,
"source": "crawl",
"crawledAt": "2024-01-15T10:30:20.000Z",
"error": null,
"failedAt": null
},
"createdAt": "2024-01-15T10:30:15.000Z",
"updatedAt": "2024-01-15T10:30:20.000Z"
}
]
}
Source Document Fields:
| Field | Type | Description |
|---|---|---|
id | string (UUID) | Unique document identifier |
factCheckId | string (UUID) | Parent fact-check identifier |
sourceUrl | string | Document URL |
sitePageVersionId | string|null (UUID) | Internal page version reference |
metadata | object|null | Crawl status and details (see below) |
createdAt | string (ISO 8601) | Creation timestamp |
updatedAt | string (ISO 8601) | Last update timestamp |
Source Metadata:
| Field | Type | Description |
|---|---|---|
hasAccessRestriction | boolean | Whether source is behind paywall/login |
source | string | Source type (crawl, provided, etc.) |
crawledAt | string|null (ISO 8601) | When source was crawled |
error | string|null | Error message if crawl failed |
failedAt | string|null (ISO 8601) | When crawl failed |
Access Restrictions: Sources flagged with hasAccessRestriction: true are behind paywalls, require login, or have other access limitations. The system handles these gracefully and uses available sources for verification.
Example
curl "https://api.feeds.onhelix.ai/fact-check/550e8400-e29b-41d4-a716-446655440000/sources" \
-H "Authorization: Bearer YOUR_API_KEY"
Error Responses
All endpoints may return these standard errors:
400 Bad Request
Invalid request parameters or body:
{
"success": false,
"error": "Text is required"
}
{
"success": false,
"error": "Maximum 100 source URLs allowed"
}
401 Unauthorized
Missing or invalid API key:
{
"success": false,
"error": "Invalid or missing API key"
}
404 Not Found
Resource not found:
{
"success": false,
"error": "Fact-check not found"
}
500 Internal Server Error
Server error:
{
"success": false,
"error": "An internal error occurred. Please try again later."
}
Best Practices
Polling for Completion
Use exponential backoff when polling for fact-check completion:
const API_KEY = process.env.HELIX_API_KEY;
const BASE_URL = 'https://api.feeds.onhelix.ai';
async function waitForCompletion(factCheckId, maxAttempts = 60) {
for (let i = 0; i < maxAttempts; i++) {
const response = await fetch(`${BASE_URL}/fact-check/${factCheckId}`, {
headers: { Authorization: `Bearer ${API_KEY}` },
});
if (!response.ok) {
throw new Error(`HTTP error ${response.status}`);
}
const result = await response.json();
const status = result.data.status;
if (status === 'completed' || status === 'failed') {
return result.data;
}
// Exponential backoff: 2s, 4s, 8s, then 10s max
const waitTime = Math.min(2000 * Math.pow(2, i), 10000);
await new Promise((resolve) => setTimeout(resolve, waitTime));
}
throw new Error('Fact-check timed out');
}
// Usage
try {
const factCheck = await waitForCompletion(
'550e8400-e29b-41d4-a716-446655440000'
);
if (factCheck.status === 'completed') {
console.log(`Determination: ${factCheck.finalDetermination}`);
console.log(`Confidence: ${factCheck.finalConfidence}`);
} else {
console.error(`Failed: ${factCheck.error}`);
}
} catch (error) {
console.error('Error:', error.message);
}
Using Webhooks (Recommended)
Set up webhooks to receive notifications when fact-checks complete instead of polling:
// Submit fact-check
const response = await fetch(`${BASE_URL}/fact-check`, {
method: 'POST',
headers: {
Authorization: `Bearer ${API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
text: 'Your text here...',
sourceUrls: ['https://example.com'],
}),
});
const { data } = await response.json();
console.log(`Fact-check submitted: ${data.id}`);
// Your webhook endpoint will receive notification when complete
See the Webhooks documentation for setup details.
Error Handling
Implement comprehensive error handling:
import requests
import time
from typing import Optional
API_KEY = os.getenv('HELIX_API_KEY')
BASE_URL = 'https://api.feeds.onhelix.ai'
def create_fact_check_with_retry(
text: str,
source_urls: list[str],
max_retries: int = 3
) -> Optional[dict]:
"""
Create fact-check with automatic retry on transient errors
"""
for attempt in range(max_retries):
try:
response = requests.post(
f'{BASE_URL}/fact-check',
json={
'text': text,
'sourceUrls': source_urls
},
headers={'Authorization': f'Bearer {API_KEY}'}
)
response.raise_for_status()
return response.json()['data']
except requests.exceptions.RequestException as e:
if attempt == max_retries - 1:
raise
# Exponential backoff
time.sleep(2 ** attempt)
return None
# Usage
try:
fact_check = create_fact_check_with_retry(
text="The Earth orbits the Sun.",
source_urls=["https://science.nasa.gov"]
)
print(f"Created fact-check: {fact_check['id']}")
except requests.exceptions.HTTPError as e:
print(f"HTTP error: {e.response.status_code}")
print(f"Error: {e.response.json()['error']}")
except Exception as e:
print(f"Unexpected error: {e}")
Handling Failed Fact-Checks
Implement automatic retry with intelligent backoff:
async function createFactCheckWithAutoRetry(text, sourceUrls, maxRetries = 3) {
let factCheckId = null;
// Create initial fact-check
const createResponse = await fetch(`${BASE_URL}/fact-check`, {
method: 'POST',
headers: {
Authorization: `Bearer ${API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ text, sourceUrls }),
});
const { data } = await createResponse.json();
factCheckId = data.id;
// Wait for completion
const result = await waitForCompletion(factCheckId);
// Retry if failed
if (result.status === 'failed' && maxRetries > 0) {
console.log(`Fact-check failed: ${result.error}`);
console.log(`Retrying (${maxRetries} attempts remaining)...`);
// Wait before retrying
await new Promise((resolve) => setTimeout(resolve, 5000));
// Retry the fact-check
const retryResponse = await fetch(
`${BASE_URL}/fact-check/${factCheckId}/retry`,
{
method: 'POST',
headers: { Authorization: `Bearer ${API_KEY}` },
}
);
if (retryResponse.ok) {
// Recursively wait and retry
return waitForCompletion(factCheckId);
}
}
return result;
}
Optimizing Source Selection
Provide high-quality, accessible sources for best results:
def create_fact_check_with_quality_sources(text: str) -> dict:
"""
Create fact-check with curated quality sources
"""
# Prioritize authoritative, accessible sources
quality_sources = [
'https://www.reuters.com',
'https://apnews.com',
'https://www.bbc.com/news',
'https://en.wikipedia.org'
]
# Avoid sources that commonly have restrictions
avoid_patterns = [
'paywall',
'subscription-required',
'members-only'
]
response = requests.post(
f'{BASE_URL}/fact-check',
json={
'text': text,
'sourceUrls': quality_sources[:10] # Limit to 10 for faster processing
},
headers={'Authorization': f'Bearer {API_KEY}'}
)
return response.json()['data']
Monitoring Confidence Scores
Implement thresholds for manual review:
async function reviewFactCheckIfNeeded(factCheckId, minConfidence = 0.7) {
const response = await fetch(`${BASE_URL}/fact-check/${factCheckId}`, {
headers: { Authorization: `Bearer ${API_KEY}` },
});
const { data } = await response.json();
if (data.finalConfidence < minConfidence) {
console.log('⚠️ Low confidence - manual review recommended');
// Get detailed claims for review
const claimsResponse = await fetch(
`${BASE_URL}/fact-check/${factCheckId}/claims?includeEvidence=true`,
{
headers: { Authorization: `Bearer ${API_KEY}` },
}
);
const { data: claims } = await claimsResponse.json();
// Identify problematic claims
const lowConfidenceClaims = claims.filter(
(claim) => claim.evidenceConfidence < minConfidence
);
console.log(`${lowConfidenceClaims.length} claims need review`);
return {
needsReview: true,
factCheck: data,
problematicClaims: lowConfidenceClaims,
};
}
return {
needsReview: false,
factCheck: data,
};
}
Next Steps
- Quickstart Guide: Create your first fact-check in 5 minutes
- Overview: Understand how the fact-checking system works
- Webhooks: Set up webhook notifications
- Authentication: API key best practices