Verify a PDF from any agent or backend in one call
Atomara is a REST API that checks whether a PDF bank statement, payslip, invoice or receipt was edited after it was issued, and returns a verdict, a 0–100 score and the signals behind them.
POST the file with your key. The analysis usually finishes while the request is open, so the same response already carries the answer — no queue to poll, no callback to host.
Get an API key Get the agent skill
Register with a work email and your first key adds 100 trial checks.
Call it from anything that can make an HTTP request
The skill below is tested with Claude Code, Codex CLI and OpenCode, which scan a skills directory for a SKILL.md. Cursor, Gemini CLI, n8n, a GitHub Action or a plain Python, PHP or Node script talk to the same endpoint directly — there is nothing agent-specific in the API.
- Claude Code
- Codex CLI
- OpenCode
- Cursor
- Gemini CLI
- n8n
- GitHub Actions
- any script with HTTP
How it works
Two steps for most documents, three for a slow one.
- Send the PDF POST /documents as multipart/form-data with the file and your key in the Authorization header. Let your HTTP client write the Content-Type — a hand-set multipart header drops the boundary. Never base64 the PDF into a tool argument: models truncate long strings and a truncated file is a meaningless verdict.
- Read the answer Most documents are analysed within 20 seconds and come back 200 with status completed: a verdict, a 0–100 score, a one-line summary and every signal with its page and position. Branch on the verdict and the signal ids — both are stable.
- The rare slow one If the analysis takes longer, the answer is 202 with status processing. Nothing failed: poll GET /documents/{id} every few seconds until it is completed or failed. The helpers in the skill do this for you.
curl -X POST https://atomara.io/api/v1/documents \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Idempotency-Key: applicant-1042-statement" \
-F "file=@statement.pdf" \
-F "external_id=applicant-1042"
{
"id": "doc_3f9a1c8e6d2b4f7a9c311e5b0a77d4c2",
"object": "document",
"status": "completed",
"external_id": "applicant-1042",
"verdict": "tampered",
"score": 3,
"tamper_score": 0.87,
"integrity_score": 0.05,
"confidence": 0.82,
"summary": "The file was re-saved by an editor after issue.",
"signals": [
{
"id": "editor_producer_blacklist",
"module": "M4",
"kind": "tamper",
"severity": "high",
"evidence": "Producer: Adobe Acrobat Pro DC",
"scored": true
},
{
"id": "invariant_balance",
"module": "M8",
"kind": "tamper",
"severity": "medium",
"page": 2,
"evidence": "Closing balance: expected 4310.50, found 6310.50",
"scored": true
}
],
"engine": {
"version": "1.0.0",
"rules_revision": "2026-07-07"
},
"report_url": "https://atomara.io/account/uploads/3f9a1c8e6d2b4f7a9c311e5b0a77d4c2"
}
The agent skill
A ready-to-use pack: a SKILL.md that teaches the agent the flow, the response and how to report a result honestly, plus two helpers that submit, wait and print the verdict — one in bash (curl + jq), one in Python with no dependencies. Clone it into the directory your agent already scans.
git clone https://github.com/atomara-io/atomara-skill .claude/skills/atomara
Project skills live under .claude/skills/<name>/SKILL.md; use ~/.claude/skills/atomara to install it for every project.
git clone https://github.com/atomara-io/atomara-skill .agents/skills/atomara
Codex reads repository skills from .agents/skills/<name>/SKILL.md at the Git root.
git clone https://github.com/atomara-io/atomara-skill .opencode/skills/atomara
OpenCode discovers project skills from .opencode/skills/<name>/SKILL.md.
- Your key, once The helpers read ATOMARA_API_KEY or a git-ignored key file next to the skill. The key never has to appear in a prompt.
- A code to branch on Every run exits 0 for no scored signs of editing, 2 for review, 3 for tampered, 4 when the file could not be analysed — so a CI step or an agent acts on a decision, not on a parsed sentence.
- Safe to retry The request carries an Idempotency-Key derived from the file, so a re-run after a dropped connection returns the same document and is never charged twice.
What the agent gets back, and what it should say
- verdict — tampered, suspicious, inconclusive, authentic or unsupported. authentic means an intact digital signature, or a file matching a reference template of its issuer in every structural detail (basis reference_match — then reference_match.attack_tested says whether the amounts were verified too); an ordinary unsigned PDF with nothing wrong is inconclusive with no signals.
- score — 0 (edited) to 100 (intact), the same number the dashboard shows. null for scans and photos, which are checked as images: a picture cannot show which document it was taken from, so the skill tells the agent to ask for the original PDF.
- signals — the evidence, each with a stable id, a severity and, where the engine can pin it down, the page and the box on the page. The skill instructs the agent to quote them and never to invent a finding that is not in the list.
- What it does not do: the check reads the file — it does not contact the bank or employer that issued it. A match with an issuer's reference template is a fact about the file's structure, not a confirmation from the issuer. The skill makes the agent say so.
What it does not do
- It reads the PDF itself: its structure, metadata, fonts and arithmetic. It does not contact the bank or employer that issued it.
- Send documents as PDF — a JPEG or PNG is refused. A scan or a photo saved as a PDF is checked as an image and usually comes back without a score, because a picture of a page cannot show which file it was taken from. Route it to a person, or ask for the original PDF.
- An unsigned file is called authentic only when its structure matches, in every detail, a reference template learned from genuine documents of its issuer, and nothing points to editing; the response then says whether the amounts were verified too. Otherwise the best answer for an unsigned file is inconclusive with no signs of editing found.
- There are no bank-specific templates. The same checks run on a statement from any bank.
Pricing
From $0.10 per document at volume, with no minimum and no setup fee. One document is one check, whatever its page count. Paid plans start at $5 a month. See all plans →
Questions platform teams ask
Can ChatGPT or Claude tell on their own whether a PDF is fake?
Not reliably. A general assistant can read the text in a PDF, but it does not inspect the file's structure, its saved revisions, its fonts, its metadata or whether the numbers on the page add up — so it guesses. The skill sends the file to the forensic API and gives the agent a verdict, a score and the signals to quote instead.
How do I verify a PDF programmatically?
Create a key under Developers in your Atomara account, then POST the file as multipart/form-data to /api/v1/documents with the key in the Authorization header. The response is JSON with the verdict, the score and the signals. Any HTTP client works; there is no client library to install.
Is there a free way to test it?
Yes. Register with a work email and your first API key adds 100 trial checks to your organization — every one of them is the full analysis on a real document. On a private mail address, ask for trial credits on the Developers page and a person answers.
What does the API do with a scan or a photo?
A scan or a photo saved as a PDF goes through and is checked as an image. It usually comes back without a score, because a picture of a page cannot show which file it was taken from; the response marks the case with basis: image_container so the agent can route it to a person or ask for the original PDF. A JPEG or PNG is refused — send PDFs.
Why call the REST API directly rather than pass the file through a chat tool?
Because a tool call takes model-generated text as its input, so a PDF would have to be inlined as a base64 string of tens of thousands of characters — which models truncate, and a truncated file gives a meaningless answer. The helpers send the raw bytes as a multipart upload from the shell, so the file arrives intact.
Where is the full reference?
At /docs/api: every endpoint, the response object field by field, verdicts and score bands, error codes, limits and data retention, with the OpenAPI document and a Postman collection to download.
Your documents
Files and results are deleted 30 days after upload; DELETE /documents/{id} removes them at once. Documents are not shared with third parties and are not used to train models.