CodamAIDocs
Topicdone

The response format: data and meta

Every response has the same envelope. This page explains what is in data and meta for a single object, a list, the history and errors.

Variants
single object (SingleResponse)list (QueryResponse)history (AuditQueryResponse)errorvalidation error with violationscreated but not read backDELETE without bodyfile download

What this is about

Every response from CDMS has one of a few fixed shapes. If you know them, you can handle them in one place in the client.

The four shapes

Which response shape do I get?
RequestSuccess?Shape of the response
create, read, update, patch, rollbackyesSingleResponse: data is one object
queryyesQueryResponse: data is a list, meta holds the match counts
historyyesAuditQueryResponse: data is a list of revisions
deleteyesempty body, status 200
file downloadyesthe file itself, not JSON
anynoerror response, see below

Single object

SingleResponse – response to create, read, update, patch, rollback
Request
POST /api/rest/crm/customer/read/5a2b…
{ "response": ["name", "email"] }
Response 200
{
  "data": {
    "id": "5a2b…",
    "@type": "crm.customer",
    "_createdOn": "2026-09-21 10:12:00",
    "_updatedOn": null,
    "name": "Muster GmbH",
    "email": "info@muster.de",
    "address": null
  },
  "meta": { "error": false, "errorMessage": null, "notNull": false }
}
  • data holds the DTO. Requested fields have their value; fields that were not requested are null.
  • id, @type, _createdOn and _updatedOn are always included.
  • On a success response, meta is always error: false. The fields have no further meaning for the client.

List

QueryResponse – response to query
Request
POST /api/rest/crm/customer/query
{ "response": ["name"],
  "parameter": { "page": 1, "limit": 2 } }
Response 200
{
  "data": [
    { "id": "…", "name": "Beta AG", … },
    { "id": "…", "name": "Gamma KG", … }
  ],
  "meta": {
    "totalCount": 5,
    "currentPage": 1,
    "currentPageSize": 2,
    "currentLimit": 2,
    "error": false,
    "errorMessage": null
  }
}
meta fieldMeaning
totalCountnumber of all matches across all pages. With "meta": false in the request, nothing is counted
currentPagethe page returned, starting at 0
currentLimitthe requested page size
currentPageSizehow many objects are actually on this page

Page count in the client: Math.ceil(totalCount / currentLimit). No matches is not an error: data is then an empty list. More in Paging and match count.

History

AuditQueryResponse – response to history
Request
POST /api/rest/crm/customer/5a2b…/history
{ "response": ["name"] }
Response 200
{
  "data": [
    {
      "revision": { "id": "5a2b…", "name": "Muster GmbH", … },
      "revisionMeta": {
        "ref": 42,
        "ts": 1790000000000,
        "ip": "10.0.0.7",
        "useragent": "Mozilla/5.0 …",
        "username": "anna"
      },
      "revisionType": "MOD"
    }
  ],
  "meta": { "error": false, … }
}
FieldMeaning
revisionthe object as it looked after this change
revisionMeta.refrevision number, which you need for a rollback
revisionMeta.tstime in milliseconds since 1970
revisionMeta.ip, useragent, usernamewho made the change, from where
revisionTypeADD created, MOD changed, DEL deleted

The newest revision comes first. See Reading the history.

Errors

Errors have a flat shape of their own, without data:

Error response – here a validation
Request
POST /api/rest/crm/customer/create
{ "data": { "name": "" }, "response": ["id"] }
Response 422
{
  "error": "ApiValidationException",
  "messageKey": "validation-failed",
  "code": "422",
  "layer": "API",
  "violations": [
    { "field": "name",  "rule": "cannot-be-empty" },
    { "field": "email", "rule": "cannot-be-null" }
  ]
}
FieldMeaningIn the client
errorkind of errorfor logging
messageKeyfixed key, e.g. missing-permission|customer-readbranch on this, not on the text
messagereadable textfor humans only
codeHTTP status as textsame as the response status
layerlayer where the error occurredfor debugging
violationsvalidation errors only: all violations with field path and rulemap them to the form fields
idonly in the special case below–

What each code means is in Map of status codes. How violations get into the form is in Getting validation errors into the form.

The special case: created, but not read back

After a create, CDMS reads the object back for the response. In LENIENT mode, creating can succeed while only the read-back fails. You then get a response in error shape, but with status 200 and the id of the created object:

Response 200
{
  "error": "CreateSucceededReadFailedException",
  "messageKey": "CDMS_CREATE_SUCCEEDED_READ_FAILED",
  "code": "200",
  "layer": "system",
  "id": "5a2b…"
}
What the client should do
The object exists.
Read it again later using the id,
do NOT create it a second time.

See Create and read back: STRICT or LENIENT.

One handler for everything

How a client handles every response
  1. 1
    Client
    Status 2xx?
  2. 2
    Client
    yes, and messageKey is CDMS_CREATE_SUCCEEDED_READ_FAILED → created, remember the id, read later
  3. 3
    Client
    yes, otherwise → use data, for lists also meta
  4. 4
    Client
    no → evaluate messageKey; on 422 map the violations to the fields; on 401 renew the token and retry once
Sources in the code and the knowledge base
  • CDMS/cdms-commons – models/response: SingleResponse, QueryResponse, AuditQueryResponse, AuditRevision, AuditRevisionMeta, SingleMetaResponse, QueryMetaResponse
  • CDMS/cdms-rest-api – CdmsExceptionMapper
  • documentation/20-api/02-payloads.md (response formats), 06-fehler-und-statuscodes.md
Search