Errors

Use the HTTP status first. Bodies are not a single envelope: some routes return MessageException, others a validation array.

HTTP Meaning
400 Validation or illegal state
401 Missing, expired or retired Token (a later login by the same user retires it)
403 Authenticated, but not allowed for that branch or case
404 Unknown application or applicant. Also used for invalid login credentials.
406 Payload does not meet submit-time rules
500 Unhandled server error

MessageException

{
  "Translations": [
    { "XmlLang": "", "Text": "Application 0008675 does not exist!" }
  ]
}

Typical 400/403/404/406 body: the reason, wrapped the way cmlapi serialises a fault. Read Translations[0].Text. The wording is stable per check (the reference lists it per operation), so you may compare it, but it is not a code.

ValidationException

[
  ["EmailAddress", "Invalid address"],
  ["ShareOfRent", "Can not be zero"],
  ["HouseNumber", "Please fill at least one of these fields"]
]

Typical 400 body from create and submit: an array of [field, message] pairs, one per failed rule. The field is the bare property name, not a path, so a nested field such as Address.Postcode arrives as Postcode. It is null when the message is not about one property, for example [null, "The self validation method thrown an exception while evaluating."] when a submit leaves out IncomeEvidences.

Authentication

Unexpected failures

{
  "title": "An error has occured",
  "status": 500,
  "type": "NullReferenceException",
  "detail": "Object reference not set to an instance of an object.",
  "traceId": "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01",
  "requestId": "0HN7GKQ2P3B4C:00000001"
}

A 500 is RFC 7807 problem details. Quote traceId when you report it; do not parse detail.