Skip to content

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-check

Both 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

ParameterTypeRequiredDescription
idintegerOne of*An APITube article id. The article is loaded from the corpus, and its claims are extracted and verified.
textstringOne of*Raw article text (title + body), 100–10000 characters. Claims are extracted automatically.
claimstringOne of*A single factual statement to verify directly (5–500 characters).
max_claimsintegerNoMaximum number of claims to extract and verify. Capped server-side (default 5).
evidence_per_claimintegerNoMaximum number of evidence articles to retrieve per claim. Capped server-side (default 5).
api_keystringYes**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

  1. Claims — for text/id the claims are extracted automatically; for claim your statement is used directly.
  2. Evidence — for each claim, matching articles are retrieved from the news corpus.
  3. 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

json
{
  "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

FieldTypeDescription
statusstringAlways ok on success.
request_idstringUnique identifier for the request.
input.typestringWhich input was used: id, text, or claim.
input.languagestringDetected language of the input.
summary.overall_verdictstringAggregated verdict across all checked claims.
summary.overall_confidencenumberAverage confidence across checked claims (0..1).
summary.claims_totalintegerTotal number of claims returned.
summary.claims_checkedintegerNumber of check-worthy claims that were verified.
summary.verdict_breakdownobjectCount of claims per verdict.
claims[].verdictstringOne of the 8 verdicts (see scale above).
claims[].confidencenumberCalibrated confidence in the verdict (0..1).
claims[].explanationstringWhy this verdict was assigned.
claims[].as_ofstringDate the verdict is valid as of (YYYY-MM-DD).
claims[].checkworthybooleanWhether the claim is an objective, verifiable statement.
claims[].evidence[]arraySupporting/refuting articles with stance (supports/refutes/neutral), relevance (0..1) and source_authority (higher = more authoritative).

Request Examples

GET — verify a single claim

bash
curl "https://api.apitube.io/v1/fact-check?claim=OpenAI released GPT-5 in 2024&api_key=YOUR_API_KEY"
python
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())
javascript
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());
php
$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);
go
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)
}
java
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());
    }
}
text
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

bash
# 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>" }'
python
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())
javascript
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());
php
$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);
go
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)
}
java
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());
    }
}
text
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

shell
curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://api.apitube.io/v1/fact-check?claim=The Eiffel Tower is in Paris"

Response Example

json
{
  "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

json
{
  "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

json
{
  "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)

json
{
  "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

json
{
  "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

json
{
  "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

json
{
  "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

json
{
  "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.

json
{
  "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.

json
{
  "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