Architecture overview

Before writing code, it helps to understand the data model. A C2PA Content Credential (formally called a C2PA Manifest) is a signed data structure embedded within or alongside a media file. It contains three core components:

Assertions are individual statements about the content. These can describe creation information (camera model, software used), actions taken (cropping, colour adjustment, AI generation), or custom data. Assertions are the building blocks - each one captures a single fact about the content's history.

A Claim bundles assertions together with metadata about the signing entity and references to any "ingredient" manifests (provenance from earlier in the content's history). The claim is the unit that gets signed.

A Claim Signature is a cryptographic signature over the claim, produced using an X.509 certificate. This is what makes the manifest tamper-evident - any modification to the content or the manifest after signing will invalidate the signature.

These three components together form a C2PA Manifest. A file can contain multiple manifests chained together, forming a Manifest Store - this is what creates the provenance chain. When you open a file that was captured on a camera, edited in Photoshop, and exported for web, the manifest store contains three linked manifests representing each stage.

Embedding vs. remote storage

Manifests can be embedded directly in the file (the default for JPEG, PNG, TIFF) or stored remotely and referenced via a URL. Remote storage is useful for formats that don't support arbitrary metadata, or when you want to keep file sizes minimal. The specification supports both approaches, and a single file can use a combination of embedded and remote manifests.

Available SDKs and tools

The Content Authenticity Initiative maintains the official open-source implementations. Here's what's available:

Tool / LibraryLanguageUse CaseRepository
c2pa-rsRustCore library. All other SDKs are built on this.github.com/contentauth/c2pa-rs
c2pa-nodeNode.jsServer-side JavaScript/TypeScript applicationsgithub.com/contentauth/c2pa-node
c2pa-pythonPythonData pipelines, ML workflows, scriptinggithub.com/contentauth/c2pa-python
c2pa-jsJavaScript (WASM)Browser-based reading and verificationgithub.com/contentauth/c2pa-js
c2pa-cCEmbedded systems, mobile, native appsgithub.com/contentauth/c2pa-c
c2patoolCLICommand-line reading, signing, verificationgithub.com/contentauth/c2patool

For most web applications, you'll use c2pa-node on the server and c2pa-js in the browser. For Python-based pipelines (ML workflows, batch processing), use c2pa-python. For embedded or mobile applications, c2pa-c provides the C bindings. All of these are wrappers around the core c2pa-rs Rust library, so behaviour is consistent across languages.

Reading Content Credentials

The simplest starting point is reading existing Content Credentials from a file. Here's how to do it with the Node.js SDK:

JavaScript (Node.js)
import { createC2pa } from 'c2pa-node';

const c2pa = createC2pa();

// Read Content Credentials from a file
const result = await c2pa.read('photo.jpg');

if (result) {
  // Get the active manifest (most recent)
  const manifest = result.active_manifest;
  console.log('Signed by:', manifest.signature_info);
  console.log('Assertions:', manifest.assertions);
  console.log('Ingredients:', manifest.ingredients);
} else {
  console.log('No Content Credentials found');
}

And the equivalent in Python:

Python
import c2pa

# Read Content Credentials from a file
reader = c2pa.Reader("photo.jpg")

if reader.manifest_store:
    manifest = reader.get_active_manifest()
    print(f"Title: {manifest.title}")
    print(f"Assertions: {manifest.assertions}")
    print(f"Signature: {manifest.signature_info}")
else:
    print("No Content Credentials found")

The read operation parses the manifest store, validates the cryptographic signatures, checks the trust chain, and returns structured data you can use in your application. If any signature is invalid or the content has been tampered with, the validation status will indicate this.

Signing Content Credentials

Signing - attaching new Content Credentials to a file - is more involved because it requires a signing certificate. Here's the basic flow with c2pa-node:

JavaScript (Node.js)
import { createC2pa, SigningAlgorithm } from 'c2pa-node';
import { readFileSync } from 'fs';

const c2pa = createC2pa();

// Define the manifest to attach
const manifest = {
  claim_generator: 'my-app/1.0',
  assertions: [
    {
      label: 'c2pa.actions',
      data: {
        actions: [
          { action: 'c2pa.created' }
        ]
      }
    },
    {
      label: 'stds.schema-org.CreativeWork',
      data: {
        '@type': 'CreativeWork',
        author: [{ '@type': 'Person', name: 'Jane Doe' }]
      }
    }
  ]
};

// Sign with your certificate
const result = await c2pa.sign({
  manifest,
  asset: { path: 'input.jpg' },
  output: { path: 'signed-output.jpg' },
  signer: {
    certificate: readFileSync('cert.pem'),
    privateKey: readFileSync('key.pem'),
    algorithm: SigningAlgorithm.ES256,
    tsaUrl: 'http://timestamp.digicert.com'
  }
});

The key elements here are the manifest definition (what assertions to attach), the asset (the file to sign), and the signer configuration (your certificate, private key, signing algorithm, and timestamp authority).

About signing certificates

For development and testing, you can generate a self-signed certificate. However, for production use, you need a certificate from a Certificate Authority (CA) that's on the C2PA Trust List. Self-signed credentials will verify structurally but won't be "trusted" by verification tools - they'll show a warning indicating the signer isn't recognised.

To get a production certificate, your product needs to go through the C2PA Conformance Programme (see below). This ensures that your implementation meets the specification's security requirements.

Certificates and trust

The C2PA trust model is built on X.509 certificates - the same PKI infrastructure that powers HTTPS. Here's how the chain works:

A Certificate Authority (CA) on the C2PA Trust List issues a Claim Signing Certificate to your product. This certificate identifies your application as a trusted C2PA signer. When your application signs a manifest, it uses this certificate. When a verifier checks the manifest, it validates the signature against the Trust List.

For development, you can create a self-signed certificate with OpenSSL:

Shell
# Generate a self-signed certificate for development
openssl req -x509 -newkey ec \
  -pkeyopt ec_paramgen_curve:P-256 \
  -keyout key.pem -out cert.pem \
  -days 365 -nodes \
  -subj "/CN=My App Development"

This will let you sign files and test your implementation. The signed Content Credentials will be structurally valid but won't chain to the C2PA Trust List - verification tools will mark them as untrusted. This is fine for development but not for production.

Developer updates
SDK releases, API changes, and implementation guidance for C2PA developers.

Supported file formats

C2PA Content Credentials can be embedded in the following formats as of specification version 2.3:

CategoryFormats
ImagesJPEG, PNG, WebP, TIFF, HEIF/HEIC, AVIF, GIF, SVG, DNG
VideoMP4, MOV, AVI, MKV
AudioMP3, WAV, FLAC, M4A
DocumentsPDF

The most robust support is for JPEG - it's the oldest and most tested implementation path. PNG and WebP are fully supported but see slightly less production usage. Video support is newer and was significantly expanded in version 2.3 with the addition of live video provenance.

For formats that don't support embedded metadata, the specification allows sidecar manifests - external files that reference the content via a hash binding. This approach works for any file format but requires the manifest and the content to be distributed together.

Validation and verification

When you read Content Credentials, the SDK automatically performs several validation checks:

Structural validation confirms the manifest conforms to the C2PA specification - correct data types, required fields present, valid CBOR encoding.

Hash validation computes a fresh hash of the content and compares it to the hash stored in the manifest. If they don't match, the content has been modified since signing.

Signature validation verifies the cryptographic signature against the signing certificate. If the signature is invalid, the manifest or its contents have been tampered with.

Trust validation checks whether the signing certificate chains to a root certificate on the C2PA Trust List. This determines whether the signer is "trusted" - an untrusted signer means the credentials are structurally valid but the signer's identity isn't verified by the C2PA ecosystem.

Timestamp validation checks the Time Stamp Authority (TSA) response to confirm when the signing occurred. This prevents backdating and ensures the certificate was valid at the time of signing.

The SDK returns detailed validation status for each of these checks, allowing your application to present appropriate information to users. A common pattern is to show a green checkmark for fully trusted and validated credentials, a yellow warning for valid but untrusted (self-signed) credentials, and a red alert for credentials that fail validation.

Architecture decisions

When integrating C2PA into your application, several architectural decisions need to be made early:

Client-side vs server-side signing. Signing requires access to a private key, which means it almost always happens server-side. The private key should never be exposed to client-side code. Reading and verification, however, can happen on either side - c2pa-js runs in the browser via WebAssembly and can verify Content Credentials without a server round-trip.

Synchronous vs asynchronous signing. For high-volume applications (e.g., signing every image uploaded to a platform), consider asynchronous signing via a queue. The cryptographic operations are fast (typically under 100ms per file), but the timestamp authority request adds network latency. Batch processing with a worker queue handles this gracefully.

Manifest storage strategy. For most applications, embedded manifests are simplest - the credentials travel with the file. However, if you're processing large volumes or want to minimise file size impact, remote manifests stored in a content-addressed store (keyed by content hash) provide more flexibility. The trade-off is that remote manifests require the storage service to be available for verification.

Ingredient handling. If your application modifies content that already has Content Credentials (e.g., a photo editor or a content management system), you should preserve the existing manifest as an "ingredient" in your new manifest. This maintains the provenance chain. The SDKs handle this automatically when you pass an input file that already contains credentials.

The Conformance Programme

To be listed on the C2PA Conforming Products List and receive a production signing certificate from a Trust List CA, your product must go through the C2PA Conformance Programme. This involves:

Technical evaluation - demonstrating that your implementation correctly follows the specification, including proper manifest generation, signing, and validation.

Security evaluation - showing that your implementation meets the C2PA's security requirements, including secure key storage, tamper-resistant signing environments, and proper certificate handling.

Legal onboarding - agreeing to the programme's terms, which include requirements around proper use of Content Credentials and responsible implementation.

The programme defines multiple Assurance Levels based on the security posture of your implementation. Higher assurance levels (e.g., hardware-backed signing) receive certificates that carry more weight in the trust model. A cloud-based signing service with HSM-backed keys will receive a higher assurance level than a software-only implementation.

The expression of interest form and programme details are available on the C2PA website. The process typically takes several weeks and involves technical review by the C2PA's administering authority.

Resources and community

Official specification: The full C2PA technical specification is published at spec.c2pa.org. This is the definitive reference for all manifest structures, assertion types, and validation procedures.

GitHub: All official SDKs and tools are published under the github.com/contentauth organisation. Issues, pull requests, and discussions are welcome.

Discord: The CAI maintains an active Discord server for developers implementing C2PA. This is the best place for implementation questions and community support.

Verify tool: The online verification tool at contentcredentials.org/verify is invaluable during development for checking your signed outputs.

Conformance Programme: Details on the programme, including the expression of interest form, are available at c2pa.org/conformance.

The C2PA ecosystem is still relatively young, which means developers implementing it now have an opportunity to shape how content authenticity works across the internet. The standard is open, the tools are free, and the community is active. If your application handles media in any form, C2PA support is worth investing in today.

This guide is maintained by the C2PA.ai editorial team. Last updated March 2026. Contact us with corrections or updates.

Related: What Is C2PA? The Complete Guide · C2PA Adoption Tracker · C2PA for Photographers