CodamAIDocs
Topicdone

The payload and its check

What the payload may hold: at most two levels, only plain values. How CRMS checks the fields a template declares, and how violations come back with field path and rule key.

Variants
plain value, list of valuesobject with one levellist of objectstoo deep → depth-exceededdeclared field missing, wrong type, no list, no objecttoo large → payload-too-large

What this is about

The payload is the data a template inserts into the document: customer name, line items, date. Your application puts it together. CRMS does not calculate, loads nothing and follows no references. It only inserts what you send.

That is why CRMS checks the payload before the template sees it. There are two checks:

  1. The structure, for every payload: at most two levels and only plain values.
  2. The declared fields: a template can state which fields it expects, with type and whether they are required. CRMS checks the payload against these declarations.

A valid payload

{
  "title": "Inspection hall 3",
  "approved": true,
  "tags": ["fire safety", "escape routes"],
  "customer": { "name": "ACME", "city": "Cologne", "phones": ["0221 1234"] },
  "items": [
    { "label": "Fire extinguisher checked", "amount": 480.00 },
    { "label": "Emergency exit clear", "amount": 120.50 }
  ],
  "due": "2026-10-17"
}
ValueFormLevels
title, approved, dueplain value1
tagslist of plain values1
customerobject with plain values or lists of plain values2
itemslist of objects with plain values or lists of plain values2

Plain values are text, numbers, true/false, dates and points in time. null is allowed everywhere. Embedded, you may also send Java date values: LocalDate, OffsetDateTime, ZonedDateTime, Instant. Over JSON, dates come as ISO text, see below.

Arbitrary Java objects are not allowed. An object would bring its methods into the template, and that is exactly what the sandbox is meant to prevent.

The structure rules

Where is the value?What is it?Result
topplain value or nullallowed
toplist of plain valuesallowed
topobjectallowed, its values are checked on level 2
toplist of objectsallowed, each object is checked on level 2
toplist of listsdepth-exceeded
level 2plain value or list of plain valuesallowed
level 2object or list with objects or listsdepth-exceeded
–other object or infinite numbervalue-type-unsupported
level 2key empty or not textkey-invalid

Before anything else, CRMS estimates the size of the payload. If it is larger than the installation’s limit (default 5 MiB, CODAMAI_CRMS_PAYLOAD_MAX_BYTES), only one violation comes back: field payload, rule payload-too-large|<limit>. The limit also applies to an SVG in the payload.

The declared fields

A revision of a template can declare its fields. Each declaration has four parts:

PartMeaningExample
pathwhere the field sits: a name, object.name or list[].name. At most two levels, only the first may be a list of objectscustomer.name, items[].amount
typeSTRING, NUMBER, BOOLEAN, DATE or DATETIMENUMBER
requiredwhether the field must be present and not nulltrue
listwhether the field is a list of values of this typefalse

How you declare fields in a template is described in How a template is built. For the check:

  • Undeclared values are allowed. A template may use more than it declares. Only the structure rules apply to them.
  • DATE matches a date or ISO text like "2026-10-17".
  • DATETIME matches a point in time or ISO text with a time zone offset, for example "2026-10-17T08:30:00+02:00" or "…Z". Without an offset it is a violation.
  • NUMBER matches any number, not text like "480".
  • For items[].amount, CRMS checks every element of the list on its own.
RuleMeaning
requireda required field is missing or null
type|string, type|number, type|boolean, type|date, type|datetimethe value does not have the declared type
list-expecteda declared list, or list of objects, is not a list
object-expecteda declared object, or a list element, is not an object

How violations come back

CRMS collects all violations and answers once: 422 with the key payload-rejected and the list violations. Each violation names the path of the value and a rule. A value from your request is never sent back.

Request (the template declares items[].amount as NUMBER, due as DATE)
POST /crms/render
{
  "template": "audit-report", "format": "PDF", "mode": "PREVIEW",
  "data": {
    "items": [
      { "label": "Fire extinguisher", "amount": "480" },
      { "label": "Emergency exit", "amount": 120.5,
        "detail": { "note": "too deep" } }
    ],
    "due": "17.10.2026"
  }
}
Response
HTTP 422
{
  "messageKey": "payload-rejected",
  "code": "422",
  "layer": "crms",
  "violations": [
    { "field": "items[1].detail", "rule": "depth-exceeded" },
    { "field": "items[0].amount", "rule": "type|number" },
    { "field": "due", "rule": "type|date" }
  ]
}

The structure violations come before the violations of declared fields. Your frontend translates the rule keys, see Errors and message keys. You can also check a payload without rendering, with POST /crms/render/validate, see The render request.

What the template sees afterwards

The template gets a copy of the checked payload. CRMS turns every field declared as DATE or DATETIME into a real date value, even if it came as ISO text. So the template can format it in the document’s language and time zone. A calendar date counts as midnight in the document’s time zone. More in Language and time zone.

Pitfalls

Next

Search