POST /v1/verify
POST /v1/verify and GET /v1/verify/{manifest_id}
Verify an asset’s provenance. Runs multi-signal verification: C2PA manifest parse and signature check, OCSP check, watermark decode, soft-binding lookup, and anchor batch check.
The public verify endpoint (POST /v1/verify without authentication) is rate-limited per IP. Authenticated requests use per-tenant rate limits.
POST /v1/verify
POST https://api.verbitas.io/v1/verifyAuthorization: Bearer vb_live_... (optional for public verify)Content-Type: multipart/form-data (when uploading a file) -- or --Content-Type: application/json (when using asset_id or manifest_uri)Request: file upload
curl -X POST https://api.verbitas.io/v1/verify \ -H "Authorization: Bearer $VERBITAS_API_KEY" \Request: by asset ID
curl -X POST https://api.verbitas.io/v1/verify \ -H "Authorization: Bearer $VERBITAS_API_KEY" \ -H "Content-Type: application/json" \ -d '{"asset_id": "a_01j..."}'Request: by manifest URI
curl -X POST https://api.verbitas.io/v1/verify \ -H "Authorization: Bearer $VERBITAS_API_KEY" \ -H "Content-Type: application/json" \ -d '{"manifest_uri": "https://m.verbitas.io/manifests/a_01j.../manifest.c2pa"}'GET /v1/verify/{manifest_id}
Retrieve a previously-computed verification result by manifest ID (cached for the TTL of the manifest).
curl -H "Authorization: Bearer $VERBITAS_API_KEY" \ https://api.verbitas.io/v1/verify/a_01j... | jq .Response: 200 OK
{ "status": "verified_manifest_and_watermark_match", "confidence": 0.97, "signals": { "c2pa_manifest_present": true, "c2pa_signature_valid": true, "signer_trusted": true, "timestamp_valid": true, "ocsp_status": "good", "watermark_present": true, "watermark_payload_valid": true, "fingerprint_match": false, "anchor_match": true }, "claims": { "origin": "acme-pipeline.example", "generator": "stable-diffusion-xl", "model": "sdxl-1.0", "ai_generated": true, "ai_assisted": false, "created_at": "2026-05-09T08:32:00Z" }, "matches": [], "warnings": [], "developer_explanation": "C2PA manifest verified. Signer cert valid and OCSP good. TrustMark decoded; watermark_id matches manifest record.", "user_explanation": "Provenance verified — manifest intact and watermark agrees.", "proves": [ "The C2PA manifest was signed by a certificate on the Verbitas trust list.", "The manifest has not been modified since signing.", "The embedded watermark ID matches the manifest record." ], "does_not_prove": [ "The assertions in the manifest were accurate when submitted.", "The content is semantically truthful." ]}Response fields
| Field | Type | Description |
|---|---|---|
status | string | One of 16 closed-enum codes. See Verification States. |
confidence | float or null | 0.0-1.0 weighted signal aggregate. null for hard-failure states. |
signals | object | Per-signal boolean or string results |
claims | object | Assertions from the manifest (if present) |
matches | array | Soft-binding matches (for watermark_only or fingerprint_match_only) |
warnings | array | Non-fatal issues (e.g. ocsp_unavailable in dev) |
developer_explanation | string | Technical summary for logging and debugging |
user_explanation | string | Plain-language summary for UI display |
proves | array | Specific claims supported by the evidence |
does_not_prove | array | Explicit list of claims not supported |
Tampered response example
{ "status": "manifest_tampered", "confidence": null, "signals": { "c2pa_manifest_present": true, "c2pa_signature_valid": false }, "developer_explanation": "Claim digest mismatch: stored digest does not match computed digest of submitted asset.", "user_explanation": "Manifest contents were altered after signing.", "proves": [], "does_not_prove": ["The manifest cannot be trusted — it was modified after signing."]}Python SDK example
import verbitas
client = verbitas.Client()
result = client.verify("received_image.jpg")print(result.status, result.confidence)
result = client.verify(asset_id="a_01j...")
if result.status == "verified_manifest_and_watermark_match": pass # proceedelif result.status == "manifest_tampered": raise ValueError(f"Asset tampered: {result.developer_explanation}")TypeScript SDK example
import { VerbitasClient } from "@verbitas/sdk";
const client = new VerbitasClient();const result = await client.verify({ assetId: "a_01j..." });
console.log(result.status); // "verified_manifest_and_watermark_match"console.log(result.confidence); // 0.97Error codes
| HTTP | Code | Meaning |
|---|---|---|
| 400 | verbitas.verify.no_input | No file, asset_id, or manifest_uri provided |
| 401 | verbitas.auth.invalid_key | API key invalid (authenticated endpoint) |
| 415 | verbitas.verify.unsupported_file_type | File format not in supported set |
| 429 | verbitas.ratelimit.exceeded | Rate limit exceeded |
Public endpoint
POST /v1/verify without an Authorization header is publicly accessible. The public endpoint is rate-limited to 10 requests/minute per IP and logs no PII about the requester.