CodamAIDocs
Topicdone

Verify and read

The endpoints for final documents: read, list, verify. What the check result says, what is logged when reading, and what the chain does not prove.

Variants
document intactchain brokenbytes changedrevision erasedreading with read log

What this is about

A final document is kept at CRMS. Your application can read it again at any time, list the versions of a chain, and have CRMS check whether chain and bytes are still correct. For this there is a small group of endpoints under /crms/documents.

The endpoints

CallRole (default)Answer
GET /crms/documents?template=…&scope=…&reference=…crms-document-readerall revisions of the chain, oldest first
GET /crms/documents/{revision}crms-document-readerthe bytes, the description in headers
POST /crms/documents/{revision}/verifycrms-document-reader{ "ok": …, "problem": … }
POST /crms/documents/{revision}/legal-holdcrms-document-custodian204, see Retention
POST /crms/documents/{revision}/legal-hold/releasecrms-document-custodian204
POST /crms/documents/{revision}/erasecrms-document-eraser204
  • {revision} is a UUID in canonical form. Any other spelling is a violation on the field revision.
  • You set the roles with CODAMAI_CRMS_REST_DOCUMENT_ROLES_READ, _HOLD and _ERASE, each as a comma-separated list. One role from the list is enough, and an empty list admits nobody.
  • The role is checked before CRMS looks for the document. If it is missing: 403 document-access-denied.
  • You only see documents of your own tenant. A revision of another tenant does not exist for you: 404 document-not-found.

If CRMS runs as a separate service, crms-client offers the same calls through the same interface and forwards the user’s token. See The CRMS client.

Reading a document

Request
GET /crms/documents/7c1e…
Response
200 OK
Content-Type: application/pdf
Content-Disposition: inline; filename="audit-report.pdf"
X-Content-Type-Options: nosniff
Crms-Document-Revision: 7c1e…
Crms-Document-Number: 2
Crms-Document-Format: PDF
Crms-Document-Stored-At: 2026-10-17T09:12:44.123456Z
Crms-Document-Retain-Until: 2036-10-17T09:12:44.123456Z
Crms-Document-Legal-Hold: false
Crms-Document-Content-Hash: sha-256:3b1d…
Crms-Template-Key: audit-report
Crms-Template-Scope: TENANT
Crms-Template-Variant: de
Crms-Template-Revision: a2f0…
Crms-Template-Revision-Hash: sha-256:9f86…
(the bytes)

When reading, CRMS decrypts the bytes and compares them with the revision’s content hash. If they do not match, there is no document but 500 document-integrity-failed. An HTML document also gets Content-Security-Policy: sandbox, so that a script in it does not run in the name of your application.

CaseAnswer
the revision does not exist (for this tenant)404 document-not-found
the revision is erased410 document-erased
the bytes do not match the hash500 document-integrity-failed
the object is missing in the storage500 document-object-missing

Logging reads

With CODAMAI_CRMS_AUDIT_READS=true, CRMS writes every read of a final document as document-read with the reader into the journal. The default is false. A check through verify does not count as a read.

Verifying a document

POST /crms/documents/{revision}/verify
  1. CRMS
    Chain
    Does every entry of the whole document chain give its stored hash?
    ↳ no ok: false, document-chain-broken
  2. CRMS
    Erased?
    Does the revision still have bytes?
    ↳ no ok: true – a tombstone is intact if the chain is
  3. CRMS
    Decrypt
    Can the bytes be decrypted with their key?
    ↳ no ok: false, document-decryption-failed
  4. CRMS
    Content
    Do the bytes match the content hash?
    ↳ no ok: false, document-integrity-failed
  5. ok: true
Request
POST /crms/documents/7c1e…/verify
Response
{ "ok": false, "problem": "document-chain-broken" }

If everything is fine, problem is missing: { "ok": true }. A finding is a normal answer with 200, not an error. The keys are listed in Errors.

If the object is missing in the storage, the check reports document-object-missing.

Verifying templates

The chain of a template variant can be verified as well: POST /crms/variants/{variant}/verify. The answer is { "intact": true } or { "intact": false, "brokenAt": 4 } with the first position that does not match. More in Life cycle of a template.

What the chain does not prove

QuestionDoes the evidence show it?
Are the bytes unchanged since they were stored?yes, through the content hash and the chain
Which approved template revision was it rendered with?yes, through the template’s revision hash
Which data was it rendered with?yes, whoever holds the data compares it with the payload hash
Who stored, held or erased it, and when?yes, through user and time in the chain and the journal
Was the history recomputed consistently afterwards?yes, the anchor reveals it
Was the data correct?no, that is the responsibility of the application that sent it

Pitfalls

Next

Search