Fact Check
The /v1/fact-check endpoint verifies factual claims against APITube's live news corpus. Instead of relying on a language model's memory, it retrieves real, recent articles that match each claim and grounds the verdict in them (retrieval-augmented fact-checking). You can check a single statement, a full article's text, or any article already in the corpus by its id.
For every claim it returns a verdict on an 8-level scale, a calibrated confidence score, a short explanation, and the supporting/refuting evidence articles.
To use the API, you'll require an API key. You can obtain an API key by signing up for an account on the APITube website.
Fact Check is a paid feature — it is not available on the Free plan. Each request costs 5 points.
Endpoint
GET /v1/fact-check
POST /v1/fact-checkBoth methods are equivalent: parameters can be passed as query parameters (GET) or as a JSON body (POST). Provide one of id, text, or claim (priority: id > text > claim).
Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | integer | One of* | An APITube article id. The article is loaded from the corpus, and its claims are extracted and verified. |
text | string | One of* | Raw article text (title + body), 100–10000 characters. Claims are extracted automatically. |
claim | string | One of* | A single factual statement to verify directly (5–500 characters). |
max_claims | integer | No | Maximum number of claims to extract and verify. Capped server-side (default 5). |
evidence_per_claim | integer | No | Maximum number of evidence articles to retrieve per claim. Capped server-side (default 5). |
api_key | string | Yes** | Your API key. Can also be provided via headers. |
* Provide exactly one of id, text, or claim. ** Required if not provided in headers.
Each request costs 5 points and is not available on the Free plan. This endpoint has a dedicated rate limit of 10 requests per minute (separate from, and stricter than, the global API rate limit), because every request runs language-model inference.
How it works
- Claims — for
text/idthe claims are extracted automatically; forclaimyour statement is used directly. - Evidence — for each claim, matching articles are retrieved from the news corpus.
- Verdict — each claim is assessed strictly against its evidence and assigned one of the verdicts below.
Verdict scale
true · mostly_true · mixed · misleading · mostly_false · false · unverified · outdated
unverified— not enough evidence in the corpus to confirm or refute.outdated— the claim was once true but is contradicted by more recent evidence.
Response Format
{
"status": "ok",
"request_id": "string",
"input": { "type": "claim", "language": "en" },
"summary": {
"overall_verdict": "false",
"overall_confidence": 0.91,
"claims_total": 1,
"claims_checked": 1,
"verdict_breakdown": { "false": 1 }
},
"claims": [
{
"claim": "string",
"normalized_claim": "string",
"checkworthy": true,
"verdict": "false",
"confidence": 0.91,
"as_of": "2026-06-15",
"explanation": "string",
"evidence": [
{
"article_id": 0,
"title": "string",
"url": "string",
"source": "string",
"source_authority": 0,
"published_at": "string",
"snippet": "string",
"stance": "refutes",
"relevance": 0.88
}
]
}
]
}Response Fields
| Field | Type | Description |
|---|---|---|
status | string | Always ok on success. |
request_id | string | Unique identifier for the request. |
input.type | string | Which input was used: id, text, or claim. |
input.language | string | Detected language of the input. |
summary.overall_verdict | string | Aggregated verdict across all checked claims. |
summary.overall_confidence | number | Average confidence across checked claims (0..1). |
summary.claims_total | integer | Total number of claims returned. |
summary.claims_checked | integer | Number of check-worthy claims that were verified. |
summary.verdict_breakdown | object | Count of claims per verdict. |
claims[].verdict | string | One of the 8 verdicts (see scale above). |
claims[].confidence | number | Calibrated confidence in the verdict (0..1). |
claims[].explanation | string | Why this verdict was assigned. |
claims[].as_of | string | Date the verdict is valid as of (YYYY-MM-DD). |
claims[].checkworthy | boolean | Whether the claim is an objective, verifiable statement. |
claims[].evidence[] | array | Supporting/refuting articles with stance (supports/refutes/neutral), relevance (0..1) and source_authority (higher = more authoritative). |
Request Examples
GET — verify a single claim
curl "https://api.apitube.io/v1/fact-check?claim=OpenAI released GPT-5 in 2024&api_key=YOUR_API_KEY"import requests
resp = requests.get(
"https://api.apitube.io/v1/fact-check",
params={"claim": "OpenAI released GPT-5 in 2024", "api_key": "YOUR_API_KEY"},
)
print(resp.json())const params = new URLSearchParams({
claim: "OpenAI released GPT-5 in 2024",
api_key: "YOUR_API_KEY",
});
const resp = await fetch(`https://api.apitube.io/v1/fact-check?${params}`);
console.log(await resp.json());$query = http_build_query([
"claim" => "OpenAI released GPT-5 in 2024",
"api_key" => "YOUR_API_KEY",
]);
$data = json_decode(file_get_contents("https://api.apitube.io/v1/fact-check?$query"), true);
print_r($data);package main
import (
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
)
func main() {
u, _ := url.Parse("https://api.apitube.io/v1/fact-check")
q := u.Query()
q.Set("claim", "OpenAI released GPT-5 in 2024")
q.Set("api_key", "YOUR_API_KEY")
u.RawQuery = q.Encode()
resp, _ := http.Get(u.String())
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
var data map[string]any
json.Unmarshal(body, &data)
fmt.Println(data)
}import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class Example {
public static void main(String[] args) throws Exception {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.apitube.io/v1/fact-check?claim=OpenAI+released+GPT-5+in+2024&api_key=YOUR_API_KEY"))
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}Write a script in your preferred language that calls the APITube News API:
GET https://api.apitube.io/v1/fact-check?claim=OpenAI released GPT-5 in 2024
Read the API key from an environment variable (do not hardcode it), handle request
errors, and print each claim's verdict, confidence and evidence.
Docs: https://docs.apitube.io/platform/news-api/fact-checkPOST — fact-check article text or an article by id
# Verify an article already in the corpus by its id
curl -X POST "https://api.apitube.io/v1/fact-check" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "id": 123456789, "max_claims": 5 }'
# Or fact-check raw article text
curl -X POST "https://api.apitube.io/v1/fact-check" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "text": "<article title and body, 100-10000 chars>" }'import requests
resp = requests.post(
"https://api.apitube.io/v1/fact-check",
headers={"X-API-Key": "YOUR_API_KEY"},
json={"id": 123456789, "max_claims": 5},
)
print(resp.json())const resp = await fetch("https://api.apitube.io/v1/fact-check", {
method: "POST",
headers: { "X-API-Key": "YOUR_API_KEY", "Content-Type": "application/json" },
body: JSON.stringify({ id: 123456789, max_claims: 5 }),
});
console.log(await resp.json());$ch = curl_init("https://api.apitube.io/v1/fact-check");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ["X-API-Key: YOUR_API_KEY", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => json_encode([
"id" => 123456789,
"max_claims" => 5,
]),
]);
$data = json_decode(curl_exec($ch), true);
print_r($data);package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
)
func main() {
payload, _ := json.Marshal(map[string]any{
"id": 123456789,
"max_claims": 5,
})
req, _ := http.NewRequest("POST", "https://api.apitube.io/v1/fact-check", bytes.NewBuffer(payload))
req.Header.Set("X-API-Key", "YOUR_API_KEY")
req.Header.Set("Content-Type", "application/json")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
var data map[string]any
json.Unmarshal(body, &data)
fmt.Println(data)
}import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class Example {
public static void main(String[] args) throws Exception {
String payload = "{\"id\": 123456789, \"max_claims\": 5}";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.apitube.io/v1/fact-check"))
.header("X-API-Key", "YOUR_API_KEY")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}Write a script in your preferred language that calls the APITube News API:
POST https://api.apitube.io/v1/fact-check
Body (JSON):
{
"id": 123456789,
"max_claims": 5
}
Read the API key from an environment variable (do not hardcode it), handle request
errors, and print each claim's verdict, confidence and evidence.
Docs: https://docs.apitube.io/platform/news-api/fact-checkUsing Bearer token
curl -H "Authorization: Bearer YOUR_API_KEY" \
"https://api.apitube.io/v1/fact-check?claim=The Eiffel Tower is in Paris"Response Example
{
"status": "ok",
"request_id": "req_abc123def456",
"input": { "type": "claim", "language": "en" },
"summary": {
"overall_verdict": "false",
"overall_confidence": 0.91,
"claims_total": 1,
"claims_checked": 1,
"verdict_breakdown": { "false": 1 }
},
"claims": [
{
"claim": "OpenAI released GPT-5 in 2024",
"normalized_claim": "openai released gpt-5 in 2024",
"checkworthy": true,
"verdict": "false",
"confidence": 0.91,
"as_of": "2026-06-15",
"explanation": "Sources report the release of GPT-4o in 2024; a model named GPT-5 was not released that year.",
"evidence": [
{
"article_id": 884412201,
"title": "OpenAI unveils GPT-4o, its new flagship model",
"url": "https://example-news.com/openai-gpt4o",
"source": "example-news.com",
"source_authority": 92,
"published_at": "2024-05-13T17:00:00Z",
"snippet": "OpenAI on Monday announced GPT-4o...",
"stance": "refutes",
"relevance": 0.88
}
]
}
]
}Error Responses
Free plan not allowed
{
"status": "not_ok",
"request_id": "req_abc123def456",
"errors": [
{
"status": 403,
"code": "ER0706",
"message": "Fact-check is not available on the free plan. Please upgrade your subscription.",
"links": { "about": "https://docs.apitube.io/platform/news-api/http-response-codes" },
"timestamp": "2026-06-15T14:30:00Z"
}
]
}Status Code: 403
Missing input
{
"status": "not_ok",
"request_id": "req_abc123def456",
"errors": [
{
"status": 400,
"code": "ER0700",
"message": "Provide one of the parameters: id, text, or claim.",
"links": { "about": "https://docs.apitube.io/platform/news-api/http-response-codes" },
"timestamp": "2026-06-15T14:30:00Z"
}
]
}Status Code: 400
Article not found (id)
{
"status": "not_ok",
"request_id": "req_abc123def456",
"errors": [
{
"status": 404,
"code": "ER0702",
"message": "Article with the provided id was not found.",
"links": { "about": "https://docs.apitube.io/platform/news-api/http-response-codes" },
"timestamp": "2026-06-15T14:30:00Z"
}
]
}Status Code: 404
Invalid id
{
"status": "not_ok",
"request_id": "req_abc123def456",
"errors": [
{
"status": 400,
"code": "ER0704",
"message": "id must be a valid integer.",
"links": { "about": "https://docs.apitube.io/platform/news-api/http-response-codes" },
"timestamp": "2026-06-15T14:30:00Z"
}
]
}Status Code: 400
Invalid text length
{
"status": "not_ok",
"request_id": "req_abc123def456",
"errors": [
{
"status": 400,
"code": "ER0701",
"message": "text must be between 100 and 10000 characters.",
"links": { "about": "https://docs.apitube.io/platform/news-api/http-response-codes" },
"timestamp": "2026-06-15T14:30:00Z"
}
]
}Status Code: 400
Invalid claim length
{
"status": "not_ok",
"request_id": "req_abc123def456",
"errors": [
{
"status": 400,
"code": "ER0705",
"message": "claim must be between 5 and 500 characters.",
"links": { "about": "https://docs.apitube.io/platform/news-api/http-response-codes" },
"timestamp": "2026-06-15T14:30:00Z"
}
]
}Status Code: 400
No Points on Account
{
"status": "not_ok",
"request_id": "req_abc123def456",
"errors": [
{
"status": 402,
"code": "ER0176",
"message": "You have no points on your account.",
"links": { "about": "https://docs.apitube.io/platform/news-api/http-response-codes" },
"timestamp": "2026-06-15T14:30:00Z"
}
]
}Status Code: 402
Rate Limit Exceeded
Fact Check allows 10 requests per minute.
{
"status": "not_ok",
"request_id": "req_abc123def456",
"errors": [
{
"status": 429,
"code": "ER0203",
"message": "Rate limit exceeded. You can make 10 requests per minute. Try again in 60 seconds.",
"links": { "about": "https://docs.apitube.io/platform/news-api/http-response-codes" },
"timestamp": "2026-06-15T14:30:00Z"
}
]
}Status Code: 429
Service Unavailable
The upstream fact-check service did not respond. This is usually transient — retry shortly.
{
"status": "not_ok",
"request_id": "req_abc123def456",
"errors": [
{
"status": 502,
"code": "ER0703",
"message": "Fact-check service is temporarily unavailable. Please try again later.",
"links": { "about": "https://docs.apitube.io/platform/news-api/http-response-codes" },
"timestamp": "2026-06-15T14:30:00Z"
}
]
}Status Code: 502