Site icon SSL.com

SSL Provenance API

Introduction

Focus on your core proposition. We handle C2PA and CAWG. The SSL Provenance API is fully managed REST API from SSL. It creates, signs and edits C2PA manifests (Content Credentials) for your images, video and audio in a single API call. It can also attach a CAWG identity assertion and your own custom assertions. Signing uses your SSL.com eSigner credentials. Private keys stay secure in SSL's HSMs, and every signature is timestamped by SSL's conformant C2PA Timestamp Authority.

Quick Start

Sign a JPEG and save the result:
curl -X POST https://mss.ssl.com/v1/c2pa/sign \
  -H "Authorization: Bearer <your-access-token>" \
  -H "C2PA-Certificate-Id: 983da863-ce7f-42b5-b227-c9076c7b34af" \
  -H "Content-Type: image/jpeg" \
  --data-binary @photo.jpg \
  --output signed_photo.jpg
signed_photo.jpg is your original image with a signed C2PA manifest embedded.

Base URL

https://mss.ssl.com
All endpoints are versioned under /v1/c2pa/.

Authentication

Every signing request needs two values from your SSL.com eSigner account:
Value Header Description
Access token Authorization: Bearer <access_token> Your eSigner API access token. It authorizes the API to use your signing credential on your behalf.
Credential ID C2PA-Certificate-Id: <credential_id> The ID of the eSigner credential (certificate and key) used to sign the C2PA claim.
The signing algorithm comes from the credential's key. Supported algorithms are ES256, ES384, ES512 (ECDSA) and PS256, PS384, PS512 (RSA-PSS).

Registering an application for an eSigner access token

Access tokens are issued to an application you register with SSL.com's eSigner CSC API. Registering takes about 15 minutes:
  1. Sign in. Go to login.ssl.com and sign in with your SSL.com account.
  2. Open Manage Applications. Select the Manage Applications menu by clicking the persona icon on the upper right.
  3. Create the application. Click Create Application.
  4. Fill in the form, then click Submit Details:
    • Application Name: a unique name for your application.
    • Redirect URIs: applications that integrate with eSigner on the web need a valid redirect URI back to your server. This URI will not be used for the Provenance API but it is required. Feel free to add anything you'd like.
    • Confidential: check this box if your application runs on a server and can store the secret securely. Leave it unchecked for client-side applications, such as native mobile or browser apps.
    • Scopes: enter service.
  5. Save your credentials. You now have an Application ID and an Application Secret. Use them to request access tokens from the eSigner CSC API.
For screenshots and more detail, see Register an Application with eSigner's CSC API.
Keep your Application Secret private. Never embed it in client-side code or commit it to source control.

What the API Adds to Your Asset

Each successful sign request adds one new, signed manifest to the asset. That manifest contains: All of these are recorded as created assertions, which means the signer takes responsibility for them.

Assets that already have Content Credentials

If the uploaded asset already carries a C2PA manifest, the API keeps its existing provenance. The new manifest is added to the existing manifest store, and the previous manifest is linked in as the parent ingredient. The asset's full history stays intact and verifiable. Existing signatures are checked against the official C2PA Trust List, so validators can report whether the earlier signer was trusted.

Supported Content Types

Pass one of the following MIME types to /v1/c2pa/sign. Use the request's Content-Type header for a raw body, or the asset part's Content-Type for a multipart request.
Category Content-Type Format
Images image/jpeg JPEG
image/png PNG
image/gif GIF
image/tiff TIFF
image/webp WebP
image/avif AVIF
image/heic HEIC
image/heif HEIF
image/jxl JPEG XL (see notes)
image/svg+xml SVG
image/dng DNG
image/x-adobe-dng Adobe DNG
Video video/mp4 MP4
video/quicktime QuickTime (MOV)
video/x-m4v M4V
video/avi AVI
video/msvideo AVI (MS)
video/x-msvideo AVI (x-ms)
Audio audio/mpeg MP3
audio/mp4 M4A
audio/flac FLAC
audio/wav WAV
audio/wave WAV
audio/x-wav WAV
audio/vnd.wave WAV
Parameters on the MIME type, such as ; charset=utf-8, are ignored.

Endpoints

Health Check

GET /v1/c2pa/health
Returns the service status. No authentication required. Response
Status Content-Type Body
200 OK application/json {"status":"ok"}
Example
curl https://mss.ssl.com/v1/c2pa/health

Sign Asset

POST /v1/c2pa/sign
Signs the asset and returns it with a C2PA manifest embedded. This endpoint accepts two request formats, chosen by the request's Content-Type:
Format Request Content-Type Use it when
Raw body The asset's own MIME type, e.g. image/jpeg You only need standard signing, with or without a CAWG identity assertion.
Multipart form multipart/form-data You also want to embed custom assertions.
Both formats support every feature except custom assertions, which require multipart. Request Headers
Header Required Description
Authorization Yes Bearer <access_token>: your eSigner access token
C2PA-Certificate-Id Yes eSigner credential ID used to sign the C2PA claim, if you use the SSL Provenance API certificate the credential ID is: 983da863-ce7f-42b5-b227-c9076c7b34af
Content-Type Yes Raw body: the asset's MIME type (see Supported Content Types). Multipart: multipart/form-data; boundary=..., which most HTTP clients set for you.
CAWG-Certificate-Id No eSigner credential ID used to sign a CAWG identity assertion. If present, the identity assertion is added. Can be the same as C2PA-Certificate-Id.
CAWG-Role No One or more named actor roles, such as cawg.creator, for the identity assertion. Requires CAWG-Certificate-Id. To send several roles, repeat the header, separate values with commas, or both.

Option A: Raw body

The request body is the asset's bytes, up to 50 MB. The Content-Type header gives the asset's MIME type.

Option B: Multipart form-data

The request body is multipart/form-data with these parts, up to 50 MB in total:
Part Required Part Content-Type Description
asset Yes The asset's MIME type, e.g. image/jpeg The asset's bytes. This part's Content-Type decides how the asset is signed, so it must be set. curl's -F "asset=@photo.jpg" infers it from the file extension. Many other clients don't, so set it yourself, for example -F "asset=@photo.jpg;type=image/jpeg".
manifest_options No application/json A JSON document that customizes the manifest. See Custom Assertions.
manifest_options schema:
{
  "custom_assertions": [
    { "label": "com.example.my-assertion", "data": { "any": "json object" } }
  ]
}
Field Type Description
custom_assertions array Up to 16 custom assertions to embed. To add one assertion, send a one-element array.
custom_assertions[].label string Required. A unique label in reverse-domain notation. See label rules.
custom_assertions[].data object Required. Any JSON object, up to 8 KB when serialized. It is embedded exactly as sent.
Response
Status Condition Content-Type Body
200 OK Success Same as the asset's Content-Type The signed asset with the C2PA manifest embedded
4xx / 5xx Error application/json {"error":"<description>"}. See Errors.

Examples

Sign a JPEG image with the SSL Provenance API Claim signing certificate:
curl -X POST https://mss.ssl.com/v1/c2pa/sign \
  -H "Authorization: Bearer <your-access-token>" \
  -H "C2PA-Certificate-Id: 983da863-ce7f-42b5-b227-c9076c7b34af" \
  -H "Content-Type: image/jpeg" \
  --data-binary @photo.jpg \
  --output signed_photo.jpg
Sign an MP4 video:
curl -X POST https://mss.ssl.com/v1/c2pa/sign \
  -H "Authorization: Bearer <your-access-token>" \
  -H "C2PA-Certificate-Id: 983da863-ce7f-42b5-b227-c9076c7b34af" \
  -H "Content-Type: video/mp4" \
  --data-binary @video.mp4 \
  --output signed_video.mp4
Sign a JPEG XL image:
curl -X POST https://mss.ssl.com/v1/c2pa/sign \
  -H "Authorization: Bearer <your-access-token>" \
  -H "C2PA-Certificate-Id: 983da863-ce7f-42b5-b227-c9076c7b34af" \
  -H "Content-Type: image/jxl" \
  --data-binary @image.jxl \
  --output signed_image.jxl
Sign a JPEG and add a CAWG identity assertion that names the creator:
curl -X POST https://mss.ssl.com/v1/c2pa/sign \
  -H "Authorization: Bearer <your-access-token>" \
  -H "C2PA-Certificate-Id: 983da863-ce7f-42b5-b227-c9076c7b34af" \
  -H "CAWG-Certificate-Id: <your-identity-credential-id>" \
  -H "CAWG-Role: cawg.creator" \
  -H "Content-Type: image/jpeg" \
  --data-binary @photo.jpg \
  --output signed_photo.jpg
Sign a JPEG and embed a custom assertion (multipart):
curl -X POST https://mss.ssl.com/v1/c2pa/sign \
  -H "Authorization: Bearer <your-access-token>" \
  -H "C2PA-Certificate-Id: 983da863-ce7f-42b5-b227-c9076c7b34af" \
  -F "asset=@photo.jpg;type=image/jpeg" \
  -F 'manifest_options={"custom_assertions":[{"label":"com.example.tracking","data":{"internal_id":"ACME-2026-004421"}}]};type=application/json' \
  --output signed_photo.jpg
Combine all of them: a CAWG identity with two roles, plus two custom assertions:
curl -X POST https://mss.ssl.com/v1/c2pa/sign \
  -H "Authorization: Bearer <your-access-token>" \
  -H "C2PA-Certificate-Id: 983da863-ce7f-42b5-b227-c9076c7b34af" \
  -H "CAWG-Certificate-Id: <your-identity-credential-id>" \
  -H "CAWG-Role: cawg.creator,cawg.editor" \
  -F "asset=@photo.jpg;type=image/jpeg" \
  -F 'manifest_options={"custom_assertions":[
        {"label":"com.example.tracking","data":{"internal_id":"ACME-2026-004421"}},
        {"label":"com.example.billing","data":{"account_ref":"AR-9001"}}
      ]};type=application/json' \
  --output signed_photo.jpg

CAWG Identity Assertions

A CAWG identity assertion (cawg.identity) lets a named actor, such as the photographer or author, sign a statement that binds their identity to the asset. This is separate from the C2PA claim signature, which identifies the organization or tool that produced the manifest. To add one, you first need to add your own CAWG certificate, contact us to purchase and provision one. Then, send the CAWG-Certificate-Id header with the eSigner credential for your CAWG certificate.

Named actor roles

Use the CAWG-Role header to describe the actor's role, for example cawg.creator or cawg.editor. To send more than one role, you can: Role values are embedded exactly as sent. Roles defined by the CAWG specification and your own custom role identifiers are both accepted. CAWG-Role requires CAWG-Certificate-Id. Without it, the request returns 400 Bad Request.

Custom Assertions

Custom assertions let you embed your own structured data in the signed manifest, such as an internal asset ID, a workflow reference or licensing metadata. Each one is a JSON object under a label you choose. It is covered by the manifest signature, so any change to it is detected. Custom assertions require the multipart request format, sent in the manifest_options part.
Custom assertions are not confidential. Like every C2PA assertion, they are signed, so changes can be detected, but they are not encrypted. Anyone who reads the manifest can read them. If a value must stay private, encrypt it before you send it.

Label rules

Every custom_assertions entry needs a label that: If an entry breaks any of these rules, the request returns 400 Bad Request with a message that names the rule.

Constraints

Constraint Limit
Custom assertions per request 16
Size of each entry's data (serialized JSON) 8 KB
Type of data JSON object (not an array, string or number)

Format-Specific Behavior

JPEG XL

A JPEG XL file can be a bare codestream or an ISOBMFF container. A C2PA manifest can only be embedded in the container form, so the API handles each one like this: The signed output is always a JPEG XL container, and standard JPEG XL decoders read it.

M4A audio

audio/mp4 (M4A) files are handled as MP4 containers. The response keeps the audio/mp4 content type.

Errors

All errors return a JSON body:
{ "error": "<human-readable description>" }
Status Cause Example message
400 Bad Request C2PA-Certificate-Id is missing or empty credential ID not present in request
400 Bad Request CAWG-Role sent without CAWG-Certificate-Id CAWG-Role requires CAWG-Certificate-Id: cawg.creator
400 Bad Request Multipart: the asset part has no Content-Type asset part must declare a Content-Type
400 Bad Request Multipart: manifest_options is not valid JSON, has more than 16 entries, has an entry with a missing or invalid label, has a data value that isn't an object or is over 8 KB, or repeats a label Invalid manifest_options: <reason>
400 Bad Request Multipart: the multipart body is malformed or over the size limit multipart error: <reason>
413 Payload Too Large The raw body is over 50 MB
415 Unsupported Media Type The asset's MIME type is not supported Unsupported media type: image/bmp
500 Internal Server Error The credential couldn't be loaded: the access token is invalid or expired, or the credential ID is wrong or not available to this token No credential info: <reason>
500 Internal Server Error Signing, timestamping or manifest generation failed, for example because the asset is corrupt or doesn't match its declared type <reason>
Troubleshooting tips

Limits

Item Limit
Request size (raw body or whole multipart body) 50 MB
Custom assertions per request 16
Custom assertion data size 8 KB each
Custom assertion label length 256 characters

Verifying a Signed Asset

You can inspect and validate the Content Credentials on any signed asset with standard C2PA tools: The output shows the SSL Provenance API claim generator, the c2pa.opened action, the parent ingredient, any CAWG identity assertion and custom assertions, and the signing certificate and timestamp.
Exit mobile version