CodamAIDocs
Topicdone

Creating an object

What happens step by step with POST /create: system fields, default values, hooks, validation, saving, reading back.

Variants
JSONwith files (multipart or Base64)Singletonabstract model with @typewith child objectsno role → 403rule violated → 422response missing → 400

What this is about

You create a new object with POST {base}/create. The body contains two things:

PartContent
datathe fields of the new object, without id
responsewhich fields you want back in the response, as in Field selection with response
Creating a customer
Request
POST /api/rest/crm/customer/create
{
  "data": { "name": "Muster GmbH", "email": "info@muster.de" },
  "response": ["+"]
}
Response
{
  "data": {
    "id": "5a2b…",
    "_createdOn": "2026-09-21 10:15:02",
    "_updatedOn": null,
    "name": "Muster GmbH",
    "email": "info@muster.de",
    "status": "NEW"
  },
  "meta": { "error": false }
}

The response is 200. id, _createdOn and _updatedOn are always included. The client did not send status: the value NEW is the field’s default value.

The stations of a create

POST /api/rest/crm/customer/create
  1. CIAS
    Filter chain
    Is the token valid?
    ↳ no 401
  2. CDMS
    Field selection
    Is there a response in the body?
    ↳ no 400 response
  3. CDMS
    Model role
    May the person create customer? The same applies to every child that is created along with it.
    ↳ no 403 missing-permission|<rolle>
  4. CDMS
    Transfer fields
    Set system fields, take values from data, fill empty fields with default values, create or link children, collect violations
    ↳ no 400 / 404 for children, see below
  5. Hook
    Before hooks
    Hooks see the new object and may still change it. It does not have an id yet.
  6. CDMS
    Validation
    Are all rules met after the hooks?
    ↳ no 422 validation-failed with all violations
  7. Database
    Save
    The row is written, and the database assigns the id. Then the after hooks run.
    ↳ no 409 already-exists, e.g. a duplicate unique value
  8. CDMS
    Read back
    The new object is read with the response, using the person's read permissions.
    ↳ no 403 / 404, and the create is rolled back as well
  9. 200 with the new object

What CDMS sets on its own when creating

FieldValue
ida new UUID, on save
_createdOnnow
_updatedOnstays empty until the first change
_userIdthe logged-in person, only for models with the scope “user”
@typethe concrete type; for an abstract model, the client chooses it
Fields with a defaultthe default value, if the client sends no value

If the client sends an id or a field starting with _, CDMS ignores it without an error. See System fields that the server sets. The database where the object ends up follows from the tenant of the request. There is no separate tenant field. See Which database? The persistence target

The flow in detail

sequenceDiagram
    participant C as Client
    participant R as REST layer
    participant S as System layer
    participant H as Hooks
    participant DB as Database
    C->>R: POST /create { data, response }
    R->>R: resolve response, take over files
    R->>S: createObject(DTO)
    S->>S: check role, set _createdOn
    S->>S: transfer fields, insert defaults,<br/>create children, collect violations
    S->>H: Before hooks (parents before children)
    S->>S: check violations again → 422?
    S->>DB: INSERT, id is assigned
    S->>H: After hooks
    S->>DB: flush
    S->>DB: read back with response
    S-->>R: DTO
    R-->>C: 200 { data, meta }

The hooks run before validation. So a before hook may fill a required field that the client does not even know about, such as a customer number. More in Hooks: types and timing.

All variants

Creating an object

When: The normal case.

  1. 1
    Client→CDMS
    sends POST /crm/customer/create with data and response
  2. 2
    CDMS
    checks the role, takes over the fields, sets defaults
  3. 3
    Hook
    Before hooks
  4. 4
    CDMS→Database
    checks the rules, saves, reads back
  5. 5
    CDMS→Client
    returns the new object

Result: 200 with the new object and its id.

When: The model is a file model or has file fields.

There are two ways. Multipart: POST /create/upload with a part data (the JSON) and the files in the part files. A file object in data finds its file by name: name in the object must equal the file name of the part. Base64: POST /create as usual, and the content is text in content of the file object. If the matching file is missing for a file model, you get 400 file-part-missing|<name>.

Result: 200, the file is in storage. See Uploading.

When: The model has exactly one object per scope, e.g. settings. Path: POST /create, without id.

  1. 1
    Client→CDMS
    sends POST /crm/einstellungen/create
  2. 2
    CDMS→Database
    Is there already an object in this scope?
  3. 3
    CDMS→Client
    yes → 400 object-already-exists|use-update
  4. 4
    CDMS
    no → creates it like a normal object

Result: 200. After that, you change it with PUT /update or PATCH /update. See Singletons: exactly one object.

When: You create through the hub API of an abstract model, e.g. /crm/kunde/create.

  1. 1
    Client→CDMS
    sends { "data": { "@type": "crm.privatkunde", "name": "Anna Muster" }, "response": ["+"] }
  2. 2
    CDMS
    reads @type and with it the fields of the subtype
  3. 3
    CDMS→Client
    @type missing → 400 missing-type-for-abstract-field|data; unknown type → 400 unknown-type-for-abstract-field|data|<typ>
  4. 4
    CDMS
    passes the request on to the subtype's API, with its roles, rules and hooks

Result: 200 with "@type": "crm.privatkunde". See Abstract models and @type.

When: You create a company with its employees in one request, or link them to existing objects.

  1. 1
    Client→CDMS
    sends "employees": [{ "firstname": "Anna", "lastname": "Schmidt" }], "mainAddress": { "id": "a7…" }
  2. 2
    CDMS
    child without id → is created if the relation allows it, with its own role check, its own defaults and _createdOn
  3. 3
    CDMS→Client
    relation does not allow creating → 400 recursive-create-not-allowed|employees
  4. 4
    CDMS
    child with id → is linked
  5. 5
    CDMS→Client
    id does not exist → 404 missing-object|a7…|mainAddress
  6. 6
    CDMS→Database
    saves everything in one transaction

Result: 200. If one child fails, the company is not created either. See The four cases in nested writing.

Decision table

Response to POST /crm/customer/create
response in the bodyrole to createrules metunique values freeread role for reading backResponse
no––––400 response
yesno–––403 missing-permission|<rolle>
yesyesno––422 validation-failed
yesyesyesno–409 already-exists
yesyesyesyesno403 missing-permission|<leserolle>, nothing created
yesyesyesyesyes200 with the new object

The table describes the standard: strict mode on and reading back in STRICT mode. In LENIENT mode, CDMS saves first and then reads. If only the read fails, the object stays created and the response names its id. See Create and read back: STRICT or LENIENT.

Pitfalls

Where to go next

Sources in the code and the knowledge base
  • CDMS/cdms-generator – ApiProcessor (POST /create, /create/upload), ApiHubProcessor, Payload2DtoMapperProcessor, RestPayloadProcessor
  • CDMS/cdms-rest-api – AbstractRestApi.createObject (getFileMap, addCreateFilesFromBase64), AbstractRestSingletonApi.create, AbstractHubApi.create, Expander, payloads/WritePayload
  • CDMS/cdms-system-layer – AbstractSystemLayer.createObject; AbstractLayer.recursiveCreate, recursivePrepare, setModel; DefaultValueResolver; session/HookRequestContext; configurations/SystemSettings (create-read-mode)
  • CDMS/cdms-persistence-database – AbstractDatabasePersistence.createObject, flush; projection/SelectionBuilder
  • CDMS/cdms-integrationtest – AbstractDefaultValueTest, AbstractRecursiveCreate, AbstractRecursiveAbstractCreate, AbstractRoleDenialTest, AbstractFileBaseTest
  • documentation/05-api-guide/06-schreiben.md, 07-verschachtelt-schreiben.md
Search