For developers

The fact-checking API for AI output. Human-written works too.

When a document, report or answer is about to ship, Lenz checks its factual claims and returns a sourced verdict with a full audit trail. One API call. Under the hood: multiple models across five stages, grounded in external sources.

Five API calls, one escalation path:

  • POST /extract pulls verifiable claims out of any text or web page.
  • POST /assess returns a fast panel verdict on each claim.
  • POST /verify runs the full pipeline and returns a verdict with citations.
  • POST /ask/{id} answers follow-up questions on a verification.
  • POST /review returns the issues in a whole draft, with suggested rewrites.

Open the quickstart notebook in Google Colab Run the five calls against your own key.

OpenAPI 3.1 spec /api/v1/openapi.json →

Five API calls. Pick the depth your use case needs.

Find claims, judge them fast, prove them deep, ask follow-ups, review a whole draft.

POST /extract Free · 1,000/day

# AI-generated brief in — atomic, verifiable claims out
brief = """
Looking at the data, Einstein had a remarkable career. He won the
1921 Nobel Prize in Physics for his theory of general relativity,
which most physicists consider one of the most important scientific
achievements of all time. His famous equation E=mc² was first published
in 1905, the same year he completed his PhD at the University of Zurich.
"""

out = client.extract(text=brief)
for c in out.identified_claims:
    print("-", c)
# Opinions and meta-commentary skipped; pronouns resolved; compound sentences split:
# - Albert Einstein won the 1921 Nobel Prize in Physics for his theory of general relativity.
# - Albert Einstein first published the equation E=mc² in 1905.
# - Albert Einstein completed his PhD at the University of Zurich in 1905.

Free, so it can run on every draft before a credit is spent.

text can also be a single public web page URL (http or https, nothing else in the field). Lenz reads the page, or a YouTube video's transcript, and extracts the claims from its first 50,000 characters. Pages behind a login (Facebook, Instagram, Threads, LinkedIn) can't be read. A URL call typically takes 5-40 seconds: SDK 2.13 and later wait up to 90 seconds; with an older SDK, create the client with Lenz(timeout=90) (Python) or new Lenz({ timeoutMs: 90000 }) (Node).

POST /assess ~10s · 3-model panel

# fast verdict from a 3-model frontier panel
r = client.assess(text="Albert Einstein won the 1921 Nobel Prize in Physics for his theory of general relativity.")
for c in r.claims:
    print(c.verdict, c.confidence)
    if c.rationale:
        print(c.rationale)
# False high
# The 1921 prize was awarded for his explanation of the photoelectric effect, not for relativity.

# a list of up to 20 in one call — one row per claim, same order
rows = client.assess(claims=["Water boils at 100 °C at sea level.", "Drinking coffee lowers the risk of heart disease."]).claims
for c in rows:
    print(c.verdict, c.confidence)
    if c.dissent:
        print("One reviewer disagreed:", c.dissent)
# True high
# Mostly True low
# One reviewer disagreed: The studies show an association, not that coffee itself lowers the risk.

# escalate low-confidence claims to /verify
if r.claims[0].confidence == "low":
    deep = client.verify_and_wait(claim=r.claims[0].claim)

One text, or the claims /extract returned in a single call. Mobile pre-flight, or any UI where users wait for an answer. Use confidence to decide when to escalate.

rationale is the reasoning of a reviewer who agrees with the panel's verdict; dissent, when set, is the reasoning of the reviewer farthest from it. Both are reviewers' notes, not checked sources; for sourced evidence, call /verify.

POST /verify ~90s · multi-model pipeline

# deep check with citations
v = client.verify_and_wait(claim="Albert Einstein won the 1921 Nobel Prize in Physics for his theory of general relativity.")

print(v.verdict, v.lenz_score, v.confidence)
# → "False" 1 "high"
# The 1921 Nobel was awarded for the photoelectric effect, not relativity.

for s in v.sources[:2]:
    print(s.title, s.url)
# → "Albert Einstein at UZH" — uzh.ch

Multiple models orchestrated through a purpose-built verification pipeline: framing → research → debate → panel review → conclusion. Returns a report with reasoning and citations.

POST /ask Q&A on a verification

# follow up on any verification
reply = client.ask.send(
    v.verification_id,
    message="What did Einstein actually win the 1921 Nobel Prize for?",
)
print(reply.content)
# → The photoelectric effect, not relativity. The Nobel committee cited his
#   1905 paper on the discovery of the law of the photoelectric effect.

Ground a chat thread on the verification's evidence. Same citations, same model, no re-research per turn.

POST /review 2–4 min · the whole ladder

# a whole draft in; the issues and the suggested rewrites out
draft = "The EU AI Act took effect in March 2024. It sorts AI systems into four risk tiers."

review = client.review_and_wait(text=draft)
for i in review.issues:
    print(i.verdict, i.claim)
    if i.suggested_rewrite:
        print("  Suggested rewrite:", i.suggested_rewrite)
# False The EU AI Act took effect in March 2024.
#   Suggested rewrite: The EU AI Act entered into force on 1 August 2024.

Extract, assess and verify in one call: the claims that come back negative or low-confidence get the full pipeline, up to a cap you set. review_and_wait polls for you; pass webhook_url to be called instead.

Three jobs, and the calls each one takes.

What goes in, what comes back, which endpoints.

Marketing and competitor claims

A landing page draft says “the only platform that” and quotes a market-share figure. /extract pulls the checkable claims out of the draft, /assess returns a verdict on each in ~10s, and /verify runs the ones a competitor would challenge — the “only” and the market-share figure — through the full pipeline. What comes back: a verdict per claim with the sources that support or contradict it, before the page goes live.

The marketing desk →
Newsletter issues

An issue is twenty sentences of figures, dates and names. /extract with a focus on exactly those, /assess on every claim it finds, and the doubtful ones escalated to /verify. What comes back: one verdict per claim, with sources, in document order. Verifications stay private to your account.

The editorial desk →
Legal and tax memos

A memo cites statutes, thresholds and treaty articles. /extract lists them as claims; /verify checks each against current sources. A citation that does not exist, or a threshold that changed last year, comes back with the sources it fails against, and every verdict carries an audit trail a colleague can re-read months later.

The tax and legal desk →

LLM hallucination detection

  • Lenz does it against the evidence: /extract pulls out every factual claim, /verify investigates each one you send it: it researches independent sources, has two models argue both sides and three reviewers score the evidence — a sourced verdict with citations, not a confidence guess.
  • LLM hallucination detection, in depth →

Independent verification, with a full audit trail.

Lenz checks your AI's output with multiple frontier models from rival vendors, cross-checked against curated sources. You get an independent verdict, decided on the evidence, with citations.

Every verification ships the full trace: framing, sources, citations, the opposing-side debate, and the panel's reasoning. When a customer, auditor, or regulator asks how a claim was checked, you have an independent, third-party record — proof the content was verified before you published it.

Picking between /assess and /verify

  • Need citations and a research trail? → /verify
  • Need batch throughput or a fast take in ~10s? → /assess
  • Calling from a UI where the user waits for the result? → /assess, then escalate low-confidence claims to /verify
  • Want to drill into a finished verdict? → /ask on the verification_id
  • Need the issues in a whole draft, with fixes? → /review

Pricing

Self-serve from day one. Pay only for what runs the pipeline.

Free

$0

100 credits/month
enough for 100 /assess, or 10 /verify, or 100 /ask
/extract free · 1,000/day

Prototype today, zero spend. No card required.

Pro

$99/mo

5,000 credits/month
enough for 5,000 /assess, or 500 /verify, or 5,000 /ask
/extract free · 1,000/day

Self-serve. Annual plan: $83/mo, billed $990 yearly. For teams shipping AI-drafted text.

Scale

$399/mo

20,000 credits/month
enough for 20,000 /assess, or 2,000 /verify, or 20,000 /ask
/extract free · 1,000/day

Annual plan: $333/mo, billed $3,990 yearly. For high-volume production workflows.

Compare all plans on the plans page →

Enterprise

Volume beyond the Scale plan, SLAs, white-label, custom integration support.

Talk to us →

10 lines in Python or TypeScript

Typed SDKs in Python and TypeScript. One method call returns the verdict.

Python 3.9+

# pip install lenz-io
from lenz_io import Lenz

client = Lenz(api_key="lenz_...")
v = client.verify_and_wait(
    claim="Albert Einstein won the 1921 Nobel Prize "
          "in Physics for his theory of general relativity.",
)
print(v.verdict, v.lenz_score)
# False 1

TypeScript Node 18+

// npm install lenz-io
import { Lenz } from "lenz-io";

const client = new Lenz({ apiKey: "lenz_..." });
const v = await client.verifyAndWait({
  claim: "Albert Einstein won the 1921 Nobel Prize "
       + "in Physics for his theory of general relativity.",
});
console.log(v.verdict, v.lenz_score);
// False 1

See the SDK in action — two open-source demos

Both run entirely on the keyless public API through the lenz-io SDKs — live claims and verdicts from the catalog, no backend of their own. Fact or Fiction is a trivia game whose whole data layer is one library.list() call; IsThisBS? is a complete fact-check publication generated from the catalog as static pages.

Fact or Fiction React · Vite · lenz-io

// the entire data layer — no API key needed
import { Lenz } from "lenz-io";

const lenz = new Lenz();
const round = await lenz.library.list({
  curated: ["trivia"],       // named curated collections
  sort: "random",
  verdict: "True,False",
});

IsThisBS? Python · Jinja2 · lenz-io

# an entire fact-check site — no API key, no server, no database
from lenz_io import Lenz

client = Lenz()                    # keyless public reads
page = client.library.list(sort="recent")
v = client.verifications.get(page.items[0].verification_id)

Or skip the SDK — run it from your shell

The same four primitives as a CLI. pipx install, paste your key once, done. Add --json to any command to pipe straight into jq.

CLI no code · pipx

# pipx install "lenz-io[cli]"   — isolated install, recommended
$ lenz login                          # paste an API key (free)
$ lenz extract "…output from your LLM…"   # atomic claims · free, 1,000/day
$ lenz extract "https://en.wikipedia.org/wiki/Air_pollution"   # or a public web page, by URL
$ lenz assess  "The Great Wall is visible from space"   # fast 3-model verdict
$ lenz verify  "Water boils at 90°C at sea level"        # full multi-model pipeline, ~90s
# False · 1/10
$ lenz verify  "<claim>" --json | jq .verdict       # machine-readable
$ lenz ask <verification_id> "Which source is strongest?"

Or skip code entirely — connect it to your AI client

Lenz is a remote MCP server. Add it to Claude Code, Cursor, or any MCP client with your API key — or connect it in Claude Desktop or ChatGPT by signing in with your Lenz account, no key needed — and your assistant can fact-check a claim inline.

MCP Streamable HTTP · .mcp.json

{
  "mcpServers": {
    "lenz": {
      "type": "http",
      "url": "https://lenz.io/mcp",
      "headers": { "Authorization": "Bearer ${LENZ_API_KEY}" }
    }
  }
}

Not writing code? Connect Lenz to Claude or ChatGPT → — the same server, as click-paths, with no config to edit.

Add the guided workflow — the fact-check Skill

The connector gives your agent the Lenz tools; the lenz-fact-check Agent Skill adds the workflow on top — it finds the claims in a passage, runs assess_claim on each, escalates the high-stakes ones to a deep verify_claim, and hands back verdicts, with sources on the claims it checks in depth, bucketed by confidence. A complement to your RAG-faithfulness checks, not a replacement.

n8n and Zapier

  • The Lenz node is live on n8n, and the Zapier app adds the same step to any Zap. Add a fact-check step to any workflow, no API code required. Integrations →

The boring infrastructure is taken care of.

Idempotency by default

A network drop after submit never spawns a duplicate task. The SDK sends an Idempotency-Key per call. On /verify, requests without one get a key derived from the body, so two identical submits collapse into one run — send your own key to force two.

Auto-retry on transient errors

5xx and 429 retried with exponential backoff, honoring Retry-After. From SDK 2.7.0, waits over 60s raise immediately so you can schedule them instead of blocking.

HMAC-signed webhooks

Submit with webhook_url=..., Lenz POSTs the typed payload when done. LenzWebhooks.parse() verifies signatures in 4 lines.

Support-ready errors

Every error carries cause + fix + docs URL + a request_id you can quote on a ticket.

12 supported languages

API responses in English (default) plus Spanish, German, French, Italian, Portuguese, Dutch, Swedish, Danish, Norwegian, Finnish, and Bulgarian.

By use case

Resources

Research

Open evaluations of how frontier LLMs perform on real-world user claims. Frozen snapshots, full data, full methodology.

Ship verified AI output.

Self-serve from day one. Free tier, no card required.