Developers

One API for C2PA validation. Billed once per report.

Send JPEG, PNG, WebP, MP3, WAV, M4A or MP4 to one authenticated endpoint and receive the hosted validator’s complete structured report, with its Evidence Unit charge in the same response. Every report identifies the exact validator build. Idempotency keys make retries safe: one key is never charged twice.

API access is included for developers  ·  seven hosted formats  ·  2 Evidence Units per completed report

From first file to production.

Free · no account

1. Verify a file free

Check a file in the browser, with no account. Free Verify checks JPG and PNG photos up to 1 MB for Content Credentials; it reports present — not evaluated, none detected, or not checked. Exact ChaosMark record matches are reported separately. Full validation is a separate, paid hosted evaluation.

Verify a file free

Paid account

2. Subscribe and upload

When online subscription is enabled, secure Stripe Checkout returns you to an account that accepts all seven formats in the browser. The account handles authentication, reports, usage and recovery without exposing an API key.

See plans

Optional API

3. Automate from your server

Developers may reveal a separate API key once from the paid account. One HTTP call per file sends raw bytes in and returns the report, Evidence Units and billing state.

API reference

Customers can validate without an API key.

A paid account includes drag-and-drop browser upload, the full findings, recent validation history, retained-report retrieval and subscription management. The browser session is bound to the account on the server; it never copies an API key into HTML, JavaScript, a cookie or a URL.

Subscribe and use the browser

The API remains available

Server integrations use the same validator, Evidence Unit ledger, idempotency rules and report custody through POST /v1/c2pa/validate. Browser and API requests do not create separate billing or validation systems.

Continue to the API reference

For software and AI agents

People subscribe through secure Stripe Checkout and upload files in the browser. Authorized software and AI agents use the API with a key issued to an accountable person or organization.

Who holds the account

A person or organization chooses the plan, accepts the Terms and pays through Stripe Checkout. They reveal the API key from their paid account and give it to the agent or automation they authorize, and they stay responsible for how it is used.

What an agent can do

Send a file to POST /v1/c2pa/validate, retry safely with the same idempotency key, and look up a report and its usage for up to 24 hours. Every call uses the same seven formats, limits and report as the browser.

Built-in limits

Each completed report uses 2 Evidence Units. When the plan's allowance or request limits are reached, requests are refused at 0 Evidence Units. There is no overage, so an agent cannot spend beyond the plan.

A plain-text summary for automated readers is at /llms.txt. Looking for something other than a monthly plan? Explore other options.

API reference

POST /v1/c2pa/validate. Raw body, not multipart. The bytes decide the format; the declared type must agree with them.

curl "$CHAOSMARK_API_BASE/v1/c2pa/validate" \
  -H "Authorization: Bearer $CHAOSMARK_API_KEY" \
  -H "Content-Type: image/jpeg" \
  -H "Idempotency-Key: photo-2026-09-29-0001" \
  --data-binary @photo.jpg

Request

  • Authorization: Bearer <key>
  • Content-Type: image/jpeg, image/png, image/webp, audio/mpeg, audio/wav, audio/mp4 or video/mp4
  • Idempotency-Key: required, 1–128 characters, letters, digits and . _ : -, starting with a letter or digit
  • Body: the file's bytes. PNG up to 1 MiB; the other hosted formats up to 16 MiB; uploaded within 30 seconds

Completed response (200)

  • status: completed, and report: the validator's full report
  • charged_eu: 2, billing_state: finalized
  • reservation_id and usage_event_id: the purchase and its usage record, for retrieval later
  • request_commitment and result_commitment: digests you can keep and check later
  • input_sha256: the digest of the bytes you sent; the bytes themselves are not kept
  • trust_material: digests of the trust lists the report was evaluated against
  • hosted_api_media and c2pa_validator_media: this endpoint's formats and the validator's, never mixed up
  • result_identity: the validator build that produced the report. For the hosted successor build, build_record.cpl_record_id is null and build_record.conformance_mapping is not-established: that build is not itself currently listed

Your API base URL is issued with your key. A completed report is billed whatever it finds, including invalid or untrusted credentials: you pay for the evaluation, not for a favourable answer. Refused input, unreadable containers and timeouts cost 0 Evidence Units, and the response says so in charged_eu and billing_state. If a failure on our side leaves the charge undetermined, billing_state says so until it is settled; check the final state by reservation_id.

Retries that never bill twice.

An idempotency key is bound to one request: the same key with the same bytes is the same request. Retry with the same key. A new key is new billable work, except that a new key for bytes already being bought under your organization is refused at 0 Evidence Units, and so is one for bytes bought recently unless you confirm a repeat purchase.

AnswerStatusWhat it meansWhat to do
No responseNetwork error or timeoutYou cannot tell whether the request ran.Retry with the same key.
Still running409 in_flightThis key is still being evaluated.Wait, then retry with the same key.
Busy429 validation-capacity-exhausted, 503 validation-service-unavailable, 503 validation-report-custody-unavailableBusy or unavailable. Nothing was charged.Back off, then retry with the same key.
Recovered200 with replayed: trueThis key already completed and was charged once. You get the same report again: nothing ran again and nothing more was charged.Nothing: this is your original result.
Recovery paused503 validation-report-recovery-unavailableCharged once already; the kept report could not be read just now.Retry with the same key. It never charges again.
Already done410 validation-report-expired, or 409 already_finalized when the report's state cannot be classifiedThis key completed and was charged once, and its report is no longer kept (the keeping period has ended).Do not retry. The request_commitment matches your first response. A new key is a new, separately charged request.
Not kept503 validation-report-not-retainedThe validation ran, but its report could not be kept, so it was not sold: nothing was charged and nothing will be. This key is closed.Send a new key to try again.
Released409 already_releasedAn earlier request with this key ended without a charge.Send a new key if you want a new evaluation.
Same bytes, open409 purchase_in_progressThese bytes are already being bought under another key in your organization. Nothing was charged and nothing ran. Confirming a repeat purchase does not apply while it is open.Wait, and retry with that key. If the earlier purchase is your account's, prior_reservation_id names it; otherwise it is null.
Same bytes, recent409 repeat_purchase_requires_confirmationThese bytes were bought under another key and that report can still be retrieved. Nothing was charged.Retrieve the earlier report (by prior_reservation_id when it is your account's), or send ChaosMark-Repeat-Purchase: confirm to confirm a repeat purchase.
Key conflict409 idempotency_conflictThis key was already used for different bytes.Use a new key for a different file.
Undetermined409 reconciliation_required, 503 validation-settlement-unconfirmedBilling is undetermined; a person reconciles it.Do not retry. Contact us with the reservation_id.
Budget used429 attempt-budget-exhaustedYour request budget is used up.Do not retry until your budget resets.
Day used429 daily-attempt-budget-exhausted, 429 daily-evidence-unit-budget-exhaustedYour organization has used this UTC day's request or Evidence Unit budget. Nothing was charged. Each finished report that is still kept can be read once more after a request-budget refusal.Wait for the time in Retry-After, the next UTC midnight, then retry with the same key.

Look up a paid validation.

By the reservation_id on the response, or by your idempotency key if the response was lost. Lookups read only: they cost 0 Evidence Units and run nothing. Each lookup still counts as one request toward your plan's request limits.

GET /v1/c2pa/validations/{reservation_id}

or GET /v1/c2pa/validations/by-idempotency-key/{idempotency_key}

  • Billing state, and charged_eu only once the charge is confirmed
  • Both commitments, and the report while it is kept
  • report_status: available, expired, not_retained, not_applicable, or integrity_failure (charged; ChaosMark reconciles it)

GET /v1/usage/reservations/{reservation_id}

  • The usage record: period, usage_event_id, quoted and confirmed Evidence Units
  • Reservation state, reason code and reconciliation status
  • Usage comes from ChaosMark's own ledger; your invoice covers the plan period, not each validation

A paid report is available for recovery for up to 24 hours after the charge, so a lost response can still be retrieved; after that, the billing record and the commitments remain. The file you send is not kept. An unknown reservation and another account's get the same 404.

Errors

Every refusal has a status and a fixed reason string, and says whether anything was charged.

HTTPReasonsCharged
400content-type-required, content-length-malformed, idempotency-key-required, idempotency-key-malformed, asset-empty0 Evidence Units
401credential-not-accepted0 Evidence Units
404reservation-not-found (lookups only)0 Evidence Units
402no-active-contract, insufficient-evidence-units, operation-not-entitled, outside-contract-period, payment-not-authorized0 Evidence Units
408asset-upload-too-slow0 Evidence Units
413content-length-exceeds-limit, asset-exceeds-limit0 Evidence Units
415content-type-not-supported-by-hosted-api, asset-media-outside-hosted-api-scope (a validator format this endpoint does not accept yet), asset-media-not-recognised, asset-media-disagrees-with-declared-type, asset-media-disagrees-with-filename, asset-media-ambiguous (the bytes read as more than one format)0 Evidence Units
422asset-container-unreadable, asset-exceeds-validator-bound (the file holds a Manifest Store larger than the validator’s resource limits; never reported as “no manifest”), remote-manifest-not-retrieved (the file points to a remote manifest, which is not fetched), asset-media-outside-hosted-api-scope (an MP4 or M4A whose hash binding is a Merkle tree, which this endpoint does not evaluate), validation-report-exceeds-limit0 Evidence Units
429attempt-budget-exhausted, daily-attempt-budget-exhausted, daily-evidence-unit-budget-exhausted, validation-capacity-exhausted, credential-lookups-rate-limited0 Evidence Units
500, 504validation-failed, validation-timed-out0 Evidence Units, when billing_state is not_billable
503validation-service-unavailable, validation-paid-route-stopped, validation-paid-schema-unavailable, validation-cost-envelope-exceeded, validation-capacity-lease-lost, validation-report-custody-unavailable, validation-report-not-retained0 Evidence Units
503validation-worker-unsettled, validation-settlement-unconfirmed0 Evidence Units when billing_state is not_billable; otherwise undetermined until a person reconciles it

The 409, 410 and recovery answers are in the retry table above. A request beyond your plan's allowance is refused, never billed as overage. Formats: what each format supports today.

Your account, key and plan.

How browser access and developer access start, what limits apply, and what happens at the end of each monthly period.

Getting access

You agree to the Terms of Service and Privacy Policy and pay for the first monthly period. A signed paid-invoice confirmation activates browser validation. The account can create a separate recovery code for restoring browser access after its session expires.

Developers may reveal the first API key once from the account. It is shown once; ChaosMark keeps only a digest of it and cannot show it again. Browser customers never need to reveal or use the key.

Keeping it secret

Keys begin with cmk_k_. Send the key only in the Authorization: Bearer header, from your server. Never put it in browser or mobile app code. A missing, unknown or revoked key gets the same 401 credential-not-accepted, and costs 0 Evidence Units.

If a developer key is lost, email us (never the key itself): a person revokes it and issues a new one. Browser access continues without it.

Limits

Each plan has a number of validations that can run at once and a number of requests per clock minute; every plan has a daily request limit, and catalog-only Scale also has a daily Evidence Unit limit. Compare the limits. Each authenticated validation request and each lookup counts. A refused request is answered 429 and costs 0 Evidence Units; the retry table above says when to try again.

Each monthly period

Each paid period starts with its plan's Evidence Units. Unused Evidence Units do not carry over, and no overage is billed: once the allowance is used, validations are refused with 402 insufficient-evidence-units until the next period.

Renewal and ending a plan

A renewed plan keeps the same browser account and developer key. If a period ends before the next one is paid, new validations are refused with 402 outside-contract-period and nothing is charged. Earlier retained reports remain available under their retention rules. Request cancellation from the paid account; service continues through the period already paid for unless it is suspended under the Terms. For a sales-assisted plan, email us.

Refunds and disputes

If a payment is not authorized, fully refunded, or a dispute is lost, we may suspend the plan. While it is suspended, validations are refused with 402 payment-not-authorized, or 401 if the key is revoked, and cost 0 Evidence Units.

Clients and integrations

Next

Python and TypeScript clients

Thin clients over this endpoint are next: key configuration, idempotency keys, typed results and errors, the retry rules above, recovery of a lost response with the same key, and the two lookups. No SDK package is published yet, and there is no self-service key-issuance endpoint; until the clients ship, any HTTP client works, as in the example.

Enterprise evaluation

Agent Evidence

Evidence of what an agent was authorized to do and what the destination shows it did, from MCP, OpenTelemetry / OTLP, A2A and compatible HTTP sources.

Agent Evidence integrations

Enterprise evaluation

Recognition

Whether a JPEG or PNG stripped of its credentials is still exactly a file you registered, by its bytes or by its decoded pixels.

How recognition answers

Public resources

Public

Published verification keys

The public keys ChaosMark records are signed with, for checking a record with standard tooling.

View the published keys

Public

Result vocabulary

Every result Verify can return, and what each one does and does not mean.

Read the result vocabulary

Public

Labelled sample result

A worked example of a result, so you know what to expect before integrating.

View the sample result

Public

C2PA Conformant Validator Product

The listed product’s recorded scope is JPEG, PNG, WebP, MP4, MP3, WAV and M4A under C2PA Specification 2.2. Hosted reports name their exact build so reviewers can check the applicable product and build details.

View C2PA scope

Windows 11 x64

Local Agent for Windows

ChaosMark Local Agent 0.2.2 is available for Windows 11 x64. It protects and verifies files on your own computer; it is a desktop application, not a developer library.

Download for Windows

Enterprise engagement

Technical evaluation

Agree the evidence you need, the keys you trust, what data may leave your systems, and how success is tested.

Email for a technical evaluation · Explore Enterprise

Treat each signature, each file fingerprint, each key or certificate you supplied, and any missing evidence as a separate finding. Do not infer truth, identity, authorization, correctness, or completeness. Read the trust boundary.