Guides
Content Credentials
Sign images with Content Credentials that name Etchv's watermark as a soft binding, and recover a copy's manifest from its watermark through the public C2PA resolver.
Content Credentials (C2PA) attach a signed record of a file's origin to the file itself. That record lives in the file's metadata, so it is lost when a platform or an editor strips the metadata. Etchv's watermark is in the pixels instead, so a copy without its metadata still carries it. Etchv's public resolver uses that watermark to give back the copy's original manifest.
How it works
- You watermark an image with
provenance=c2pa. Etchv embeds the watermark, then signs a C2PA manifest into the file. - The manifest has a
c2pa.watermarked.boundaction and ac2pa.soft-bindingassertion. The assertion names the algorithmcom.etchv.watermark.1and carries the file's watermark ID. - The file is opted in to public provenance: its manifest store is kept so that anyone can recover it from the watermark.
- Someone finds a copy whose metadata is gone. A C2PA tool, or anyone, asks the resolver with the copy itself or with its watermark ID. The resolver returns the manifest ID, and the manifest store is one request away.
Only opted-in files can be resolved. A watermark ID from any other file matches nothing, exactly like one that doesn't exist, and an answer names a manifest and nothing else: no workspace, asset or filename.
The watermark algorithm
alg | com. |
| Type | Invisible watermark |
| Media | Images; Etchv also watermarks PDFs and video, which don't carry Content Credentials yet |
| Payload | A 256-bit watermark ID |
Soft-binding value | The 32 bytes of the watermark ID, base64-encoded (44 characters) |
algcom.etchv. watermark. 1
- Type
- Invisible watermark
- Media
- Images; Etchv also watermarks PDFs and video, which don't carry Content Credentials yet
- Payload
- A 256-bit watermark ID
- Soft-binding
value - The 32 bytes of the watermark ID, base64-encoded (44 characters)
The watermark ID is the 64-character hex digest that X-Watermark-ID returns
when you watermark a file; see embedding. Detection reads it
from the pixels, so removing the metadata doesn't affect it. Editing or
recompressing the file can affect recovery.
To turn a watermark ID into a soft-binding value:
VALUE=$(python3 -c 'import base64, sys; print(base64.b64encode(bytes.fromhex(sys.argv[1])).decode())' "$WATERMARK_ID")Sign a file with Content Credentials
Add provenance=c2pa to an image watermark request:
curl --fail-with-body "https://api.etchv.com/watermarks/images?provenance=c2pa" \
-H "X-API-Key: $ETCHV_API_KEY" \
-F 'file=@photo.png' \
--form-string 'data={"generation_id":"gen_0042"}' \
--output photo-signed.pngIt applies to JPEG, PNG, WebP, single-page TIFF and GIF images, and costs the
same as any image embed. Any other format returns 422.
Resolve a copy
The resolver implements the C2PA Soft Binding Resolution API at
https:. It takes no credentials.
/c2pa/v1/matches/byContentSend the image itself as the request body. The resolver detects its watermark and returns the matching manifests:
curl --fail-with-body "https://api.etchv.com/c2pa/v1/matches/byContent" \
-H "Content-Type: image/png" \
--data-binary @copy.png{
"matches": [
{
"manifestId": "urn:c2pa:6f1e2a7c-4d3b-4c55-9a8e-2b1f0c9d7e61",
"endpoint": "https://api.etchv.com/c2pa/v1",
"similarityScore": 100
}
]
}It takes one JPEG, PNG, WebP, TIFF or GIF image of up to 5 MB and 20 megapixels.
A detected watermark that differs from an opted-in one in up to 48 of its 256
bits still matches, with a lower similarityScore (out of 100).
/c2pa/v1/matches/byBindingIf you already have the watermark ID, query by its soft-binding value, URL-encoded:
curl --fail-with-body -G "https://api.etchv.com/c2pa/v1/matches/byBinding" \
--data-urlencode "alg=com.etchv.watermark.1" \
--data-urlencode "value=$VALUE"POST takes the same alg and value as a JSON body.
/c2pa/v1/manifests/{manifestId}Returns the manifest store as application:
curl --fail-with-body "https://api.etchv.com/c2pa/v1/manifests/$MANIFEST_ID" \
--output photo.c2paGET lists com.etchv.watermark.1 under
watermarks.
Both matches routes take maxResults, from 1 to 10 (default 10). The newest
manifest comes first.
Validate the manifest
The Etchv Content Credentials client, open source under the MIT license, resolves a copy, fetches its manifest store and validates it in one step:
pip install "git+https://github.com/etchv-labs/integrations.git#subdirectory=c2pa"
etchv-c2pa copy.png --save copy.c2paValidate the copy against the manifest store with any C2PA validator, such as the C2PA SDK or c2patool, giving it the store as external manifest data.
The signature and the claim validate. The hard binding reports
assertion.dataHash.mismatch, and that's expected: the data hash covers the
signed file's bytes, and a copy without its metadata has different bytes. The
soft binding is what ties the copy to the manifest. A validator also reports
signingCredential.untrusted unless Etchv's signing certificate is on its
trust list.
Limits
| Route | Limit |
|---|---|
| Every resolver route | 60 requests a minute per IP address |
matches | 10 requests an hour per IP address, and a shared daily limit across all callers |
- Every resolver route
- Limit
- 60 requests a minute per IP address
matches/byContent - Limit
- 10 requests an hour per IP address, and a shared daily limit across all callers
A request over a limit returns 429. Over the matches limits, the
429 carries Retry-After, in seconds; the shared daily limit resets at
midnight UTC.
| Status | Meaning |
|---|---|
400 | An alg other than com., a value that isn't 32 bytes in base64, or a manifest ID that isn't a URN |
404 | No such manifest |
413 | An image larger than 5 MB or 20 megapixels |
415 | Not a supported still image, more than one frame or page, or an image too large to decode safely |
422 | A maxResults outside 1–10, or a malformed query or body |
429 | Over a limit |
503 | Detection is briefly unavailable; try again later |
400- Meaning
- An
algother thancom., aetchv. watermark. 1 valuethat isn't 32 bytes in base64, or a manifest ID that isn't a URN
404- Meaning
- No such manifest
413- Meaning
- An image larger than 5 MB or 20 megapixels
415- Meaning
- Not a supported still image, more than one frame or page, or an image too large to decode safely
422- Meaning
- A
maxResultsoutside 1–10, or a malformed query or body
429- Meaning
- Over a limit
503- Meaning
- Detection is briefly unavailable; try again later