Docs

How Coatables verifies a Certificate of Analysis

Last updated: 15 June 2026

Upload a CoA PDF (digital or scanned). A vision model reads it; a deterministic layer recomputes the safety-critical values and cross-checks them against the lab's printed verdict. You get verified JSON and Excel.

The three steps

  1. Extract — Claude vision reads digital PDFs and scans natively: analyte, result, unit, spec limit, method, LOD/LOQ, and the lab's printed verdict.
  2. Verify — limit notation and units are normalized, then pass/fail is recomputed from the parsed numbers — not guessed by a model.
  3. Reconcile — the computed verdict is compared to the lab's printed one. Any disagreement, missing field, or low-confidence read is flagged.

What it supports

Third-party supplement lab reports — heavy metals, microbiology, contaminants — across a bounded set of common lab formats. It is deliberately not a general "any document" extractor; an unrecognized layout is flagged for review rather than silently guessed (and isn't charged).

Limit notation it reads

NotationMeaning
≤ / < / ≥ / >upper / lower bounds
NMT / NLT / max / minnot-more-than / not-less-than
X–Yrange
Absent in 25 gmicrobial absence
ND / <LOQnot detected / below quantitation

Units are canonicalized and compared by class: mg/kg ↔ ppm, µg/kg ↔ ppb, mg/g ↔ %, and CFU/g classes. A result whose unit class doesn't match the analyte is flagged.

Output

JSON — the full structured result: document header, and per analyte the raw + parsed result, normalized unit, structured limit (min/max/type), method, LOD/LOQ, the lab's verdict, the computed verdict, whether they match, confidence, and flags.

XLSX — a Header sheet (document metadata) plus an Analytes sheet, one row per analyte with the same columns.

Verification flags

FlagMeaning
verdict_mismatchour recomputed pass/fail disagrees with the lab's printed verdict
missing_limita result with no spec limit to check against
unparseable_limita limit string we couldn't normalize
ambiguous_unita unit we couldn't canonicalize (skipped for qualitative results)
unit_class_mismatchthe unit class doesn't fit the analyte
low_confidencea low-confidence read (common on scans) — check it
no_analytesdocument-level: nothing recognized as a supported CoA

API

The tool is a thin client over one endpoint.

FieldValue
POST/api/extract
bodymultipart/form-data, field file = the PDF (≤ 20 MB)
?format=xlsxreturns the XLSX instead of JSON
AuthorizationBearer <credit key> (when billing is on)
X-Credits-Remainingresponse header with your balance after the call
402 / 400 / 500no/invalid key or out of credits / no file / extraction error

Try it on a sample certificate →