Protocol integration design. The sandbox returns a signed test receipt and a C2PA assertion
payload; your tool must embed and sign the manifest itself. Hosted manifest verification and
production conformance certification are not available.
Start with the runnable quickstart and sandbox support matrix.
c2pa object: the receipt, ready to add to the C2PA manifest you
sign for the output. You add it next to a c2pa.actions entry that declares the output as AI
generated, sign the manifest with your own certificate, and show the disclosure label. Your
platform stays the C2PA claim signer. The receipt inside is signed by Reflections, so it verifies
on its own, whoever signed the manifest.
What you receive
The generation carries the assertion and the obligations that ask for it:c2pa is present once the decision is allow: in the generation response, in
generation.allowed for outputs checked
asynchronously, and in generation.released for held
outputs. You can read it again at any time with
GET /v1/generations/{generation_id}.
Order of operations
1
Finish the bytes
Resize, re-encode, and draw any visible label into the pixels before you submit the
generation. The receipt’s
artifact_sha256 is the digest of the bytes you submitted.2
Submit and wait for allow
Create the generation. A held or asynchronous output has no
c2pa until it is allowed.3
Write the manifest
Add a
c2pa.actions assertion and the c2pa object, unchanged, to the manifest definition.4
Sign with your certificate
Sign the manifest as you sign any C2PA claim, and embed it in the file.
5
Deliver with the label
Show the disclosure text where the obligation’s
placement says, then deliver.Write the manifest
This is a manifest definition in the JSON form thatc2patool reads (see the
C2PA specifications for the assertions). It declares the output as
created by a trained algorithm, using the IPTC digital source type
http://cv.iptc.org/newscodes/digitalsourcetype/trainedAlgorithmicMedia, and carries the receipt
assertion exactly as the generation returned it.
manifest.json
private_keyandsign_certare your platform’s C2PA signing key and certificate chain. Never use a Reflections key: the receipt carries the Reflections signature.descriptionon the action holds the disclosure text when thedisclosureobligation’splacementismetadataorboth.- Copy
c2pa.labelandc2pa.datawithout changes. The receipt is a signed JWS; a single changed character makes it fail verification.
c2patool, the open-source C2PA command-line tool:
c2pa-rs for Rust,
c2pa-node for Node.js and c2pa-python for Python. Because the generation’s c2pa object already
has the label and data shape of a manifest assertion, you can append it as is:
Place the disclosure
Thedisclosure obligation gives the exact text and where it goes. Show the text as written; do
not shorten or translate it.
For a visible label:
level decides the wording: licensed says the person’s likeness is licensed, brand adds who
licensed it, and scope adds the use. The text already reflects the level, so you only place it.
Before release, a held output has no receipt and no c2pa. If the generation carries
draft_watermark, any preview carries the visible draft mark instead.
Check your output
Read the manifest back withc2patool:
manifest.signer is your platform. Test receipts verify only with a test key.
What can go wrong
Related
Provenance
Receipts, manifests, fingerprints and verification.
C2PA assertion
The
ai.reflections.license assertion format.C2PA interoperability
Manifest and assertion placement in the Standard.
Verify content
Find the receipt behind any file.