Skip to main content

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:

ParameterTypeRequiredDescription
textstringYesText content to fact-check (minimum 1 character)
sourceUrlsstring[]NoURLs 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:

FieldTypeDescription
idstring (UUID)Unique fact-check identifier
textstringOriginal text that was submitted
sourceUrlsstring[]Provided source URLs
statusstringCurrent status: pending, processing, completed, failed
finalDeterminationstring|nullOverall assessment when complete (see below)
finalConfidencenumber|nullConfidence in determination (0.0-1.0)
processingTimeMsnumber|nullProcessing time in milliseconds
retryCountnumberNumber of retry attempts
errorstring|nullError message if failed
createdAtstring (ISO 8601)Creation timestamp
updatedAtstring (ISO 8601)Last update timestamp
completedAtstring|null (ISO 8601)Completion timestamp
aggregatedStatsobject|nullStatistics summary (see below)
metadataobject|nullAdditional 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 evidence
  • insufficient_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:

ParameterTypeRequiredDescription
pagenumberNoPage number (min: 1, default: 1)
pageSizenumberNoItems per page (min: 1, max: 100, default: 20)
statusstringNoFilter by status: pending, processing, completed, failed
startDatestring (ISO 8601)NoFilter by creation date (from)
endDatestring (ISO 8601)NoFilter 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:

FieldTypeDescription
pagenumberCurrent page number
pageSizenumberItems per page
totalnumberTotal number of fact-checks
totalPagesnumberTotal 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:

ParameterTypeRequiredDescription
factCheckIdstring (UUID)YesUnique 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:

ParameterTypeRequiredDescription
factCheckIdstring (UUID)YesUnique 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:

FieldTypeDescription
idstring (UUID)Fact-check identifier
statusstringReset to pending
retryCountnumberIncremented retry count
errornullError cleared on retry
updatedAtstring (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:

ParameterTypeRequiredDescription
factCheckIdstring (UUID)YesUnique fact-check identifier

Query Parameters:

ParameterTypeRequiredDescription
includeEvidencebooleanNoInclude 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:

FieldTypeDescription
idstring (UUID)Unique claim identifier
claimTextstringThe factual claim statement
claimContextstring|nullAdditional context for the claim
claimTypestringType of claim (factual, statistical, etc.)
confidencenumberExtraction confidence (0.0-1.0)
textFragmentstring|nullW3C text fragment for source linking
verificationResultstringverified, disputed, unverified, mixed
evidenceConfidencenumber|nullConfidence in verification (0.0-1.0)
evidenceBalancenumberBalance of support/contradiction (-1.0 to 1.0)
createdAtstring (ISO 8601)Extraction timestamp
updatedAtstring (ISO 8601)Last update timestamp

Verification Results:

ResultDescriptionEvidence Balance
verifiedClaim supported by strong evidencePositive (0.6 to 1.0)
disputedClaim contradicted by evidenceNegative (-1.0 to -0.6)
unverifiedInsufficient evidence foundNear zero (-0.2 to 0.2)
mixedBoth supporting and contradicting evidenceMixed (-0.6 to 0.6, with evidence)

Evidence Fields (when includeEvidence=true):

FieldTypeDescription
idstring (UUID)Unique evidence identifier
claimIdstring (UUID)Related claim identifier
sourceDocumentIdstring (UUID)Source document identifier
sourceUrlstringSource URL where evidence was found
evidenceTextstringRelevant text passage from source
evidenceContextstring|nullSurrounding context for evidence
textFragmentstring|nullW3C text fragment for precise linking
extractedTextstring|nullActual extracted text from page
evidenceTypestringsupporting, contradicting, neutral
relevanceScorenumberRelevance to claim (0.0-1.0)
confidenceScorenumberConfidence in this evidence (0.0-1.0)
explanationstring|nullWhy this evidence matters
metadataobject|nullAdditional evidence metadata
createdAtstring (ISO 8601)Discovery timestamp
updatedAtstring (ISO 8601)Last update timestamp

Evidence Types:

TypeDescriptionImpact
supportingEvidence supports the claimIncreases verification confidence
contradictingEvidence contradicts the claimLeads to disputed result
neutralEvidence neither clearly supports nor contradictsMinimal 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:

ParameterTypeRequiredDescription
factCheckIdstring (UUID)YesUnique 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:

ParameterTypeRequiredDescription
factCheckIdstring (UUID)YesUnique 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:

FieldTypeDescription
idstring (UUID)Unique document identifier
factCheckIdstring (UUID)Parent fact-check identifier
sourceUrlstringDocument URL
sitePageVersionIdstring|null (UUID)Internal page version reference
metadataobject|nullCrawl status and details (see below)
createdAtstring (ISO 8601)Creation timestamp
updatedAtstring (ISO 8601)Last update timestamp

Source Metadata:

FieldTypeDescription
hasAccessRestrictionbooleanWhether source is behind paywall/login
sourcestringSource type (crawl, provided, etc.)
crawledAtstring|null (ISO 8601)When source was crawled
errorstring|nullError message if crawl failed
failedAtstring|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);
}

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