Vaelis
Documentation

API reference

Vaelis verifies C2PA content credentials in media assets, computes a Trust Score, and generates signed EU AI Act Article 50 evidence files.

Basics

ItemValue
Base URLhttps://vaelistrust.com
AuthWhen enabled, send x-api-key: <your key>. During the pilot phase the API may be open.
Inputmultipart/form-data (field file) or JSON {"url": "..."} — the service downloads the asset (max 10 MB, public URLs only).
Size limit10 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 limit20 POST requests per minute per IP (fixed window). Over the limit: 429 with Retry-After: 60.
Request IDEvery 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 statusok 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

ScenarioConditionScore
AManifest present, signature valid, chain trusted80 (+20 with valid TSA timestamp), max 100
A-clashAs A, but watermark confidence ≥ 0.85 and the manifest claims human authorship20, integrity_clash = true (watermark is a veto only here)
BNo fully valid manifest, watermark confidence ≥ 0.540 + 30·confidence, +15 broken manifest, +15 trainedAlgorithmicMedia; cap 85
CNo reliable signals0, +15 trainedAlgorithmicMedia, +5 broken manifest; cap 20

Errors

StatusMeaning
400Invalid input — malformed body, missing file field or url, unsupported content type.
401Missing or invalid API key (only when key auth is enabled).
422Unprocessable asset — download failed, empty body, or the URL fails the SSRF guard (non-public address).
429Rate limit exceeded (20 POST requests per minute per IP). Wait for the window to reset.
500Internal 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.