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.bound action and a c2pa.soft-binding assertion. The assertion names the algorithm com.etchv.watermark.1 and 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

algcom.etchv.watermark.1
TypeInvisible watermark
MediaImages; Etchv also watermarks PDFs and video, which don't carry Content Credentials yet
PayloadA 256-bit watermark ID
Soft-binding valueThe 32 bytes of the watermark ID, base64-encoded (44 characters)
alg
com.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:

Shell
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:

Shell
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.png

It 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://api.etchv.com/c2pa/v1. It takes no credentials.

POST/c2pa/v1/matches/byContent

Send the image itself as the request body. The resolver detects its watermark and returns the matching manifests:

Shell
curl --fail-with-body "https://api.etchv.com/c2pa/v1/matches/byContent" \
  -H "Content-Type: image/png" \
  --data-binary @copy.png
JSON
{
  "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).

GET/c2pa/v1/matches/byBinding

If you already have the watermark ID, query by its soft-binding value, URL-encoded:

Shell
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 /c2pa/v1/matches/byBinding takes the same alg and value as a JSON body.

GET/c2pa/v1/manifests/{manifestId}

Returns the manifest store as application/c2pa:

Shell
curl --fail-with-body "https://api.etchv.com/c2pa/v1/manifests/$MANIFEST_ID" \
  --output photo.c2pa

GET /c2pa/v1/services/supportedAlgorithms 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:

Shell
pip install "git+https://github.com/etchv-labs/integrations.git#subdirectory=c2pa"
etchv-c2pa copy.png --save copy.c2pa

Validate 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

RouteLimit
Every resolver route60 requests a minute per IP address
matches/byContent10 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/byContent limits, the 429 carries Retry-After, in seconds; the shared daily limit resets at midnight UTC.

StatusMeaning
400An alg other than com.etchv.watermark.1, a value that isn't 32 bytes in base64, or a manifest ID that isn't a URN
404No such manifest
413An image larger than 5 MB or 20 megapixels
415Not a supported still image, more than one frame or page, or an image too large to decode safely
422A maxResults outside 1–10, or a malformed query or body
429Over a limit
503Detection is briefly unavailable; try again later
400
Meaning
An alg other than com.etchv.watermark.1, a value that 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 maxResults outside 1–10, or a malformed query or body
429
Meaning
Over a limit
503
Meaning
Detection is briefly unavailable; try again later
View source on GitHub

Your privacy, your choice

We use essential cookies to keep Etchv working. Optional analytics helps us improve the site. Analytics is on by default; you can turn it off in preferences. PostHog loads only if you accept all. Privacy policy

ETCHV

Privacy preferences

Choose what you allow on this browser. Analytics is enabled by default. You can turn it off, and change your choice at any time.

Essential

Always active

Supports secure sign-in, account sessions, site security, and remembering your privacy choice. These are needed for Etchv to work.

Analytics

Helps us understand visits and improve the website using page-view and device statistics, which do not use cookies. PostHog also measures visits and campaigns and may set cookies; it loads only after you save a choice with analytics on. Turning this off stops future analytics events.

We do not load advertising scripts. Meeting calendars load only when you open them. These preferences do not change your account, watermarking requests, or asset storage.

Your choice is remembered for 180 days on this browser. Privacy policy