Most censorship-research platforms force a journalist to manually query a country page, then a service page, then cross-reference probe rows by hand. The Voidly Atlas auto-fact-check service inverts that flow: a journalist or researcher types a natural-language claim ("Twitter is blocked in Iran") and gets a verdict, a confidence score, and five evidence permalinks in under a second.
The endpoint POST /v1/atlas/fact-check ships today.
Behind the scenes: a regex-based claim parser maps country names (122
aliases including "iran", "persia", "PRC", "ksa", "Türkiye") and
service names (36 aliases including the OONI test-name conventions for
service-level probes) to canonical
(country_code, domain_patterns, ooni_test_names) tuples;
the evidence table is then queried with strict suffix-matching on
domain (so "twitter.com" matches "twitter.com" and
"abc.twitter.com" but never "chatgpt.com") plus OONI's
upstream_claim LIKE "OONI tor:%" for service-level tests
plus CensoredPlanet's source_url LIKE "%domain=twitter.com%".
Verdict logic: confirmed_block requires at least
3 block-style observations across at least 2 independent
sources (OONI + CensoredPlanet, or OONI + Voidly probes, or
any combination). partial_block is anything with at least
one block observation that falls short of the confirmation threshold.
not_observed is zero block-style rows in the window — and
crucially the response flags that this is not the same as
"not blocked" because it can also mean the probe network has no recent
coverage for that (country, domain) pair. contradicted
fires when the claim asserts blocking but the evidence is unambiguously
normal/accessible, or when the claim asserts unrestricted access but
the evidence shows blocks. insufficient_data is reserved
for unparseable claims (no country recognized).
Confidence is a heuristic blend of block-row count, source diversity,
and the average block signal value. The formula caps at 0.99 and is
deliberately bounded below 1.0 — every response reminds the caller in
the honest_caveats field that parsing is not LLM-based and
that absence of evidence is not evidence of absence.
20-claim accuracy test, run end-to-end against the public
api.voidly.ai endpoint: 19/20 correct
(95%). Median latency 178ms, p95 990ms, against the
intelligence.voidly.ai upstream directly: median
7ms, p95 17ms. The 18ms median upstream measurement is the
real bound — the public-URL number absorbs Cloudflare Worker proxy
overhead and TLS termination.
The one "failure" is informative rather than a bug: the test
expected "WhatsApp is blocked in France" to return not_observed
(France being a non-blocker), but the evidence table actually contains
6 Voidly community probe rows that flag WhatsApp anomalies in France.
The verdict was partial_block with confidence 0.80 — the
service is being honest about the data, not the test's prior. The
appropriate journalist action when seeing this verdict is to click the
single source, see that all 6 rows are from one community probe in one
ASN over a short window, and conclude "this is a real anomaly worth
investigating, not country-wide blocking." That's the workflow the
endpoint is designed to enable.
Honest caveats baked into every response:
matched_country_alias,
matched_service_alias) so the caller can verify.not_observed can mean "service is accessible" or
"we have no probe coverage for this (country, domain)" — these are
fundamentally different states and the endpoint flags this
ambiguity inline.partial_block with a lower confidence
and tell the caller why.Endpoints:
POST /v1/atlas/fact-check — body
{"claim": "...", "time_range_days": N} (default 365,
max 365)GET /v1/atlas/fact-check?claim=...&days=N — same
thing for easy testing in a browser or shellGET /v1/atlas/fact-check/info — methodology,
thresholds, supported alias counts, honest-caveat listSample (curl):
curl -X POST https://api.voidly.ai/v1/atlas/fact-check \
-H "Content-Type: application/json" \
-d '{"claim":"Telegram is blocked in Iran"}'
Returns:
{
"verdict": "confirmed_block",
"confidence": 0.99,
"evidence_count": 135,
"corroboration_sources": ["censoredplanet", "ooni"],
"last_observed_at": "2026-05-20T18:00:00Z",
"top_evidence": [
"https://explorer.ooni.org/search?probe_cc=IR&test_name=telegram&...",
...
],
"signal_types": ["blocking", "dns-blocking", "http-blocking-tcp-reset"],
"avg_block_signal": 0.73,
"honest_caveats": [...],
"latency_ms": 13
}
Per-category breakdown of the 20-claim test: confirmed-block category
10/10 (100%), ambiguous category 5/5 (100%), false-claim category
4/5 (80% — the one "failure" is the honest-data case described
above). All ten heavy-censorship claims (Telegram/Signal/WhatsApp in
Iran, YouTube/Facebook/WhatsApp/Tor in China, Instagram in Russia,
Twitter in Turkey, plus the headline IR/Twitter) returned
partial_block or confirmed_block. All four
"is X blocked in Germany/USA/Canada/Japan" claims returned
not_observed as expected.
This is a building block for downstream systems: an LLM agent can
verify its own claims before publishing, a journalist's chatbot can
fact-check user-typed assertions in real time, and a research-paper
auto-generation pipeline can refuse to cite a country-service pair
when the verdict comes back insufficient_data or
not_observed. Free tier; cached for 5 minutes on the
Worker edge.