You have access to the NovaDB MCP server tools. This skill guides you through creating, editing, and managing forms via the CMS API.
Form Architecture
Object Type (root, ID 0) ├─ objectTypeCreateForm (5001) ──→ 1 Form (shown when creating new objects) └─ objectTypeDetailForms (5002) ──→ [Form, ...] (shown as tabs in detail view) Form Definition (typeForm, ID 50) ├─ formContent (5053) ──→ Individual Attr Def entries (one per field, ordered by sortReverse) ├─ formConditionAttribute (5054) ──→ 1 Attr Def (form visible only when this attr has a value) ├─ formConditionRefs (5055) ──→ [Condition, ...] (all conditions must pass) └─ formIsSingleEditor (5056) ──→ Boolean (single code editor mode)
- •Each object type references one create form and one or more detail forms (tabs).
- •Each form contains an ordered list of attribute definitions (
formContent) controlling which fields appear and in what order. - •Conditional visibility: A form can be hidden based on
formConditionAttribute(show only when a specific attribute has a value) and/orformConditionRefs(condition objects, all must pass). - •Single editor mode (
formIsSingleEditor): Whentrue, renders a single code editor (CSS/JS/HTML) instead of individual fields.
CMS API Value Format
The CMS API uses normalized value tuples:
{ "values": [{ "attribute": 1000, "language": 201, "variant": 0, "value": "Example" }] }
Languages: 201=en-US, 202=de-DE. Use language: 0 for language-independent attributes.
Form Attribute Reference
| ID | apiIdentifier | Data Type | Notes |
|---|---|---|---|
| 5053 | formContent | ObjRef (multi) | Ordered list of attribute definitions to display |
| 5054 | formConditionAttribute | ObjRef | Form visible only when this attribute has a value |
| 5055 | formConditionRefs | ObjRef (multi) | Condition objects (types 170-176), all must pass |
| 5056 | formIsSingleEditor | Boolean | Single code editor mode (CSS/JS/HTML) |
Object Type Form Attributes
| ID | apiIdentifier | Data Type | Notes |
|---|---|---|---|
| 5001 | objectTypeCreateForm | ObjRef | Form shown when creating new objects (single) |
| 5002 | objectTypeDetailForms | ObjRef (multi) | Forms shown as tabs in detail view (array) |
Workflows
Inspect Existing Forms
List all forms in a branch:
novadb_cms_get_typed_objects(branch="branchDefault", type="typeForm")
Get a form with its content:
# 1. Fetch the form novadb_cms_get_object(branch, id=<formId>, inherited=true) # 2. Find formContent (attribute 5053) — individual value entries, each with a single attribute def ID # 3. Resolve the attribute definitions novadb_cms_get_objects(branch, ids="<attrDefId1>,<attrDefId2>,...")
Get an object type's forms:
# 1. Fetch the type novadb_cms_get_object(branch, id=<typeId>, inherited=true) # 2. Find objectTypeCreateForm (5001) and objectTypeDetailForms (5002) values # 3. Resolve the form references novadb_cms_get_objects(branch, ids="<createFormId>,<detailFormId1>,...")
Create a New Form
novadb_cms_create_objects(branch="branchDefault", objects=[{
"meta": { "typeRef": 50, "apiIdentifier": "myFormName" },
"values": [
{ "attribute": 1000, "language": 201, "value": "My Form (EN)" },
{ "attribute": 1000, "language": 202, "value": "Mein Formular (DE)" },
{ "attribute": 5053, "value": <attrDefId1> },
{ "attribute": 5053, "value": <attrDefId2>, "sortReverse": 1 },
{ "attribute": 5053, "value": <attrDefId3>, "sortReverse": 2 },
{ "attribute": 5056, "value": false }
]
}])
Each formContent (5053) entry is a separate value tuple with a single attribute reference. Use sortReverse (0, 1, 2, ...) to control field order. Do not pass an array — it causes HTTP 400.
Add a Form to an Object Type
Important: objectTypeDetailForms (5002) is an array. Always read existing forms first, then append.
# 1. Read existing detail forms
novadb_cms_get_object(branch, id=<typeId>, inherited=true)
# Find the value for attribute 5002, e.g. [2098001, 2098002]
# 2. Append the new form
novadb_cms_update_objects(branch, objects=[{
"meta": { "id": <typeId>, "typeRef": 0 },
"values": [
{ "attribute": 5002, "value": [2098001, 2098002, <newFormId>] }
]
}])
For the create form (5001), it's a single reference:
novadb_cms_update_objects(branch, objects=[{
"meta": { "id": <typeId>, "typeRef": 0 },
"values": [
{ "attribute": 5001, "value": <createFormId> }
]
}])
Edit Form Content (Reorder/Add/Remove Fields)
To edit form content, read the current entries, then rebuild all formContent (5053) entries with the desired order:
# 1. Get current form content
novadb_cms_get_object(branch, id=<formId>, inherited=true)
# Find all value entries for attribute 5053 — each is a separate entry with a single attribute ref
# 2. Rebuild with new order/additions/removals (all entries for 5053 must be sent)
novadb_cms_update_objects(branch, objects=[{
"meta": { "id": <formId>, "typeRef": 50 },
"values": [
{ "attribute": 5053, "value": 2098502 },
{ "attribute": 5053, "value": 1000, "sortReverse": 1 },
{ "attribute": 5053, "value": 2098501, "sortReverse": 2 },
{ "attribute": 5053, "value": <newAttrId>, "sortReverse": 3 }
]
}])
Conditional Forms
Add a condition so a form tab only appears when a specific attribute has a value:
novadb_cms_update_objects(branch, objects=[{
"meta": { "id": <formId>, "typeRef": 50 },
"values": [
{ "attribute": 5054, "value": <conditionAttrId> }
]
}])
For more complex conditions, create condition objects and reference them:
novadb_cms_update_objects(branch, objects=[{
"meta": { "id": <formId>, "typeRef": 50 },
"values": [
{ "attribute": 5055, "value": [<conditionObjId1>, <conditionObjId2>] }
]
}])
Create Condition Objects
To create a typed condition and attach it to a form:
# 1. Discover the condition type's schema (e.g., String Condition)
novadb_cms_get_object(branch, id=173, inherited=true)
# Inspect its forms to understand which attributes it expects
# 2. Create the condition object
novadb_cms_create_objects(branch, objects=[{
"meta": { "typeRef": 173 },
"values": [
{ "attribute": 1000, "language": 201, "value": "Region is EMEA" },
{ "attribute": 1000, "language": 202, "value": "Region ist EMEA" },
# ... condition-specific attributes (varies by type)
]
}])
# Returns the new condition object ID
# 3. Attach to a form via formConditionRefs (5055)
# First read the form to get existing conditions
novadb_cms_get_object(branch, id=<formId>, inherited=true)
# Then update with ALL condition refs (existing + new)
novadb_cms_update_objects(branch, objects=[{
"meta": { "id": <formId>, "typeRef": 50 },
"values": [
{ "attribute": 5055, "value": [<existingCondId>, <newCondId>] }
]
}])
Multi-Tab Management
Manage the detail form tabs of an object type (objectTypeDetailForms / 5002):
List all tabs for a type:
# 1. Fetch the type with inherited values novadb_cms_get_object(branch, id=<typeId>, inherited=true) # 2. Find all values for attribute 5002 — these are the detail form IDs # 3. Resolve the form references to see names novadb_cms_get_objects(branch, ids="<formId1>,<formId2>,...")
Reorder tabs:
# Send the full array with the new order
novadb_cms_update_objects(branch, objects=[{
"meta": { "id": <typeId>, "typeRef": 0 },
"values": [
{ "attribute": 5002, "value": [<formId3>, <formId1>, <formId2>] }
]
}])
Remove a tab:
# Send the full array without the removed form
novadb_cms_update_objects(branch, objects=[{
"meta": { "id": <typeId>, "typeRef": 0 },
"values": [
{ "attribute": 5002, "value": [<formId1>, <formId3>] }
]
}])
Clone a Form
Duplicate an existing form with all its fields:
# 1. Read the source form
novadb_cms_get_object(branch, id=<sourceFormId>, inherited=true)
# 2. Extract all formContent (5053) entries and other attributes
# 3. Create the new form with the same field list
novadb_cms_create_objects(branch, objects=[{
"meta": { "typeRef": 50, "apiIdentifier": "clonedFormName" },
"values": [
{ "attribute": 1000, "language": 201, "value": "Cloned Form (EN)" },
{ "attribute": 1000, "language": 202, "value": "Kopiertes Formular (DE)" },
# Copy all 5053 entries from the source form with their sortReverse values
{ "attribute": 5053, "value": <attrDefId1> },
{ "attribute": 5053, "value": <attrDefId2>, "sortReverse": 1 },
{ "attribute": 5053, "value": <attrDefId3>, "sortReverse": 2 },
# Optionally copy condition attributes (5054, 5055) and single editor mode (5056)
]
}])
Condition Types Reference
| ID | apiIdentifier | Name |
|---|---|---|
| 170 | typeScriptedCondition | Scripted Condition |
| 171 | typeObjectReferenceValueCondition | Object Reference Condition |
| 172 | typeUserNameValueCondition | User Name Condition |
| 173 | typeStringValueCondition | String Condition |
| 174 | typeNumericValueCondition | Numeric Condition |
| 175 | typeTimestampValueCondition | Timestamp Condition |
| 176 | typeBooleanValueCondition | Boolean Condition |
Gotchas
- •
objectTypeDetailForms(5002) is an array — Always read-then-append. Never overwrite with just a single new form ID, or you'll remove all existing tabs. - •
formContent(5053) uses individual entries, NOT arrays — Each attribute reference must be a separate value entry with"attribute": 5053and a single"value". UsesortReverse(0, 1, 2, ...) to control field order. Passing an array like[id1, id2]causes HTTP 400. - •
apiIdentifieris immutable — Set inmeta.apiIdentifierat creation time. Cannot be changed later (HTTP 403). - •
attributeName(1000) is language-dependent — Provide one value per language (201=en-US, 202=de-DE). - •CMS uses numeric attribute IDs, not apiIdentifier strings.
- •Use
inherited=truewhen reading objects to see all values including inherited ones.