Asynchronous contracts
Recipe discovery
Section titled “Recipe discovery”Call authenticated GET /v1/recipes before submitting POST /v1/sign. Each entry returns:
- the stable
recipe_id; - its currently enabled immutable
version; - its customer-visible
capabilities, in execution order; - its
supported_media_types.
c2pa_signing means C2PA manifest creation and signing. The response deliberately leaves out
provider identities, algorithms, configuration, storage locations, and the internal recipe graph.
An operation that is not classified in the scope policy is denied by default.
Verification identifiers and polling
Section titled “Verification identifiers and polling”POST /v1/verifications accepts an immutable asset object identifier in object_id, also called
the asset_object_id, whose public form starts with aob_. The parent asset_id (ast_…) cannot
stand in for it. Unknown request fields are rejected, and validation responses never echo the
identifier you sent.
Verification is asynchronous. The create call returns HTTP 202 with a status snapshot. Poll
GET /v1/verifications/{verification_id} no more often than every 2 seconds, with bounded
exponential backoff for longer runs:
state |
Terminal | Field contract |
|---|---|---|
accepted |
No | result, evidence_id, completed_at, and failure_reason are absent/null. |
running |
No | Continue polling. A client timeout does not cancel the durable job. |
completed |
Yes | result, evidence_id, and completed_at are present. |
failed |
Yes | failure_reason and completed_at are present. |
Pick a client-side timeout that suits the calling workflow. If it expires, keep the
verification_id and resume polling later. Do not create a second verification just because the
caller stopped waiting.
A recovery-only result is not cryptographic validity. It means no C2PA manifest could be read from the asset, and a bounded soft-binding recovery found one unique candidate. Show it as recovery-only provenance and keep the reasons and recovery evidence that come with it.
When a manifest was read, what validation found about it is the status (for example
untrusted for an intact manifest from a signer that is not on the trust list), and a recovery
match, if any, is reported alongside it in result.recovery as supplementary evidence. Results
issued before 2026-09-29 (schema_version op.public-verify-result.v1) keep the status they
were issued with: under that version a unique recovery match outranked an expired or untrusted
manifest.
Published downloads
Section titled “Published downloads”A successful authenticated POST /v1/assets/{asset_id}/download response always includes both
byte_length and lowercase sha256 for the exact immutable published bytes. Use them to check
the downloaded body. The API also ties the download URL to one exact private storage version
without revealing its bucket, object key, or version identifier.
If the immutable byte facts are missing or inconsistent, the API fails closed with a reason-coded error and issues no partial download. The same applies to their publication and verification bindings.
