Fact Check
Check a factual claim against recent news with /v1/fact-check. Send a statement, an article's text or the id of an article in APITube.
For each claim, the response includes one of 8 verdicts, a confidence score, a short explanation and articles that support or challenge it.
Sign up at APITube to get your API key. Include it with every API request.
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-checkGET and POST return the same results. Send parameters in the URL with GET or as JSON in the request body with 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 archive, 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. Values below 1 are raised to 1; values above 5 are reduced to 5. Default: 5. |
evidence_per_claim | integer | No | Maximum number of evidence articles to retrieve per claim. Values below 1 are raised to 1; values above 20 are reduced to 20. 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 requires a paid plan. This endpoint allows 10 requests per minute, in addition to your account's overall rate limit.
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 archive.
- 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 archive 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 factual, verifiable claims that were checked. |
summary.verdict_breakdown | object | Count of claims per verdict. |
claims[].verdict | string | One of the 8 verdicts (see scale above). |
claims[].confidence | number | Confidence score for the verdict, from 0 to 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-check
POST — 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-check
Using 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 fact-check service did not respond. Wait a moment and retry.
{
"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