What this is about
When an application renders a report with mode: FINAL, CRMS returns the document to it and keeps it as well. It becomes a revision: a version that never changes, in a document chain. A document chain collects all final versions of a report about the same business object, for example all inspection reports for the audit audit-4711.
How FINAL differs from PREVIEW and TRANSIENT is described in The three modes.
What defines a chain
A chain is defined by four values. CRMS computes the chain’s id from them. The same four values always give the same chain.
| Value | Where it comes from | Example |
|---|---|---|
| Owner | the tenant from the token. Without a tenant, the system | acme |
| Template key | template from the request | audit-report |
| Scope | the scope of the template edition that was actually rendered | TENANT |
| Reference | reference from the request: the id of the business object in your application | audit-4711 |
For CRMS the reference is only text. CRMS does not look into it. It is required for FINAL, 1 to 255 characters long, without blanks at the start or end and without control characters. If it is missing, CRMS refuses the request with a violation on the field reference.
POST /crms/render
{
"template": "audit-report",
"format": "PDF",
"mode": "FINAL",
"reference": "audit-4711", ← names the chain
"locale": "de-DE",
"data": { "customer": { "name": "ACME" } }
}200 OK
Content-Type: application/pdf
Crms-Document-Revision: 7c1e… ← the new revision
Crms-Template-Key: audit-report
Crms-Template-Scope: TENANT
Crms-Template-Revision-Hash: sha-256:9f86…
(the document's bytes)What happens when it is stored
-
1Client→CRMSsends a render request with
mode: FINALandreference -
2CRMSchecks whether this installation stores final documents
-
3CRMSno → 409
document-revisions-disabled -
4CRMSrenders the document. A PDF then gets the seal if the installation seals
-
5CRMScreates a key just for this document and encrypts the bytes with it
-
6CRMS→File storagestores the encrypted bytes locked until the retention ends
-
7CRMS→Databaseappends the revision to the chain and writes an entry
document-storedinto the journal -
8CRMS→Clientreturns the documentResult: The document is stored. The header
Crms-Document-Revisionnames the revision
The bytes only come back once they are stored. So there can be no final document that your application holds and CRMS does not.
The journal is the second record next to the chain, one per tenant. More in The two hash chains.
What a revision records
A revision carries everything you need later to show how the document came about:
| Item | What for |
|---|---|
| number in the chain | position, from 1, without gaps |
| template key, scope, language variant, template revision and its hash | binds the document to exactly one approved version of the template |
| format and PDF profile | what was produced |
| content hash (SHA-256 of the bytes) and size | shows that the bytes are unchanged |
| payload hash | shows which data it was rendered with |
| whether the payload is kept encrypted | see below |
| id of the document key | the key the bytes are encrypted with |
| object key and version in the storage | where the bytes are |
retainUntil | until when the document is kept |
| tenant, user, time (UTC, to the microsecond) | who produced it and when |
| language and time zone | how numbers and dates were formatted |
| previous hash and own hash | the chaining |
A hash is a short fingerprint of data. If a single bit changes, the whole hash changes. CRMS always writes hashes with the algorithm in front, for example sha-256:9f86….
The payload
The payload is the data the document was rendered with. Before hashing, CRMS brings it into a fixed form: canonical JSON, integers stay numbers, decimals and dates become text. So the same data always gives the same hash.
- The payload hash is always stored.
- The payload itself is kept, encrypted with the same document key, as long as
CODAMAI_CRMS_DOCUMENT_STORE_PAYLOADis on (defaulttrue).
When FINAL is accepted
| Document revisions on? | Reference given? | Attachments included? | What happens |
|---|---|---|---|
| no | – | – | 409 document-revisions-disabled |
| yes | no | – | 422, violation on the field reference |
| yes | yes | yes | 422 attachments-not-for-final |
| yes | yes | no | the document is stored and returned |
Document revisions are on by default (CODAMAI_CRMS_DOCUMENT_REVISIONS=true). Then the installation needs a retention period and a storage, or it does not start. See Retention and Storage on WORM.
Reading the revisions of a chain
GET /crms/documents?template=audit-report&scope=TENANT&reference=audit-4711[
{
"revision": "7c1e…",
"number": 1, ← oldest first
"format": "PDF",
"template": "audit-report",
"scope": "TENANT",
"variant": "de",
"templateRevision": "a2f0…",
"templateRevisionHash": "sha-256:9f86…",
"storedAt": "2026-10-17T09:12:44.123456Z",
"retainUntil": "2036-10-17T09:12:44.123456Z",
"legalHold": false,
"erased": false,
"contentHash": "sha-256:3b1d…"
}
]All endpoints for documents and who may call them are listed in Verify and read.