Learn

Proof-backed records at scale

Hash artifacts locally, register the hashes with Cryptowerk, store the retrieval ID, then verify proof when needed.

artifactsha256/registerretrievalIdverify later
Enterprise features including API key issuance endpoint, QR/PDF seals, secret seals, additional blockchain sources are account-level capabilities. Contact us for details and activation.

Quickstart

Move from first working integration to first working proof-backed record flow in four steps. Assume you already have a valid X-API-Key header. Hash locally first. Only hashes are submitted to Cryptowerk.

01

Add a proof-backed record step where the run already completes

Hash artifacts locally inside the workflows you already run, then call Cryptowerk from that step.

See details

Add proof-backed record creation at the point where your run already completes. That can be a gateway middleware step or a worker hook. Use the X-API-Key header you already issued on the key page.

bash
printf '{"eventType":"tool_call","tool":"search","input":"weather sf","output":"sunny"}' | shasum -a 256
Hash the exact artifact payload locally first, then send only the resulting SHA-256 to /register.
02

Register hashes

Submit SHA-256 hashes to /register with optional lookup info, callback, and mode settings.

See details

/register accepts a comma-separated hashes parameter plus optional lookupInfo, optional per-hash lookupInfos, optional callback, and optional mode for individualSeal or bulkSeal.

Secret seals use the register parameter publiclyRetrievable. The playground defaults this to true. Contact us if you want private retrieval settings for your account.
You can also activate additional blockchain sources for your account. Contact us to enable Bitcoin, Ethereum mainnet, and other sources.
bash
curl -X POST \
  'https://aiagent.cryptowerk.com/platform/API/v8/register?hashes=181210f8f9c779c26da1d9b2075bde0127302ee0e3fca38c9a83f5b1dd8e5d3b' \
  -H 'X-API-Key: CK....g= CR....9Q='
json
{
  "documents": [
    {
      "retrievalId": "ri315539637d780a5f2d7f7333b7ad916c7fae79ac20c34c8d37a1ed5a0e9f3f736"
    }
  ]
}
Store documents[i].retrievalId with the business event or trace that produced the hash so the proof-backed record stays attached to the originating run.
When multiple hashes are submitted, preserve order. lookupInfos maps 1:1 to hashes.

Callbacks

Enterprise

Instead of polling, pass a callback parameter to /register and Cryptowerk will POST the completed verification payload when available. Retries run every 5 minutes for up to 12 hours, and the callback user agent is Cryptowerk Callback v1.

Callback specifications can target URL, email, MQTT. Use URL callbacks for webhooks, email callbacks for simple delivery testing, and MQTT when you want registration events published into an existing broker flow.

Callback delivery is blockchain-paced. Ethereum may appear in a callback within seconds, while Bitcoin can take much longer. Until all requested chains are done, expect hasBeenInsertedIntoAllRequestedBlockchains=false.
Callbacks may batch multiple registrations together. This is intentional for throughput. If you need to force separate callback deliveries for the same endpoint, vary the callback URL with a throwaway query value such as ?keepthemapart=1.
url callback
callback=http:jsonplain:https://some.site.com/5d5803df-0e8b-4779-80e8;stampFormat:JSON
email callback
callback=email:jsonplain:callbacktest@mailinator.com
mqtt callback
callback=mqtt:tcp://mqttcc1.cryptowerk.com:1883;test/topic2;{myCustomId:'someid1'}
  • URL callbacks use http plus jsonplain or jsonformenc, followed by the target URL.
  • Add ;stampFormat:JSON or ;stampFormat:STREAM to choose the returned seal format.
  • Add ;keepQuery:true if you want query parameters preserved in the outgoing POST URL.
  • Add ;hashSequenceKnown:true when bulk seal callbacks can omit the original hash list.
  • MQTT callbacks use mqtt, then broker endpoint, topic, and a JSON template for your internal reference.
URL example: http:jsonformenc:http://yetanotherwebhook.com/14nve;stampFormat:JSON
Query-preserving example: http:jsonplain:https://some.site.com/5d5803df-0e8b-4779-80e8?myparameter=somevalue;keepQuery:true
Separation example: http:jsonplain:${webhook}?keepthemapart=1 and http:jsonplain:${webhook}?keepthemapart=2
hashSequenceKnown:true is useful with bulk seals because the callback payload can omit the original hash list.

Bulk mode

Enterprise

Use bulk sealing when throughput matters more than one completed proof payload per hash.

  • mode=individualSeal returns one seal per submitted hash.
  • mode=bulkSeal is better for high-volume systems.
  • Bulk mode saves space and improves throughput.
  • If you use bulk mode, preserve the original hash order locally.
03

Store the retrieval ID

Persist retrievalId with the execution event, trace, or business record that produced the hash.

See details

Persist retrievalId with the execution event, trace, or business record that produced the hash. That gives you a stable join key for later proof-backed record retrieval and proof verification.

FieldWhy it matters
documents[].retrievalIdPrimary lookup key for later proof-backed record lookup and proof retrieval.
seal.isCompleteReady check for proof availability.
seal.proofs[]Proof payload returned with the completed seal.
seal.blockchainRegistrations[]Blockchain anchor records for proof verification workflows.
documentInfo.submittedAtSubmission timestamp for the original execution event registration.
lookupInfoBusiness-side join key that links the proof-backed record back to the originating execution event or trace.

Get the seal

getseal is the retrieval endpoint for a previously returned retrievalId. Use it to retrieve the current proof-backed record state and completed proof data. It can also take multiple retrieval IDs.

HTML certificate: https://developers.cryptowerk.com/platform/portal/CertificateDownload?mode=html&retrievalId=<retrievalId>
PDF certificate: https://developers.cryptowerk.com/platform/portal/CertificateDownload?mode=pdf&retrievalId=<retrievalId>
bash
curl -X POST \
  'https://aiagent.cryptowerk.com/platform/API/v8/getseal?retrievalId=ri315539637d780a5f2d7f7333b7ad916c7fae79ac20c34c8d37a1ed5a0e9f3f736' \
  -H 'X-API-Key: CK....g= CR....9Q='
Treat seal.isComplete as the point when cryptographic proof is ready. Many proofs can come back in one seal. A proof for each source of truth is included in seal.proofs[], and each blockchain registration is included in seal.blockchainRegistrations[].
04

Verify proof

Use getseal or callback delivery to retrieve proof verification data, then use verifyseal when you need an explicit check.

See details

Use verifyseal when you want Cryptowerk to check one or more document hashes against one or more previously issued seals. You can also verify independently with your own tooling if you do not want to rely on the hosted verification service.

query
POST /verifyseal?verifyDocHashes=<sha256-a>,<sha256-b>&seals=<seal-a>,<seal-b>&provideInstructions=true
  • verifyDocHashes is a comma-separated list of hex- or base64-encoded hashes to verify.
  • seals contains the previously issued seal payloads to check those hashes against, and it must be a JSON array rather than a single object.
  • provideInstructions=true adds extra verification guidance to the response when you want it.
If you send JSON to verifyseal, include Content-Type: application/json.
json verify
{
  "provideInstructions": true,
  "verifyDocHashes": [
    "1111111111111111111111111111111111111111111111111111111111111111"
  ],
  "seals": [[
    {
      "bundleMethod": "BALANCED_MERKLE_TREE",
      "operations": [
        {
          "opcode": "DOCUMENTINFO",
          "lookupInfo": "17",
          "submittedAt": 1564454366050
        },
        {
          "opcode": "BLOCKCHAIN",
          "blockchainGeneralName": "Ethereum",
          "instanceName": "4",
          "blockChainId": "0x6a98749ff3eca810881b842e09cedfcabc478a6994661d1e534b6f31299bfe5b",
          "insertedIntoBlockchainAt": 1564454401831
        },
        {
          "opcode": "DOC_SHA256",
          "docHash": "1111111111111111111111111111111111111111111111111111111111111111"
        },
        {
          "opcode": "ANCHOR_SHA256",
          "hash": "a77bb697d9d9acb10cbd8703426b977efa92b09d83ab676a2d4a7353c06fb8fb"
        }
      ],
      "version": 7
    }
  ]]
}
url-encoded verify
curl -sS --header "X-ApiKey: $apiKey $apiCred" --data "provideInstructions=true&verifyDocHashes=1111111111111111111111111111111111111111111111111111111111111111&seals=$(urlEncode "$(jq --raw-output </tmp/verify.json '.documents[0].seals[0]')")" $server/API/v8/verifyseal | jq
Use getseal when you want to retrieve proof-backed record state and returned proof data.
Use verifyseal when you want a convenience proof verification step against an existing seal.
You can also verify independently without Cryptowerk. The essential flow is: hash the original document, follow the seal operations to recompute the anchor, and confirm that anchor in an independent blockchain explorer or your own verifier tooling.

Try it live

Generate a SHA-256 hash in the browser, register it, fetch the seal, and verify it without copying values between steps.

Recommended flow: generate the hash in your own system, call /register, store documents[].retrievalId, then retrieve the completed seal later with /getseal or callback delivery.
When submitting multiple hashes in a single register call, preserve order locally.

Open the wizard when you want to walk through the exact happy path with your own values.

The outputs from each step feed the next one automatically.

cURL commands

Copy this block when you want to load the main cURL conventions, helper setup, endpoint usage, callback formats, and enterprise notes into an LLM in one shot.