Live verifier
Drop a file to verify it against this API. The bytes are hashed and checked; they are never stored.
Verdicts
labelled | A C2PA credential is present and validates. |
unlabelled | No verifiable credential found. Not proof of anything about AI. |
invalid | A credential is present but validation failed. |
indeterminate | Unsupported type, or the engine errored/timed out. |
Validation state distinguishes Trusted (signer on a known trust list) from
Valid (cryptographically intact but unknown signer). AI signal
(aiInferred) is one of ai-generated, ai-edited,
not-declared, unknown.
Endpoints
POST /v1/verify
Verify one asset → verdict + manifest summary + signed audit record.
# multipart upload
curl -s -X POST "$BASE/v1/verify" -F "file=@photo.jpg"
# by URL
curl -s -X POST "$BASE/v1/verify" \
-H "content-type: application/json" \
-d '{"url":"https://example.com/image.jpg"}'
// fetch (browser)
const fd = new FormData();
fd.append("file", fileInput.files[0]);
const r = await fetch("/c2pa/v1/verify", { method: "POST", body: fd });
const { verdict, aiInferred, audit } = await r.json();
POST /v1/verify/batch
curl -s -X POST "$BASE/v1/verify/batch" \
-H "content-type: application/json" \
-d '{"assets":[{"id":"a","url":"https://ex.com/1.jpg"},{"id":"b","url":"https://ex.com/2.png"}]}'
POST /v1/report
Full parsed manifest store + raw C2PA validation_results (for display/debugging).
GET /v1/audit/{recordId} · GET /v1/usage
Retrieve a retained audit record (API-key holders) and see your usage/quota.
Static (no auth): /api/v1/*
index.json · meta.json · formats.json · status-codes.json · audit-key.json · openapi.yaml
Signed audit record
Every verify returns a tamper-evident record — asset hash, verdict, trust-list & engine
versions, timestamp — signed with the service key. Verify it offline with the
public key at /api/v1/audit-key.json and the
@c2pa-provenance/lib verifyAuditRecord() helper. No asset bytes are ever stored.
Access & rate limits
Public and free. Anonymous callers get 60 req/min and 5,000/day
per IP; an optional API key raises that and retains audit history. Over-limit returns
429 with Retry-After. Uploads over the size cap return 413;
images with any side over 8000px return 400.