Skip to content

Workflow templates

llms.txtAsk agent

A workflow template is a named, saved sign request. You build it from blocks in the console’s Workflows builder or through the API, and reuse it by sending template_id on POST /v1/sign. The server derives the sign fields from the blocks, so a template can never hold a combination POST /v1/sign would refuse.

Blocks run in one fixed order. upload and sign are required, and each block appears at most once.

Order type Params Becomes on the sign request
1 upload none A step you run first (POST /v1/uploads).
2 watermark algorithm, strength (both optional) watermark: true, watermark_algorithm, watermark_strength
3 fingerprint algorithms (optional) fingerprint: true, fingerprint_algorithms
4 ai_mark declaration (the ai_declaration object) ai_declaration
5 cawg_identity credential_id identity
6 sign creator_id, mode (both optional) creator_id, mode
7 verify none A step you run after the job (POST /v1/verifications).
8 webhook endpoint_id (optional, whe_…) Your webhook configuration for the job’s events.
9 disclosure_event kind, jurisdiction A step you run (POST /v1/disclosures/events).

Without a watermark block the template sends watermark: false, and likewise for fingerprint. Upload, verify, webhook and disclosure-event blocks describe steps your integration runs around the sign call; they are saved so the console and your code agree on the whole workflow.

POST /v1/workflow-templates (scope workflow_templates:write, with an Idempotency-Key header):

Terminal window
curl -sS -X POST "$OP_API_BASE_URL/v1/workflow-templates" \
-H "Authorization: Bearer $OP_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"name": "Generated images",
"description": "AI mark, fingerprints, verify",
"blocks": [
{ "type": "upload" },
{ "type": "fingerprint" },
{ "type": "ai_mark", "declaration": {
"digital_source_type": "trainedAlgorithmicMedia",
"software_agent_name": "Studio Nova Imagine" } },
{ "type": "sign" },
{ "type": "verify" }
]
}'

The 201 answer has the template_id (wft_…), a version, and the read-only sign_request the blocks become:

{
"schema_version": "op.workflow-template.v1",
"template_id": "wft_…",
"name": "Generated images",
"version": 1,
"sign_request": {
"watermark": false,
"fingerprint": true,
"ai_declaration": {
"digital_source_type": "trainedAlgorithmicMedia",
"software_agent_name": "Studio Nova Imagine"
}
}
}

List, read, replace and delete with GET /v1/workflow-templates, GET, PUT and DELETE /v1/workflow-templates/{template_id}. Reading needs workflow_templates:read. PUT replaces the whole template and needs the expected_version you last read. Deleting a template never changes a job it already admitted. An account can keep up to 100 templates, and names are unique within it.

{ "asset_id": "ast_…", "template_id": "wft_…" }

Every field the request itself sends wins over the template’s, even an explicit null. Objects such as ai_declaration and identity are replaced whole, never merged field by field. So {"asset_id": "ast_…", "template_id": "wft_…", "fingerprint": false} runs the template without fingerprints.

Template Status code detail_code
A watermark block together with an ai_mark block 422 WORKFLOW_TEMPLATE_INVALID AI_DECLARATION_REQUIRES_SIGN_ONLY
A cawg_identity block while no identity credential is enrolled 422 WORKFLOW_TEMPLATE_INVALID IDENTITY_CREDENTIAL_NOT_ENROLLED
Blocks out of order, repeated, or without upload and sign 422 WORKFLOW_TEMPLATE_INVALID
A duplicate name, or a stale expected_version 409 WORKFLOW_TEMPLATE_CONFLICT
template_id unknown or deleted, on a template route or the sign 404 WORKFLOW_TEMPLATE_NOT_FOUND

The console shows the same reasons on the disabled control, for example “AI-generated mark needs a sign-only call (C2PA claim plan)” and “Blocks run in this order: Upload, Watermark, Fingerprint, AI mark, CAWG identity, Sign, Verify, Webhook, Disclosure event”.

The console offers starters for the jurisdictions in the disclosure policy. None combines a watermark with the AI mark; where a jurisdiction allows either signal, there are two variants. Each names the marking check preset it is meant to pass.

Starter Blocks Marking preset
EU AI Act Art. 50: AI mark (sign-only) upload, fingerprint, ai_mark, sign, verify, disclosure_event (visible_label_applied, EU) eu_ai_act_art50
EU AI Act Art. 50: watermark + fingerprint upload, watermark, fingerprint, sign, verify, disclosure_event (visible_label_applied, EU) eu_ai_act_art50
California SB 942 / AB 853 upload, fingerprint, ai_mark, sign, verify us_ca_sb942
China labelling: AI mark (sign-only) upload, fingerprint, ai_mark, sign, verify cn_labeling_measures
China labelling: watermark + fingerprint upload, watermark, fingerprint, sign, verify none: the China preset requires the AI declaration
Korea AI Framework Act: AI mark (sign-only) upload, fingerprint, ai_mark, sign, verify kr_ai_framework_act
Korea AI Framework Act: watermark + fingerprint upload, watermark, fingerprint, sign, verify kr_ai_framework_act
India synthetic information upload, fingerprint, ai_mark, sign, verify in_synthetic_information

The starters are drafts pending legal review, like the presets they target.