Quickstart
Get a key, run a quick check and a deep check on one claim, then check a whole draft: about five minutes, in Python, TypeScript or the shell.
Prefer your browser? The Colab notebook runs the same calls.
Contents
Get an API key
Sign up and generate a key at /api-credentials; it is shown once, so copy it somewhere safe. A free account gets 100 free credits a month.
Using an AI coding agent? /setup writes the steps for Claude Code, Cursor, Codex or n8n, and issues a test key only where the route needs one.
Install the SDK
Put the key in the environment; every example below reads it from there.
export LENZ_API_KEY=lenz_...
pip install lenz-io
npm install lenz-io
pipx install "lenz-io[cli]"
The lenz CLI calls Lenz from your shell, with --json to pipe into jq; it ships in the Python package behind the cli extra.
A quick check: /assess
A 3-model panel returns a verdict and a confidence for each claim in about 15 seconds, for 1 credit a claim: a first read, with the pages the reviewers looked at (searched_pages).
from lenz_io import Lenz client = Lenz() # reads LENZ_API_KEY rows = client.assess( claim="The Great Wall of China is visible from space.", ).claims for c in rows: print(c.verdict, c.confidence) # e.g. False high if c.rationale: print(c.rationale)
import { Lenz } from "lenz-io"; const client = new Lenz(); // reads LENZ_API_KEY const { claims } = await client.assess({ claim: "The Great Wall of China is visible from space.", }); for (const c of claims) { console.log(c.verdict, c.confidence); // e.g. False high if (c.rationale) console.log(c.rationale); }
lenz assess "The Great Wall of China is visible from space."curl -X POST https://lenz.io/api/v1/assess \ -H "Authorization: Bearer $LENZ_API_KEY" \ -H "X-Lenz-API-Version: 2026-10-11" \ -H "Content-Type: application/json" \ -d '{"claim": "The Great Wall of China is '\ 'visible from space."}'
rationale is the reasoning of a reviewer who agrees with the panel's verdict. It is a reviewer's note, not a checked source; for sourced evidence, run the deep check.
A quick check can complete with the verdict No Public Record: no public record was found that would show the claim. Its confidence is never high, so branch on verdict as well as confidence.
A deep check: /verify
Lenz investigates the claim: it researches independent sources, has two models argue both sides, and has three reviewers score the evidence. It takes about 90 seconds and costs 10 credits (5 at depth="low"). The deep check can change the quick verdict; rely on the deep check.
v = client.verify_and_wait(
claim="The Great Wall of China is visible from space.",
)
print(v.verdict, v.lenz_score) # e.g. False 2
print(v.key_finding)
for s in v.sources[:2]:
print(s.title, s.url)const v = await client.verifyAndWait({ claim: "The Great Wall of China is visible from space.", }); console.log(v.verdict, v.lenz_score); // e.g. False 2 console.log(v.key_finding); for (const s of (v.sources ?? []).slice(0, 2)) { console.log(s.title, s.url); }
lenz verify "The Great Wall of China is visible from space."A deep check can also complete with the verdict No Public Record: no public record was found that would show the claim. lenz_score is then null (None in Python), so print or branch on verdict first.
A whole draft: /review
One call reads a draft’s claims, quick-checks each, and deep-checks the ones that come back False, Mostly False, Mixed or No Public Record, or with low confidence, up to five; it takes 2–4 minutes and returns the issues with suggested rewrites. It costs 1 credit per quick check and 10 per deep check, and an answer served from the last hour's cache is free, unless it issues you a new warranty certificate, which costs the depth you asked for.
draft = (
"The EU AI Act entered into force on 1 August 2024. "
"Fines for prohibited practices reach 7% of "
"global annual turnover. About 40% of European "
"companies had started compliance work by the "
"end of 2024."
)
review = client.review_and_wait(text=draft)
# clean | issues_found | incomplete | unchecked
print(review.outcome)
for i in review.issues:
print(i.verdict, i.claim)
if i.suggested_rewrite:
print(" Suggested rewrite:", i.suggested_rewrite)const draft = "The EU AI Act entered into force on 1 August 2024. " + "Fines for prohibited practices reach 7% of " + "global annual turnover. About 40% of European " + "companies had started compliance work by the " + "end of 2024."; const review = await client.reviewAndWait({ text: draft }); // clean | issues_found | incomplete | unchecked console.log(review.outcome); for (const i of review.issues) { console.log(i.verdict, i.claim); if (i.suggested_rewrite) { console.log(" Suggested rewrite:", i.suggested_rewrite); } }
# quick verdicts first, each row rewritten as its deep check lands
lenz review draft.mdA suggested_rewrite is not verified itself: check it before you use it. Set escalate.max_citations to also check the draft’s links and DOIs.
A citation: /citecheck
For each citation, Lenz reads the source and says whether it says what your text attributes to it, with the passage it rests on, for 1 credit per checked citation (the citation guide).
check = client.citecheck_and_wait(pairs=[{
"statement": "Mount Everest is 7,000 metres high.",
"url": "https://en.wikipedia.org/wiki/Mount_Everest",
}])
for c in check.citations:
# result is None when the check failed on our side
finding = c.result.finding if c.result else "failed"
print(finding, c.check.snippet)const check = await client.citecheckAndWait({ pairs: [{ statement: "Mount Everest is 7,000 metres high.", url: "https://en.wikipedia.org/wiki/Mount_Everest", }], }); for (const c of check.citations) { // result is null when the check failed on our side console.log(c.result?.finding ?? "failed", c.check.snippet); }
# pairs from stdin (or --pairs pairs.json); a draft file works too: lenz citecheck draft.md echo '[{"statement": "Mount Everest is 7,000 metres high.", "url": "https://en.wikipedia.org/wiki/Mount_Everest"}]' \ | lenz citecheck --pairs -
Follow-up questions: /ask
Ask about a deep check, answered from its evidence, for 1 credit a question.
reply = client.ask.send(
v.verification_id,
message="Which source is strongest?",
)
print(reply.content)const reply = await client.ask.send(v.verification_id, { message: "Which source is strongest?", }); console.log(reply.content);
lenz ask <verification_id> "Which source is strongest?"reply.content is plain text with bold, italic, bullet lists and [label](url) links, which only ever point to the verification’s own sources.
Going to production
- Webhooks: pass
webhook_urland Lenz POSTs the signed result when a run ends. - Batch: many claims in one
verify_batchcall. - Stopping a run:
cancela verification, a review or a citation check you no longer need. - Timeouts and retries: when to resend, and with which key.
depth="low": a shallower deep check for 5 credits.
All of it on Going to production; every endpoint in the API reference.
If something fails
LenzAuthError: the key is missing or wrong; checkLENZ_API_KEY.LenzQuotaExceededError(402): out of credits; plans and top-ups are on billing.LenzRateLimitError(429): waitretry_afterseconds, then send it again.
Every error carries a request_id to quote to support; the full list is on the errors page.
Using the API in production? Read the Terms of Service →