Basics
| Item | Value |
|---|---|
| Base URL | https://vaelistrust.com |
| Auth | When enabled, send x-api-key: <your key>. During the pilot phase the API may be open. |
| Input | multipart/form-data (field file) or JSON {"url": "..."} — the service downloads the asset (max 10 MB, public URLs only). |
| Size limit | 10 MB per asset by default (operator-tunable via MAX_ASSET_MB, ceiling 50 MB); 50 files / 50 MB per batch. GB-scale video is on the roadmap (streaming pipeline). |
| Rate limit | 20 POST requests per minute per IP (fixed window). Over the limit: 429 with Retry-After: 60. |
| Request ID | Every response carries an x-request-id header for support and log correlation. |
POST /v1/verify
Run the full verification pipeline on one asset.
# upload a file curl -F "file=@image.jpg" https://vaelistrust.com/v1/verify # or pass a URL curl -H "Content-Type: application/json" \ -d '{"url": "https://example.com/image.jpg"}' \ https://vaelistrust.com/v1/verify
Response (abridged):
{
"trust_score": 100,
"integrity_clash": false,
"verdict": "trusted",
"c2pa": {
"manifest_present": true,
"signature_valid": true,
"cert_chain_trusted": true,
"trust_list_enforced": true,
"timestamp_valid": true,
"issuer": "Example Issuer",
"manifest_uri": "self#jumbf=c2pa",
"errors": [],
"actions": ["c2pa.created"]
},
"watermark": { "detected": false, "confidence": 0.0, "vendor": "none configured (SynthID API pending)" },
"exif": { "digital_source_type": null, "software": null }
}
cert_chain_trusted means the signing chain anchors to the official C2PA trust list (30 roots, see GET /v1/trust-roots). A self-signed or unknown chain scores as untrusted even when the signature itself is cryptographically valid.
POST /v1/verify-batch
Verify many assets in one request. A batch counts as one request against the rate limit.
# upload up to 50 files (50 MB total) curl -F "files=@a.jpg" -F "files=@b.png" \ https://vaelistrust.com/v1/verify-batch # or pass up to 100 URLs curl -H "Content-Type: application/json" \ -d '{"urls": ["https://example.com/a.jpg", "https://example.com/b.jpg"]}' \ https://vaelistrust.com/v1/verify-batch
Returns a JSON array in input order: each item is the full /v1/verify response plus a filename field. A failed URL fetch returns that item with score 0 and the error recorded — it does not fail the batch. Try it in the batch playground.
POST /v1/audit/evidence-file
Verify an asset and receive a signed, W3C-PROV-compliant Article 50 evidence file.
Same input as /v1/verify, plus optional fields: deployer_id, publication_id, disclosure_decision (default displayed_eu_ai_icon).
curl -H "Content-Type: application/json" \
-d '{"url": "https://example.com/image.jpg", "deployer_id": "acme-news"}' \
https://vaelistrust.com/v1/audit/evidence-file
The response contains the full JSON-LD document, the asset's SHA-256, and the server-side file path. The document is signed with the platform's Ed25519 key: the signature field is a base64 Ed25519 signature over the canonical JSON (object keys sorted recursively, no whitespace, signature/signingKeyId excluded). Verification procedure: strip those two fields, canonicalize, verify against the platform public key identified by signingKeyId.
POST /v1/telemetry/drift
Compare live assets against expected hashes and re-validate provenance.
curl -H "Content-Type: application/json" \
-d '{"items": [{"url": "https://example.com/live.jpg", "expected_sha256": "abc..."}]}' \
https://vaelistrust.com/v1/telemetry/drift
Per item you get actual_sha256, hash_match, c2pa_manifest_present, trust_score, and status — ok only when the hash matches and a fully valid, trusted manifest is present, otherwise drifted. Max 100 items per request; fetches are sequential by design.
GET /v1/health · GET /v1/trust-roots
/v1/health returns {"status": "ok", "time": "<rfc3339>"} — use it for uptime checks (or see /status). /v1/trust-roots returns the loaded C2PA trust anchors.
Trust Score v1
| Scenario | Condition | Score |
|---|---|---|
| A | Manifest present, signature valid, chain trusted | 80 (+20 with valid TSA timestamp), max 100 |
| A-clash | As A, but watermark confidence ≥ 0.85 and the manifest claims human authorship | 20, integrity_clash = true (watermark is a veto only here) |
| B | No fully valid manifest, watermark confidence ≥ 0.5 | 40 + 30·confidence, +15 broken manifest, +15 trainedAlgorithmicMedia; cap 85 |
| C | No reliable signals | 0, +15 trainedAlgorithmicMedia, +5 broken manifest; cap 20 |
Errors
| Status | Meaning |
|---|---|
400 | Invalid input — malformed body, missing file field or url, unsupported content type. |
401 | Missing or invalid API key (only when key auth is enabled). |
422 | Unprocessable asset — download failed, empty body, or the URL fails the SSRF guard (non-public address). |
429 | Rate limit exceeded (20 POST requests per minute per IP). Wait for the window to reset. |
500 | Internal error. The x-request-id header identifies the request in server logs. |
Errors are JSON: {"error": "<message>"}.
Current limitations
Watermark detection is multi-provider: an optional detector sidecar (Meta's TrustMark, real pixel-level decoding) runs when WATERMARK_DETECTOR_URL is set; SynthID integration follows Google's API access (waitlist only today). EXIF/IPTC extraction is live (digitalSourceType, Software, plus AI-generator metadata hints). Evidence files on the hosted demo are written to ephemeral disk.
Access
API keys are provisioned by email: hello@vaelistrust.com. Or try the API without a key in the playground.