Verifica un file
POST https://api.kennmarq.com/v1/verify
GET https://api.kennmarq.com/v1/credentials/{watermark_id}
GET https://api.kennmarq.com/v1/verify/key
Cosa dicono il manifest C2PA e le filigrane invisibili di un’immagine, di un brano o di una clip, nostri o di chiunque altro; su richiesta, come risultato firmato da noi. Gratis, senza chiave. La pagina del verificatore fa lo stesso per le immagini nel tuo browser, senza caricare nulla.
POST /v1/verify
Invia l’immagine come multipart/form-data in file (PNG, JPEG o WebP; la richiesta è al massimo di 4 MB). Aggiungi signed=true per un risultato firmato. I nostri server a Zurigo leggono il file in memoria e non conservano nulla. Un’immagine più grande, fino a 25 MB, passa da un upload indicato in upload, che richiede la chiave che lo ha creato; oppure verificala sulla pagina del verificatore, nel tuo browser, con qualsiasi dimensione fino a 25 MB. Brani (MP3, WAV, M4A) e clip (MP4) vengono letti sui nostri server allo stesso modo, fino a 25 MB, con una chiave (una qualsiasi delle tue, gratis; non conta nulla): vedi brani e clip.
curl https://api.kennmarq.com/v1/verify -F file=@picture.jpg -F signed=true{
"object": "check",
"checked_at": "2026-11-12T10:00:00Z",
"checker": { "name": "Kennmarq.com", "version": "0.4.0" },
"file": { "type": "image/jpeg", "bytes": 482113, "width": 1024, "height": 768, "sha256": "…" },
"c2pa": {
"state": "Trusted",
"manifest": "urn:c2pa:3fa85f64-…",
"signer": { "common_name": "Kennmarq.com", "issuer": "Neuramare", "ours": true, "environment": "live" },
"signed_at": "2026-11-12T09:58:31+00:00",
"time_stamp": { "validated": true, "trusted": true },
"claim_generator": "Kennmarq.com 0.4.0",
"ai": { "digital_source_type": "http://cv.iptc.org/newscodes/digitalsourcetype/trainedAlgorithmicMedia", "generated": true },
"soft_binding": { "alg": "com.adobe.trustmark.Q", "value": "1*0101…" },
"failures": []
},
"watermark": { "found": true, "alg": "com.adobe.trustmark.Q", "schema": "BCH_5", "id": "1d455a804e9802a6", "matches_manifest": true },
"durable_credential": {
"watermark_id": "1d455a804e9802a6",
"manifest": "urn:c2pa:3fa85f64-…",
"environment": "live",
"asset_sha256": "…",
"same_file": true,
"log_index": 1834001,
"url": "https://api.kennmarq.com/v1/credentials/1d455a804e9802a6"
},
"log": { "leaf_index": 1834001, "status": "included", "proof_url": "https://api.kennmarq.com/v1/log/proof/1834001" },
"signed": { "jws": "eyJhbGciOiJFUzI1NiIs…", "key_id": "…", "log_index": 1834530 }
}c2paènullquando il file non contiene un manifest.stateèTrustedquando la firma risale ai nostri certificati radice (ours),Validper un altro firmatario la cui firma risulta corretta, eInvalidquando il file è cambiato dopo la firma;failureselenca i codici.watermark.idè valorizzato per le filigrane nel nostro schema (BCH_5); le altre filigrane TrustMark risultano trovate, con il loro schema, quando il centro dell’immagine restituisce esattamente la stessa lettura, così un’immagine senza marcatura non ne mostra una per caso. La nostra si legge anche in un’immagine salvata ruotata di lato o capovolta.durable_credential: ciò a cui rimanda la filigrana nei nostri archivi, quando il file l’abbiamo firmato noi. Quando una piattaforma rimuove i metadati, è così che si ritrova la credenziale di provenienza;same_fileindica se è proprio il file che abbiamo firmato, ed ènullper un file marcato in modalità locale, che non ci è mai arrivato.log: la voce del manifest nel nostro registro di trasparenza.- Brani e clip:
filehaseconds(e, per una clip, le sue dimensioni);watermarkscontiene la lettura Video Seal della clip (id, letto da 64 fotogrammi, eagreement, la quota dei suoi 256 bit che concordano) e quella AudioSeal (detected, la quota del suono che risulta marcata, ebitssu 16);c2paaggiungeclaims, le filigrane che il manifest dichiara presenti nel file, e ilwatermark_recorddi una clip.watermarkè allora il Video Seal della clip, che rimanda alla sua credenziale di provenienza durevole come quello di un’immagine, oppure l’AudioSeal del brano, che dice che il file è stato marcato da noi ma non contiene alcun ID.
Risultati firmati
Con signed=true, signed.jws è un JWS (RFC 7515, compatto) firmato con ES256 dalla chiave del nostro verificatore: il suo payload è il risultato qui sopra (il file, il suo manifest e la sua filigrana, l’ora), più iss, iat e un jti univoco; il kid del suo header indica la chiave. Prima di essere restituito entra nel nostro registro di trasparenza come voce checker.result (lo SHA-256 del JWS, quello del file e l’ID della chiave), all’indice riportato in X-Log-Index. Qualsiasi libreria JWT lo verifica con la chiave di GET /v1/verify/key.
import { decodeProtectedHeader, importSPKI, jwtVerify } from "jose";
const { jws } = result.signed;
const { kid } = decodeProtectedHeader(jws);
const key = await (await fetch(`https://api.kennmarq.com/v1/verify/key?key_id=${kid}`)).json();
const { payload } = await jwtVerify(jws, await importSPKI(key.public_key, "ES256"), { issuer: "Kennmarq.com" });
// payload.file.sha256 is the SHA-256 of the file that was checked; compare it with yours.
console.log(payload.file.sha256, payload.checked_at);GET /v1/credentials/{watermark_id}
Il manifest store C2PA a cui rimanda una filigrana, conservato dal momento in cui abbiamo firmato il file: in JSON (lo store in base64 in manifest_store), oppure con ?format=c2pa come file .c2pa leggibile da qualsiasi strumento C2PA. Chiunque sappia leggere la filigrana può scaricarlo, quindi chiunque abbia l’immagine.
curl "https://api.kennmarq.com/v1/credentials/1d455a804e9802a6?format=c2pa" -o credential.c2paGET /v1/verify/key
La chiave pubblica del verificatore: key_id (SHA-256 della sua SubjectPublicKeyInfo DER), algorithm e public_key (PEM). Con ?key_id= e il kid di un JWS, la chiave che lo ha firmato, comprese quelle con cui non firmiamo più; senza, la più recente.
Errori
| Stato | Codice | Quando |
|---|---|---|
| 400 | invalid_request | Nessun file, un campo inviato due volte, signed diverso da true o false, un’immagine illeggibile, oppure un ID della filigrana o un key_id non validi. |
| 400 | unknown_field | Un campo diverso da file (o upload) e signed. |
| 401 | missing_api_key, invalid_api_key, api_key_revoked | È stato indicato un upload senza la chiave che lo ha creato. |
| 400 | option_not_available | url: la verifica di un file tramite URL non è ancora disponibile. |
| 404 | not_found | Nessuna credenziale di provenienza con quell’ID della filigrana, oppure nessuna chiave del verificatore con quel key_id. |
| 404 | upload_not_found | L’upload indicato non è utilizzabile con questa chiave: sconosciuto, già usato, scaduto o di un’altra chiave. |
| 413 | payload_too_large | La richiesta supera i 4 MB: verifica le immagini più grandi sulla pagina del verificatore, oppure invia i file tramite un upload (fino a 25 MB). |
| 415 | unsupported_media_type | Non è multipart, oppure non è un’immagine, un brano o una clip che sappiamo leggere. |
| 429 | rate_limited | Più di 10 verifiche al minuto o 200 al giorno da un solo indirizzo (un indirizzo IPv6 conta per il suo /64; ricerche: 120 al minuto), le verifiche senza chiave di oggi sono esaurite per tutti oppure, con una chiave, le chiamate al minuto della tua organizzazione. |
| 503 | marker_unavailable, storage_unavailable | Il verificatore (o gli upload) non è disponibile, oppure un risultato firmato non ha superato la verifica prima dell’invio. Riprova. |