> For the complete documentation index, see [llms.txt](https://docs.ninox.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.ninox.com/ninox-api/api-reference/api-endpoints/modules.md).

# Modules

## Get a module definition

> Returns every object of a module as one definition that the PUT route applies, in this or another workspace. Custom roles are referenced by name as @role:\<name>.

```json
{"openapi":"3.0.0","info":{"title":"Ninox Public API","version":"1.0.0"},"security":[{"bearer":[]}],"components":{"securitySchemes":{"bearer":{"scheme":"bearer","bearerFormat":"API Key","description":"Enter your Workspace API key. \n\n API keys can be generated and managed within the **Workspace Integration** settings in the Ninox app.","in":"header","name":"Authorization","type":"http"}},"schemas":{"ModuleDefinitionResponse":{"type":"object","properties":{"data":{"type":"object","properties":{"capabilities":{"type":"array","items":{"type":"string","enum":["ai","connections","cross-module-access","custom-widget","dynamic-html","email","http","scripts"]},"description":"Features the module uses"},"checksum":{"type":"string","description":"Hash of the definition as exported. Not checked on apply"},"formatVersion":{"type":"number","enum":[1]},"objects":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"kind":{"type":"string"}},"required":["id","kind"],"additionalProperties":{}},"description":"Every object of the module, with the module id replaced by a placeholder"},"requiredConnections":{"type":"array","items":{"type":"string"},"description":"Connection names the scripts expect"},"roles":{"type":"array","items":{"type":"object","properties":{"alias":{"type":"string"},"name":{"type":"string"}},"required":["alias","name"],"additionalProperties":{}},"description":"Custom roles the objects reference as @role:<name>"}},"additionalProperties":{}}},"required":["data"]},"ErrorResponse":{"type":"object","properties":{"error":{"type":"object","properties":{"message":{"type":"string","description":"Error message"}}}},"required":["error"]}}},"paths":{"/api/v1/workspace/{workspaceId}/modules/{moduleName}/definition":{"get":{"operationId":"ModuleDefinitionsV1Controller_getModuleDefinition","summary":"Get a module definition","description":"Returns every object of a module as one definition that the PUT route applies, in this or another workspace. Custom roles are referenced by name as @role:<name>.","parameters":[{"name":"moduleName","required":true,"in":"path","description":"Module name","schema":{"minLength":1,"maxLength":100,"pattern":"^[a-z0-9_]+$","type":"string"}},{"name":"workspaceId","required":true,"in":"path","description":"Workspace ID","schema":{"minLength":12,"maxLength":12,"pattern":"^[a-z0-9]+$","type":"string"}}],"responses":{"200":{"description":"Definition retrieved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModuleDefinitionResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Module not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"tags":["Modules"]}}}}
```

## Apply a module definition

> Applies a module definition onto an existing module. An empty module gets every object created, flows included. Otherwise an object is matched by its id, or by the object an earlier apply created it from, so a rename in the source updates the copy. The rest are matched by table id, table and field id, table and name (views, reports), name (scripts), and parent, type and name (components); matched objects are updated, the rest created. Nothing is deleted, and flows and the data-model diagram are skipped. Custom roles resolve by name in this workspace; none are created. Applying the same definition twice changes nothing the second time.

```json
{"openapi":"3.0.0","info":{"title":"Ninox Public API","version":"1.0.0"},"security":[{"bearer":[]}],"components":{"securitySchemes":{"bearer":{"scheme":"bearer","bearerFormat":"API Key","description":"Enter your Workspace API key. \n\n API keys can be generated and managed within the **Workspace Integration** settings in the Ninox app.","in":"header","name":"Authorization","type":"http"}},"schemas":{"ApplyModuleDefinitionBody":{"type":"object","properties":{"capabilities":{"maxItems":20,"type":"array","items":{"type":"string"}},"checksum":{"type":"string"},"documentation":{"type":"object","additionalProperties":{"type":"string"}},"formatVersion":{"type":"number","enum":[1]},"gettingStartedComponentId":{"type":"string"},"objects":{"minItems":1,"maxItems":5000,"type":"array","items":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":100},"kind":{"type":"string","minLength":1,"maxLength":50}},"required":["id","kind"],"additionalProperties":{}}},"requiredConnections":{"maxItems":100,"type":"array","items":{"type":"string"}},"roles":{"default":[],"maxItems":200,"type":"array","items":{"type":"object","properties":{"alias":{"type":"string","minLength":1,"maxLength":100},"name":{"type":"string","minLength":1,"maxLength":100}},"required":["alias","name"],"additionalProperties":{}}}},"required":["formatVersion","objects"],"additionalProperties":false},"ApplyModuleDefinitionResponse":{"type":"object","properties":{"data":{"type":"object","properties":{"created":{"type":"number","description":"Objects created"},"skipped":{"type":"object","additionalProperties":{"type":"number"},"description":"Objects left out on a module that was not empty, counted by kind (flows, data-model diagram)"},"updated":{"type":"number","description":"Existing objects that changed"}}}},"required":["data"]},"ErrorResponse":{"type":"object","properties":{"error":{"type":"object","properties":{"message":{"type":"string","description":"Error message"}}}},"required":["error"]}}},"paths":{"/api/v1/workspace/{workspaceId}/modules/{moduleName}/definition":{"put":{"operationId":"ModuleDefinitionsV1Controller_applyModuleDefinition","summary":"Apply a module definition","description":"Applies a module definition onto an existing module. An empty module gets every object created, flows included. Otherwise an object is matched by its id, or by the object an earlier apply created it from, so a rename in the source updates the copy. The rest are matched by table id, table and field id, table and name (views, reports), name (scripts), and parent, type and name (components); matched objects are updated, the rest created. Nothing is deleted, and flows and the data-model diagram are skipped. Custom roles resolve by name in this workspace; none are created. Applying the same definition twice changes nothing the second time.","parameters":[{"name":"moduleName","required":true,"in":"path","description":"Module name","schema":{"minLength":1,"maxLength":100,"pattern":"^[a-z0-9_]+$","type":"string"}},{"name":"workspaceId","required":true,"in":"path","description":"Workspace ID","schema":{"minLength":12,"maxLength":12,"pattern":"^[a-z0-9]+$","type":"string"}}],"requestBody":{"required":true,"description":"A definition as returned by the GET route, sent back as is or edited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApplyModuleDefinitionBody"}}}},"responses":{"200":{"description":"Definition applied","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApplyModuleDefinitionResponse"}}}},"400":{"description":"Bad request (e.g., malformed definition)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The API key lacks a grant a written key needs","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Module not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Definition refused (unknown role, ambiguous match, field type change)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"tags":["Modules"]}}}}
```

## List all modules in a workspace

> Retrieves all modules available in a workspace

```json
{"openapi":"3.0.0","info":{"title":"Ninox Public API","version":"1.0.0"},"security":[{"bearer":[]}],"components":{"securitySchemes":{"bearer":{"scheme":"bearer","bearerFormat":"API Key","description":"Enter your Workspace API key. \n\n API keys can be generated and managed within the **Workspace Integration** settings in the Ninox app.","in":"header","name":"Authorization","type":"http"}},"schemas":{"ModulesResponse":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"afterOpen":{"description":"Script expression run in the browser each time the app is opened","type":"string"},"components":{"description":"Module components (pages, containers, widgets)","type":"array","items":{"type":"object","properties":{"afterHide":{"description":"Container directly under Tabs: script run when this tab stops being shown","type":"string"},"aggregation":{"description":"MetricCard: aggregation function","type":"string","enum":["avg","count","max","median","min","sum"]},"annualRecurring":{"description":"Calendar: render every record on the same day/month every year","type":"boolean"},"arrangement":{"description":"Page/Container: layout direction","type":"string","enum":["grid","ltr","row","ttb"]},"background":{"description":"Container/Page/Text: background","anyOf":[{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"beforeShow":{"description":"Container directly under Tabs: script run when this tab is shown","type":"string"},"border":{"description":"Container: border","anyOf":[{"type":"object","properties":{"color":{"type":"string"},"style":{"type":"string","enum":["dashed","dotted","double","none","solid"]},"width":{"type":"string"}},"required":["style","width"]},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"calendarType":{"description":"Calendar: display type","type":"string"},"cardBorder":{"description":"Kanban: card border CSS shorthand, Normal mode only","type":"string"},"cardFont":{"description":"Kanban: card font style tokens, Normal mode only","type":"string"},"cardPadding":{"description":"Kanban: card padding in px, Normal mode only","type":"number"},"cardRadius":{"description":"Kanban: card corner radius in px, Normal mode only","type":"number"},"chartConfig":{"description":"Chart: chart type, axes and data series","type":"object","properties":{"chartType":{"type":"string","enum":["bar","line","pie","funnel","ranking","board"]},"dataSets":{"type":"array","items":{"type":"object","properties":{"aggregation":{"type":"string","enum":["average","count","max","median","min","none","sum"]},"color":{"description":"Series color (hex string)","type":"string"},"fieldName":{"description":"Field name this series reads from","type":"string"},"labels":{"description":"Series labels (localized)","type":"object","additionalProperties":{"type":"string"}}}}},"donut":{"type":"boolean"},"labelPosition":{"type":"string","enum":["bottom","center","inside","outside","top"]},"legend":{"type":"object","properties":{"show":{"type":"boolean"}}},"limit":{"description":"ranking only: how many categories it shows","type":"integer","minimum":1,"maximum":20},"orientation":{"type":"string","enum":["horizontal","vertical"]},"showDataTable":{"type":"boolean"},"showLabels":{"type":"boolean"},"showPoints":{"type":"boolean"},"showTitle":{"type":"boolean"},"smooth":{"type":"boolean"},"stacked":{"type":"boolean"},"style":{"type":"string","enum":["default","half_donut","pad_angle","rounded_corner"]},"tooltips":{"type":"object","properties":{"show":{"type":"boolean"}}},"xAxis":{"type":"object","properties":{"fieldName":{"description":"X-axis field name, null removes it","type":["string","null"]},"groupBy":{"type":"string","enum":["daily","monthly","none","quarterly","weekly","yearly"]},"show":{"type":"boolean"}}},"yAxis":{"type":"object","properties":{"show":{"type":"boolean"}}}},"required":["chartType","dataSets","xAxis"]},"color":{"description":"Text: text color (hex string). Button: theme color name","anyOf":[{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"colorFieldName":{"description":"Map: marker color field name","type":"string"},"constraints":{"description":"FieldComponent: script limiting which records a reference can link to, needs schema:manage-permissions","type":"string"},"content":{"description":"Text: content, localized or a script expression","anyOf":[{"type":"object","additionalProperties":{"type":"string"}},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"customStyle":{"description":"Text: full custom style config, opaque, used only when quickStyle is \"custom\"","type":"object","additionalProperties":{}},"dataPoint":{"description":"'conditional' replaces table/filter/… with the `value` script","type":"string","enum":["conditional","normal"]},"defaultValue":{"description":"InputComponent: initial value, or { $nx: <script> }","anyOf":[{"type":"boolean"},{"type":"number"},{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"disabled":{"description":"Button/FieldComponent: disable the control, a boolean or a script","anyOf":[{"type":"boolean"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"display":{"description":"MetricCard: display formatting and trend configuration","type":"object","properties":{"color":{"type":"string"},"format":{"type":"string","enum":["compact","currency","number","percentage"]},"icon":{"type":"string"},"trend":{"type":"object","properties":{"customPeriodEnd":{"description":"ISO date (YYYY-MM-DD), for period \"custom\"","type":"string"},"customPeriodStart":{"description":"ISO date (YYYY-MM-DD), for period \"custom\"","type":"string"},"format":{"type":"string","enum":["absolute","percentage"]},"isShown":{"type":"boolean"},"period":{"type":"string","enum":["custom","last_month","last_week","last_year","previous_period","yesterday"]},"positiveDirection":{"type":"string","enum":["down","up"]}},"required":["format","isShown"]}},"required":["color","format","trend"]},"displayAs":{"description":"FieldComponent: how a yes/no field is shown","type":"string"},"expression":{"description":"DynamicHTMLComponent: script returning the HTML to render","type":"string"},"fieldIdDataPoint":{"description":"MetricCard: 'conditional' replaces table/filter/fieldName/aggregation with fieldIdValue","type":"string","enum":["conditional","normal"]},"fieldIdValue":{"description":"MetricCard: whole-dataset script producing the final number when fieldIdDataPoint is conditional","type":"string"},"fieldName":{"description":"MetricCard/Calendar/Map: primary bound field name","type":"string"},"filter":{"description":"MetricCard/Chart: stored filter conditions","type":"array","items":{"type":"object","properties":{"field":{"description":"Field name","type":"string"},"id":{"type":"string","description":"Stable condition id"},"operator":{"description":"Filter operator","type":"string"},"value":{"description":"Value compared against","type":"string"}},"required":["id"]}},"flex":{"description":"Container: flex sizing","anyOf":[{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"ganttConfig":{"description":"Gantt: which fields the bars/milestones/dependencies read from","type":"object","properties":{"baselineEndFieldName":{"description":"Planned end field, rendered as a ghost bar","type":["string","null"]},"baselineStartFieldName":{"description":"Planned start field, rendered as a ghost bar","type":["string","null"]},"dependencyDirection":{"type":"string","enum":["predecessor","successor"]},"dependencyFieldName":{"description":"A reference field pointing back at this table","type":["string","null"]},"disableDragAndDrop":{"type":"boolean"},"endFieldName":{"type":["string","null"]},"hideTitleColumn":{"type":"boolean"},"hideWeekends":{"type":"boolean"},"milestoneFieldName":{"type":["string","null"]},"progressFieldName":{"type":["string","null"]},"showCriticalPath":{"type":"boolean"},"showWeekends":{"type":"boolean"},"startFieldName":{"type":["string","null"]},"timeScale":{"type":"string","enum":["day","month","quarter","week"]},"titleColumnFieldName":{"type":["string","null"]},"titleColumnWidth":{"type":"number"}}},"gap":{"description":"Page/Container: gap between children","anyOf":[{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"globalFilterBinding":{"description":"MetricCard: field names this card reacts to for global page filters","type":"array","items":{"type":"string"}},"gridPreset":{"description":"Container: grid layout preset","anyOf":[{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"groupByFieldName":{"description":"Kanban: lane grouping field name","type":"string"},"height":{"description":"Component height","type":"number"},"icon":{"description":"Page: icon","type":"object","properties":{"color":{"description":"Icon color (hex string)","type":"string"},"filling":{"description":"Icon filling","anyOf":[{"type":"number","enum":[0]},{"type":"number","enum":[1]}]},"icon":{"type":"string","description":"Icon name"}},"required":["icon"]},"iconLeft":{"description":"Button/FieldComponent: icon before the label","anyOf":[{"type":"object","properties":{"color":{"description":"Icon color (hex string)","type":"string"},"filling":{"description":"Icon filling","anyOf":[{"type":"number","enum":[0]},{"type":"number","enum":[1]}]},"icon":{"type":"string","description":"Icon name"}},"required":["icon"]},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"iconRight":{"description":"Button/FieldComponent: icon after the label","anyOf":[{"type":"object","properties":{"color":{"description":"Icon color (hex string)","type":"string"},"filling":{"description":"Icon filling","anyOf":[{"type":"number","enum":[0]},{"type":"number","enum":[1]}]},"icon":{"type":"string","description":"Icon name"}},"required":["icon"]},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"id":{"type":"string","description":"Component id"},"imagePosition":{"description":"Kanban: card image crop/anchor, Normal mode only","type":"object","properties":{"position":{"type":"string"},"size":{"type":"string"}}},"isCompact":{"description":"Accordion: compact sections","type":"boolean"},"isHidden":{"description":"Page: hide from navigation","type":"boolean"},"isMarkdownEnabled":{"description":"FieldComponent: render a rich text field as markdown","type":"boolean"},"isSpreadsheetMode":{"description":"Table/FieldComponent: spreadsheet-style editing","type":"boolean"},"kind":{"type":"string","deprecated":true,"description":"Deprecated, use type. Same value, kept so existing integrations keep working"},"labelPosition":{"description":"FieldComponent: top, left, inside or hidden","type":"string"},"labels":{"description":"Component labels (localized)","type":"object","additionalProperties":{"type":"string"}},"mapTypeId":{"description":"Map: base layer type","type":"string"},"margin":{"description":"Container: margin","anyOf":[{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"name":{"description":"Component name","type":"string"},"onChange":{"description":"Tabs/FieldComponent: script run when the value changes","type":"string"},"onClick":{"description":"Button: script run on click","type":"string"},"order":{"description":"Component display order","type":"number"},"overflow":{"description":"Container: overflow behavior","anyOf":[{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"padding":{"description":"Page/Container: padding","anyOf":[{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"parentId":{"description":"Parent component id (forms the component tree)","type":"string"},"placeholder":{"description":"FieldComponent: placeholder, localized, plain or a script","anyOf":[{"type":"object","additionalProperties":{"type":"string"}},{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"quickStyle":{"description":"Text: style preset","anyOf":[{"type":"string","enum":["body-md","body-sm","custom","title-lg","title-md","title-sm"]},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"radius":{"description":"Container/Text: corner radius","anyOf":[{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"remember":{"description":"InputComponent: how long the value is kept","type":"string","enum":["localStorage","memory","url"]},"shadow":{"description":"Container: shadow","anyOf":[{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"shadowDom":{"description":"DynamicHTMLComponent: render inside a shadow DOM","type":"boolean"},"showAs":{"description":"FieldComponent: how the value is shown (e.g. popup, combobox)","type":"string"},"showBulkActions":{"description":"Table/FieldComponent: show bulk actions","type":"boolean"},"showCalendarType":{"description":"Calendar: show the calendar type switcher","type":"boolean"},"showCreateButton":{"description":"Table: show the create-record button","type":"boolean"},"showCreateRow":{"description":"Table: show the inline create row","type":"boolean"},"showDataAs":{"description":"FieldComponent: script formatting a linked record","type":"string"},"showEmptyLane":{"description":"Kanban: show lanes with no cards","type":"boolean"},"showLinkExistingRecord":{"description":"FieldComponent: offer linking an existing record","type":"boolean"},"showMetadata":{"description":"FieldComponent: show file metadata","type":"boolean"},"showOutlines":{"description":"Page: show layout outlines in the editor","type":"boolean"},"showSearchField":{"description":"Table/Kanban/Gantt/Calendar/Map: show the search field","type":"boolean"},"showTimeScaleSelector":{"description":"Gantt: let the viewer switch time scale","type":"boolean"},"showTitle":{"description":"Table: show the table title","type":"boolean"},"size":{"description":"Button: sm, md or lg","anyOf":[{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"tableName":{"description":"Table this component reads from (Chart/Table/Kanban/Gantt/Calendar/Map/MetricCard)","type":"string"},"textAlign":{"description":"Text: alignment","type":"string","enum":["text-center","text-left","text-right"]},"titleFieldName":{"description":"Map: marker title field name","type":"string"},"tooltip":{"description":"FieldComponent: tooltip text","type":"string"},"type":{"type":"string","description":"Component type (e.g. Container, Button, Text, Page), the property the create and update routes and the module definition take"},"value":{"description":"Script used instead of table/filter/… when dataPoint is conditional","type":"string"},"valueSpec":{"description":"InputComponent: the type of the value, shaped like a field type, a reference has refTableName","type":"object","properties":{"type":{"type":"string"}},"required":["type"],"additionalProperties":{}},"valueType":{"description":"InputComponent: legacy value type, valueSpec wins where both are set","type":"string"},"variant":{"description":"Button/Accordion/Tabs: visual variant, InputComponent: text, email, phone, url, ...","anyOf":[{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"view":{"description":"Table/MetricCard/Kanban/Gantt/Calendar/Map: columns/filter/groupBy/sort configuration","type":"object","properties":{"columns":{"description":"View columns","type":"array","items":{"type":"object","properties":{"agg":{"description":"Aggregation function applied to the column","type":"string"},"conditionalStyling":{"description":"Legacy per-column conditional styling rules","type":"array","items":{"type":"object","properties":{"background":{"description":"Background color (hex string)","type":"string"},"cell":{"description":"Target cell","type":"string"},"color":{"description":"Icon color (hex string)","type":"string"},"icon":{"description":"Icon name","type":"string"},"operand":{"type":"string","description":"Comparator"},"value":{"type":"string","description":"Value compared against"}},"required":["operand","value"]}},"field":{"type":"string","description":"Field name, or a script expression for a calculated column"},"hidden":{"description":"Column retained but hidden from the grid","type":"boolean"},"id":{"description":"Stable identity of a calculated column; send it back unchanged when updating the view","type":"string"},"labels":{"description":"Column labels (localized)","type":"object","additionalProperties":{"type":"string"}},"order":{"type":"number","description":"Column display order"},"role":{"description":"Column role (e.g. title, date, image, location, color)","type":"string"},"width":{"description":"Column width","type":"number"}},"required":["field","order"]}},"conditionalFormatting":{"description":"Conditional formatting rules","type":"array","items":{"type":"object","properties":{"backgroundColor":{"description":"Background color (hex string)","type":"string"},"bold":{"description":"Bold text","type":"boolean"},"comparator":{"type":"string","enum":["contains","does_not_contain","ends_with","gt","gte","is","is_empty","is_not","is_not_empty","logic","lt","lte","starts_with"],"description":"Comparator"},"expression":{"description":"Script expression, used only when comparator is 'logic'","type":"string"},"fieldName":{"type":"string","description":"Target field name"},"highlightColor":{"description":"Highlight color (hex string)","type":"string"},"icon":{"description":"Icon","type":"object","properties":{"color":{"description":"Icon color (hex string)","type":"string"},"filling":{"description":"Icon filling","anyOf":[{"type":"number","enum":[0]},{"type":"number","enum":[1]}]},"icon":{"type":"string","description":"Icon name"}},"required":["icon"]},"id":{"type":"string","description":"Stable rule id"},"italic":{"description":"Italic text","type":"boolean"},"order":{"type":"number","description":"Rule evaluation order"},"strikethrough":{"description":"Strikethrough text","type":"boolean"},"target":{"type":"string","enum":["cell","row"],"description":"Whether the rule styles a single cell or the whole row"},"textColor":{"description":"Text color (hex string)","type":"string"},"value":{"description":"Value compared against"}},"required":["comparator","fieldName","id","order","target"]}},"filter":{"description":"Stored filter conditions","type":"array","items":{"type":"object","properties":{"field":{"description":"Field name","type":"string"},"id":{"type":"string","description":"Stable condition id"},"operator":{"description":"Filter operator","type":"string"},"value":{"description":"Value compared against","type":"string"}},"required":["id"]}},"groupBy":{"description":"Grouping configuration","type":"array","items":{"type":"object","properties":{"direction":{"description":"Group order direction, defaults to ascending","type":"string","enum":["asc","desc"]},"fieldName":{"type":"string","description":"Field name"}},"required":["fieldName"]}},"sort":{"description":"Sort configuration","type":"object","properties":{"direction":{"type":"string","enum":["asc","desc"],"description":"Sort direction"},"fieldName":{"type":"string","description":"Field name"}},"required":["direction","fieldName"]}}},"visible":{"description":"Conditional visibility logic: a boolean, or a script expression (as { $nx: <script> }) evaluated at render time","anyOf":[{"type":"boolean"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"visibleRoles":{"description":"Page: roles allowed to view this page","type":"array","items":{"type":"string"}},"widgetName":{"description":"CustomWidget: folder name under the workspace widgets directory","type":"string"},"widgetProps":{"description":"CustomWidget: property values, each static or a script expression (as { $nx: <script> })","type":"object","additionalProperties":{"anyOf":[{"type":"boolean"},{"type":"number"},{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]}},"width":{"description":"Component width: number = legacy px, string = percentage e.g. \"50%\"","type":["number","string"]}},"required":["id","kind","type"]}},"hideNavigation":{"description":"Hide module from navigation","type":"boolean"},"icon":{"description":"Module icon","type":"object","properties":{"color":{"description":"Icon color (hex string)","type":"string"},"filling":{"description":"Icon filling","anyOf":[{"type":"number","enum":[0]},{"type":"number","enum":[1]}]},"icon":{"type":"string","description":"Icon name"}},"required":["icon"]},"isHidden":{"description":"Hide module","type":"boolean"},"labels":{"description":"Module labels (localized)","type":"object","additionalProperties":{"type":"string"}},"name":{"type":"string"},"openRoles":{"description":"Module open roles","type":"array","items":{"type":"string"}},"tables":{"type":"array","items":{"type":"object","properties":{"canCreate":{"description":"Script expression gating record creation","type":"string"},"canDelete":{"description":"Script expression gating record deletion","type":"string"},"canRead":{"description":"Script expression gating record read access","type":"string"},"canWrite":{"description":"Script expression gating record write access","type":"string"},"createRoles":{"description":"Roles allowed to create records","type":"array","items":{"type":"string"}},"deleteRoles":{"description":"Roles allowed to delete records","type":"array","items":{"type":"string"}},"fields":{"type":"array","items":{"type":"object","properties":{"binding":{"description":"Read-only: internal binding reference, format not yet specified","type":"string"},"canRead":{"description":"Script expression gating field-level read access","type":"string"},"canWrite":{"description":"Script expression gating field-level write access","type":"string"},"defaultValue":{"description":"Default value applied when a record is created: a literal value (an array of option ids for multi/dmulti), or a script expression (as { $nx: <script> }) evaluated at creation time","anyOf":[{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]},{"type":["boolean","null","number","string"]},{"type":"array","items":{"type":"string"}}]},"expression":{"description":"Expression (for function type)","type":"string"},"index":{"description":"Field is indexed","type":"boolean"},"labels":{"description":"Field labels (localized)","type":"object","additionalProperties":{"type":"string"}},"name":{"type":"string","description":"Field name"},"onUpdate":{"description":"Script expression run as a row trigger when the field value changes","type":"string"},"optionColor":{"description":"Color expression for dchoice/dmulti fields","type":"string"},"optionIcon":{"description":"Icon expression for dchoice/dmulti fields","type":"string"},"optionName":{"description":"Display name expression for dchoice/dmulti fields","type":"string"},"options":{"description":"Options array for choice/multi fields, or selection expression for dchoice/dmulti fields","anyOf":[{"type":"array","items":{"type":"object","properties":{"color":{"description":"Option color (hex string)","type":"string"},"icon":{"description":"Option icon name","type":"string"},"id":{"type":"string","description":"Option id, a string the caller can set and change"},"label":{"type":"string","description":"Option text in the default language"},"labels":{"description":"Option text per language","type":"object","additionalProperties":{"type":"string"}},"order":{"type":"number","description":"Option display order"},"textColor":{"description":"Option text color (hex string)","type":"string"}},"required":["id","label","order"]}},{"type":"string"}]},"readRoles":{"description":"Roles allowed to read the field","type":"array","items":{"type":"string"}},"refTableName":{"description":"Reference table name","type":"string"},"required":{"description":"Field is required","type":"boolean"},"search":{"description":"Field is searchable","type":"boolean"},"syncedFrom":{"description":"Source column this field syncs from. Read-only unless the table has two-way sync with updates enabled, in which case every synced field except the key column is writable.","type":"string"},"type":{"type":"string","enum":["any","appointment","boolean","choice","color","date","dchoice","dmulti","file","function","html","icon","lambda","multi","number","react","reference","reverse","rowId","string","styled","time","timeinterval","timestamp","unknown","user","void"],"description":"Field type"},"unique":{"description":"Field is unique","type":"boolean"},"variant":{"description":"Field variant (for string type)","type":"string"},"writeRoles":{"description":"Roles allowed to write to the field","type":"array","items":{"type":"string"}}},"required":["name","type"]}},"hasFiles":{"description":"Enable files for the table","type":"boolean"},"hasGlobalSearch":{"description":"Enable global search for the table","type":"boolean"},"hasHistory":{"description":"Enable history for the table","type":"boolean"},"icon":{"description":"Table icon","type":"object","properties":{"color":{"description":"Icon color (hex string)","type":"string"},"filling":{"description":"Icon filling","anyOf":[{"type":"number","enum":[0]},{"type":"number","enum":[1]}]},"icon":{"type":"string","description":"Icon name"}},"required":["icon"]},"isEmailLinkingEnabled":{"description":"Enable email linking for the table","type":"boolean"},"isHidden":{"description":"Hide the table","type":"boolean"},"labels":{"description":"Table labels (localized)","type":"object","additionalProperties":{"type":"string"}},"name":{"type":"string"},"onCreate":{"description":"Script expression run as a trigger after a record is created","type":"string"},"onDelete":{"description":"Script expression run as a trigger when a record is deleted","type":"string"},"onUpdate":{"description":"Script expression run as a trigger after a record is updated","type":"string"},"readRoles":{"description":"Roles allowed to read records","type":"array","items":{"type":"string"}},"writeRoles":{"description":"Roles allowed to update records","type":"array","items":{"type":"string"}}},"required":["name"]}}},"required":["name"]},"description":"List of modules"},"page_info":{"type":"object","properties":{"has_more":{"type":"boolean","description":"Whether more results are available"},"limit":{"type":"number","description":"Maximum results per page"},"offset":{"type":"number","description":"Current offset"}},"description":"Pagination information"}},"required":["data","page_info"]},"ErrorResponse":{"type":"object","properties":{"error":{"type":"object","properties":{"message":{"type":"string","description":"Error message"}}}},"required":["error"]}}},"paths":{"/api/v1/workspace/{workspaceId}/modules":{"get":{"operationId":"ModulesV1Controller_getModules","summary":"List all modules in a workspace","description":"Retrieves all modules available in a workspace","parameters":[{"name":"workspaceId","required":true,"in":"path","description":"Workspace ID","schema":{"minLength":12,"maxLength":12,"pattern":"^[a-z0-9]+$","type":"string"}},{"name":"limit","required":false,"in":"query","description":"Maximum number of modules to return","schema":{"minimum":1,"type":"number"}},{"name":"offset","required":false,"in":"query","description":"Number of modules to skip (starts with 0)","schema":{"minimum":0,"type":"number"}}],"responses":{"200":{"description":"Modules retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModulesResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Workspace not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"tags":["Modules"]}}}}
```

## Create a module

> Creates a new module in a workspace

```json
{"openapi":"3.0.0","info":{"title":"Ninox Public API","version":"1.0.0"},"security":[{"bearer":[]}],"components":{"securitySchemes":{"bearer":{"scheme":"bearer","bearerFormat":"API Key","description":"Enter your Workspace API key. \n\n API keys can be generated and managed within the **Workspace Integration** settings in the Ninox app.","in":"header","name":"Authorization","type":"http"}},"schemas":{"CreateModuleBody":{"type":"object","properties":{"afterOpen":{"description":"Script expression run in the browser each time the app is opened. Needs schema:write plus records:write","type":"string"},"name":{"type":"string","minLength":1,"maxLength":100,"pattern":"^[a-z0-9_]+$","description":"Module name"},"hideNavigation":{"description":"Hide module from navigation","type":"boolean"},"icon":{"description":"Module icon","type":"object","properties":{"color":{"type":"string"},"filling":{"anyOf":[{"type":"number","enum":[0]},{"type":"number","enum":[1]}]},"icon":{"type":"string","minLength":1}}},"isHidden":{"description":"Hide module","type":"boolean"},"labels":{"description":"Module labels (localized)","type":"object","additionalProperties":{"type":"string","minLength":1,"maxLength":100}},"openRoles":{"description":"Module open roles","minItems":1,"maxItems":2,"type":"array","items":{"type":"string","enum":["admin","editor"]}}},"required":["name"],"description":"Create Module request body"},"ModuleResponse":{"type":"object","properties":{"data":{"type":"object","properties":{"afterOpen":{"description":"Script expression run in the browser each time the app is opened","type":"string"},"components":{"description":"Module components (pages, containers, widgets)","type":"array","items":{"type":"object","properties":{"afterHide":{"description":"Container directly under Tabs: script run when this tab stops being shown","type":"string"},"aggregation":{"description":"MetricCard: aggregation function","type":"string","enum":["avg","count","max","median","min","sum"]},"annualRecurring":{"description":"Calendar: render every record on the same day/month every year","type":"boolean"},"arrangement":{"description":"Page/Container: layout direction","type":"string","enum":["grid","ltr","row","ttb"]},"background":{"description":"Container/Page/Text: background","anyOf":[{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"beforeShow":{"description":"Container directly under Tabs: script run when this tab is shown","type":"string"},"border":{"description":"Container: border","anyOf":[{"type":"object","properties":{"color":{"type":"string"},"style":{"type":"string","enum":["dashed","dotted","double","none","solid"]},"width":{"type":"string"}},"required":["style","width"]},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"calendarType":{"description":"Calendar: display type","type":"string"},"cardBorder":{"description":"Kanban: card border CSS shorthand, Normal mode only","type":"string"},"cardFont":{"description":"Kanban: card font style tokens, Normal mode only","type":"string"},"cardPadding":{"description":"Kanban: card padding in px, Normal mode only","type":"number"},"cardRadius":{"description":"Kanban: card corner radius in px, Normal mode only","type":"number"},"chartConfig":{"description":"Chart: chart type, axes and data series","type":"object","properties":{"chartType":{"type":"string","enum":["bar","line","pie","funnel","ranking","board"]},"dataSets":{"type":"array","items":{"type":"object","properties":{"aggregation":{"type":"string","enum":["average","count","max","median","min","none","sum"]},"color":{"description":"Series color (hex string)","type":"string"},"fieldName":{"description":"Field name this series reads from","type":"string"},"labels":{"description":"Series labels (localized)","type":"object","additionalProperties":{"type":"string"}}}}},"donut":{"type":"boolean"},"labelPosition":{"type":"string","enum":["bottom","center","inside","outside","top"]},"legend":{"type":"object","properties":{"show":{"type":"boolean"}}},"limit":{"description":"ranking only: how many categories it shows","type":"integer","minimum":1,"maximum":20},"orientation":{"type":"string","enum":["horizontal","vertical"]},"showDataTable":{"type":"boolean"},"showLabels":{"type":"boolean"},"showPoints":{"type":"boolean"},"showTitle":{"type":"boolean"},"smooth":{"type":"boolean"},"stacked":{"type":"boolean"},"style":{"type":"string","enum":["default","half_donut","pad_angle","rounded_corner"]},"tooltips":{"type":"object","properties":{"show":{"type":"boolean"}}},"xAxis":{"type":"object","properties":{"fieldName":{"description":"X-axis field name, null removes it","type":["string","null"]},"groupBy":{"type":"string","enum":["daily","monthly","none","quarterly","weekly","yearly"]},"show":{"type":"boolean"}}},"yAxis":{"type":"object","properties":{"show":{"type":"boolean"}}}},"required":["chartType","dataSets","xAxis"]},"color":{"description":"Text: text color (hex string). Button: theme color name","anyOf":[{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"colorFieldName":{"description":"Map: marker color field name","type":"string"},"constraints":{"description":"FieldComponent: script limiting which records a reference can link to, needs schema:manage-permissions","type":"string"},"content":{"description":"Text: content, localized or a script expression","anyOf":[{"type":"object","additionalProperties":{"type":"string"}},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"customStyle":{"description":"Text: full custom style config, opaque, used only when quickStyle is \"custom\"","type":"object","additionalProperties":{}},"dataPoint":{"description":"'conditional' replaces table/filter/… with the `value` script","type":"string","enum":["conditional","normal"]},"defaultValue":{"description":"InputComponent: initial value, or { $nx: <script> }","anyOf":[{"type":"boolean"},{"type":"number"},{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"disabled":{"description":"Button/FieldComponent: disable the control, a boolean or a script","anyOf":[{"type":"boolean"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"display":{"description":"MetricCard: display formatting and trend configuration","type":"object","properties":{"color":{"type":"string"},"format":{"type":"string","enum":["compact","currency","number","percentage"]},"icon":{"type":"string"},"trend":{"type":"object","properties":{"customPeriodEnd":{"description":"ISO date (YYYY-MM-DD), for period \"custom\"","type":"string"},"customPeriodStart":{"description":"ISO date (YYYY-MM-DD), for period \"custom\"","type":"string"},"format":{"type":"string","enum":["absolute","percentage"]},"isShown":{"type":"boolean"},"period":{"type":"string","enum":["custom","last_month","last_week","last_year","previous_period","yesterday"]},"positiveDirection":{"type":"string","enum":["down","up"]}},"required":["format","isShown"]}},"required":["color","format","trend"]},"displayAs":{"description":"FieldComponent: how a yes/no field is shown","type":"string"},"expression":{"description":"DynamicHTMLComponent: script returning the HTML to render","type":"string"},"fieldIdDataPoint":{"description":"MetricCard: 'conditional' replaces table/filter/fieldName/aggregation with fieldIdValue","type":"string","enum":["conditional","normal"]},"fieldIdValue":{"description":"MetricCard: whole-dataset script producing the final number when fieldIdDataPoint is conditional","type":"string"},"fieldName":{"description":"MetricCard/Calendar/Map: primary bound field name","type":"string"},"filter":{"description":"MetricCard/Chart: stored filter conditions","type":"array","items":{"type":"object","properties":{"field":{"description":"Field name","type":"string"},"id":{"type":"string","description":"Stable condition id"},"operator":{"description":"Filter operator","type":"string"},"value":{"description":"Value compared against","type":"string"}},"required":["id"]}},"flex":{"description":"Container: flex sizing","anyOf":[{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"ganttConfig":{"description":"Gantt: which fields the bars/milestones/dependencies read from","type":"object","properties":{"baselineEndFieldName":{"description":"Planned end field, rendered as a ghost bar","type":["string","null"]},"baselineStartFieldName":{"description":"Planned start field, rendered as a ghost bar","type":["string","null"]},"dependencyDirection":{"type":"string","enum":["predecessor","successor"]},"dependencyFieldName":{"description":"A reference field pointing back at this table","type":["string","null"]},"disableDragAndDrop":{"type":"boolean"},"endFieldName":{"type":["string","null"]},"hideTitleColumn":{"type":"boolean"},"hideWeekends":{"type":"boolean"},"milestoneFieldName":{"type":["string","null"]},"progressFieldName":{"type":["string","null"]},"showCriticalPath":{"type":"boolean"},"showWeekends":{"type":"boolean"},"startFieldName":{"type":["string","null"]},"timeScale":{"type":"string","enum":["day","month","quarter","week"]},"titleColumnFieldName":{"type":["string","null"]},"titleColumnWidth":{"type":"number"}}},"gap":{"description":"Page/Container: gap between children","anyOf":[{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"globalFilterBinding":{"description":"MetricCard: field names this card reacts to for global page filters","type":"array","items":{"type":"string"}},"gridPreset":{"description":"Container: grid layout preset","anyOf":[{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"groupByFieldName":{"description":"Kanban: lane grouping field name","type":"string"},"height":{"description":"Component height","type":"number"},"icon":{"description":"Page: icon","type":"object","properties":{"color":{"description":"Icon color (hex string)","type":"string"},"filling":{"description":"Icon filling","anyOf":[{"type":"number","enum":[0]},{"type":"number","enum":[1]}]},"icon":{"type":"string","description":"Icon name"}},"required":["icon"]},"iconLeft":{"description":"Button/FieldComponent: icon before the label","anyOf":[{"type":"object","properties":{"color":{"description":"Icon color (hex string)","type":"string"},"filling":{"description":"Icon filling","anyOf":[{"type":"number","enum":[0]},{"type":"number","enum":[1]}]},"icon":{"type":"string","description":"Icon name"}},"required":["icon"]},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"iconRight":{"description":"Button/FieldComponent: icon after the label","anyOf":[{"type":"object","properties":{"color":{"description":"Icon color (hex string)","type":"string"},"filling":{"description":"Icon filling","anyOf":[{"type":"number","enum":[0]},{"type":"number","enum":[1]}]},"icon":{"type":"string","description":"Icon name"}},"required":["icon"]},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"id":{"type":"string","description":"Component id"},"imagePosition":{"description":"Kanban: card image crop/anchor, Normal mode only","type":"object","properties":{"position":{"type":"string"},"size":{"type":"string"}}},"isCompact":{"description":"Accordion: compact sections","type":"boolean"},"isHidden":{"description":"Page: hide from navigation","type":"boolean"},"isMarkdownEnabled":{"description":"FieldComponent: render a rich text field as markdown","type":"boolean"},"isSpreadsheetMode":{"description":"Table/FieldComponent: spreadsheet-style editing","type":"boolean"},"kind":{"type":"string","deprecated":true,"description":"Deprecated, use type. Same value, kept so existing integrations keep working"},"labelPosition":{"description":"FieldComponent: top, left, inside or hidden","type":"string"},"labels":{"description":"Component labels (localized)","type":"object","additionalProperties":{"type":"string"}},"mapTypeId":{"description":"Map: base layer type","type":"string"},"margin":{"description":"Container: margin","anyOf":[{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"name":{"description":"Component name","type":"string"},"onChange":{"description":"Tabs/FieldComponent: script run when the value changes","type":"string"},"onClick":{"description":"Button: script run on click","type":"string"},"order":{"description":"Component display order","type":"number"},"overflow":{"description":"Container: overflow behavior","anyOf":[{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"padding":{"description":"Page/Container: padding","anyOf":[{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"parentId":{"description":"Parent component id (forms the component tree)","type":"string"},"placeholder":{"description":"FieldComponent: placeholder, localized, plain or a script","anyOf":[{"type":"object","additionalProperties":{"type":"string"}},{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"quickStyle":{"description":"Text: style preset","anyOf":[{"type":"string","enum":["body-md","body-sm","custom","title-lg","title-md","title-sm"]},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"radius":{"description":"Container/Text: corner radius","anyOf":[{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"remember":{"description":"InputComponent: how long the value is kept","type":"string","enum":["localStorage","memory","url"]},"shadow":{"description":"Container: shadow","anyOf":[{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"shadowDom":{"description":"DynamicHTMLComponent: render inside a shadow DOM","type":"boolean"},"showAs":{"description":"FieldComponent: how the value is shown (e.g. popup, combobox)","type":"string"},"showBulkActions":{"description":"Table/FieldComponent: show bulk actions","type":"boolean"},"showCalendarType":{"description":"Calendar: show the calendar type switcher","type":"boolean"},"showCreateButton":{"description":"Table: show the create-record button","type":"boolean"},"showCreateRow":{"description":"Table: show the inline create row","type":"boolean"},"showDataAs":{"description":"FieldComponent: script formatting a linked record","type":"string"},"showEmptyLane":{"description":"Kanban: show lanes with no cards","type":"boolean"},"showLinkExistingRecord":{"description":"FieldComponent: offer linking an existing record","type":"boolean"},"showMetadata":{"description":"FieldComponent: show file metadata","type":"boolean"},"showOutlines":{"description":"Page: show layout outlines in the editor","type":"boolean"},"showSearchField":{"description":"Table/Kanban/Gantt/Calendar/Map: show the search field","type":"boolean"},"showTimeScaleSelector":{"description":"Gantt: let the viewer switch time scale","type":"boolean"},"showTitle":{"description":"Table: show the table title","type":"boolean"},"size":{"description":"Button: sm, md or lg","anyOf":[{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"tableName":{"description":"Table this component reads from (Chart/Table/Kanban/Gantt/Calendar/Map/MetricCard)","type":"string"},"textAlign":{"description":"Text: alignment","type":"string","enum":["text-center","text-left","text-right"]},"titleFieldName":{"description":"Map: marker title field name","type":"string"},"tooltip":{"description":"FieldComponent: tooltip text","type":"string"},"type":{"type":"string","description":"Component type (e.g. Container, Button, Text, Page), the property the create and update routes and the module definition take"},"value":{"description":"Script used instead of table/filter/… when dataPoint is conditional","type":"string"},"valueSpec":{"description":"InputComponent: the type of the value, shaped like a field type, a reference has refTableName","type":"object","properties":{"type":{"type":"string"}},"required":["type"],"additionalProperties":{}},"valueType":{"description":"InputComponent: legacy value type, valueSpec wins where both are set","type":"string"},"variant":{"description":"Button/Accordion/Tabs: visual variant, InputComponent: text, email, phone, url, ...","anyOf":[{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"view":{"description":"Table/MetricCard/Kanban/Gantt/Calendar/Map: columns/filter/groupBy/sort configuration","type":"object","properties":{"columns":{"description":"View columns","type":"array","items":{"type":"object","properties":{"agg":{"description":"Aggregation function applied to the column","type":"string"},"conditionalStyling":{"description":"Legacy per-column conditional styling rules","type":"array","items":{"type":"object","properties":{"background":{"description":"Background color (hex string)","type":"string"},"cell":{"description":"Target cell","type":"string"},"color":{"description":"Icon color (hex string)","type":"string"},"icon":{"description":"Icon name","type":"string"},"operand":{"type":"string","description":"Comparator"},"value":{"type":"string","description":"Value compared against"}},"required":["operand","value"]}},"field":{"type":"string","description":"Field name, or a script expression for a calculated column"},"hidden":{"description":"Column retained but hidden from the grid","type":"boolean"},"id":{"description":"Stable identity of a calculated column; send it back unchanged when updating the view","type":"string"},"labels":{"description":"Column labels (localized)","type":"object","additionalProperties":{"type":"string"}},"order":{"type":"number","description":"Column display order"},"role":{"description":"Column role (e.g. title, date, image, location, color)","type":"string"},"width":{"description":"Column width","type":"number"}},"required":["field","order"]}},"conditionalFormatting":{"description":"Conditional formatting rules","type":"array","items":{"type":"object","properties":{"backgroundColor":{"description":"Background color (hex string)","type":"string"},"bold":{"description":"Bold text","type":"boolean"},"comparator":{"type":"string","enum":["contains","does_not_contain","ends_with","gt","gte","is","is_empty","is_not","is_not_empty","logic","lt","lte","starts_with"],"description":"Comparator"},"expression":{"description":"Script expression, used only when comparator is 'logic'","type":"string"},"fieldName":{"type":"string","description":"Target field name"},"highlightColor":{"description":"Highlight color (hex string)","type":"string"},"icon":{"description":"Icon","type":"object","properties":{"color":{"description":"Icon color (hex string)","type":"string"},"filling":{"description":"Icon filling","anyOf":[{"type":"number","enum":[0]},{"type":"number","enum":[1]}]},"icon":{"type":"string","description":"Icon name"}},"required":["icon"]},"id":{"type":"string","description":"Stable rule id"},"italic":{"description":"Italic text","type":"boolean"},"order":{"type":"number","description":"Rule evaluation order"},"strikethrough":{"description":"Strikethrough text","type":"boolean"},"target":{"type":"string","enum":["cell","row"],"description":"Whether the rule styles a single cell or the whole row"},"textColor":{"description":"Text color (hex string)","type":"string"},"value":{"description":"Value compared against"}},"required":["comparator","fieldName","id","order","target"]}},"filter":{"description":"Stored filter conditions","type":"array","items":{"type":"object","properties":{"field":{"description":"Field name","type":"string"},"id":{"type":"string","description":"Stable condition id"},"operator":{"description":"Filter operator","type":"string"},"value":{"description":"Value compared against","type":"string"}},"required":["id"]}},"groupBy":{"description":"Grouping configuration","type":"array","items":{"type":"object","properties":{"direction":{"description":"Group order direction, defaults to ascending","type":"string","enum":["asc","desc"]},"fieldName":{"type":"string","description":"Field name"}},"required":["fieldName"]}},"sort":{"description":"Sort configuration","type":"object","properties":{"direction":{"type":"string","enum":["asc","desc"],"description":"Sort direction"},"fieldName":{"type":"string","description":"Field name"}},"required":["direction","fieldName"]}}},"visible":{"description":"Conditional visibility logic: a boolean, or a script expression (as { $nx: <script> }) evaluated at render time","anyOf":[{"type":"boolean"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"visibleRoles":{"description":"Page: roles allowed to view this page","type":"array","items":{"type":"string"}},"widgetName":{"description":"CustomWidget: folder name under the workspace widgets directory","type":"string"},"widgetProps":{"description":"CustomWidget: property values, each static or a script expression (as { $nx: <script> })","type":"object","additionalProperties":{"anyOf":[{"type":"boolean"},{"type":"number"},{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]}},"width":{"description":"Component width: number = legacy px, string = percentage e.g. \"50%\"","type":["number","string"]}},"required":["id","kind","type"]}},"hideNavigation":{"description":"Hide module from navigation","type":"boolean"},"icon":{"description":"Module icon","type":"object","properties":{"color":{"description":"Icon color (hex string)","type":"string"},"filling":{"description":"Icon filling","anyOf":[{"type":"number","enum":[0]},{"type":"number","enum":[1]}]},"icon":{"type":"string","description":"Icon name"}},"required":["icon"]},"isHidden":{"description":"Hide module","type":"boolean"},"labels":{"description":"Module labels (localized)","type":"object","additionalProperties":{"type":"string"}},"name":{"type":"string"},"openRoles":{"description":"Module open roles","type":"array","items":{"type":"string"}},"tables":{"type":"array","items":{"type":"object","properties":{"canCreate":{"description":"Script expression gating record creation","type":"string"},"canDelete":{"description":"Script expression gating record deletion","type":"string"},"canRead":{"description":"Script expression gating record read access","type":"string"},"canWrite":{"description":"Script expression gating record write access","type":"string"},"createRoles":{"description":"Roles allowed to create records","type":"array","items":{"type":"string"}},"deleteRoles":{"description":"Roles allowed to delete records","type":"array","items":{"type":"string"}},"fields":{"type":"array","items":{"type":"object","properties":{"binding":{"description":"Read-only: internal binding reference, format not yet specified","type":"string"},"canRead":{"description":"Script expression gating field-level read access","type":"string"},"canWrite":{"description":"Script expression gating field-level write access","type":"string"},"defaultValue":{"description":"Default value applied when a record is created: a literal value (an array of option ids for multi/dmulti), or a script expression (as { $nx: <script> }) evaluated at creation time","anyOf":[{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]},{"type":["boolean","null","number","string"]},{"type":"array","items":{"type":"string"}}]},"expression":{"description":"Expression (for function type)","type":"string"},"index":{"description":"Field is indexed","type":"boolean"},"labels":{"description":"Field labels (localized)","type":"object","additionalProperties":{"type":"string"}},"name":{"type":"string","description":"Field name"},"onUpdate":{"description":"Script expression run as a row trigger when the field value changes","type":"string"},"optionColor":{"description":"Color expression for dchoice/dmulti fields","type":"string"},"optionIcon":{"description":"Icon expression for dchoice/dmulti fields","type":"string"},"optionName":{"description":"Display name expression for dchoice/dmulti fields","type":"string"},"options":{"description":"Options array for choice/multi fields, or selection expression for dchoice/dmulti fields","anyOf":[{"type":"array","items":{"type":"object","properties":{"color":{"description":"Option color (hex string)","type":"string"},"icon":{"description":"Option icon name","type":"string"},"id":{"type":"string","description":"Option id, a string the caller can set and change"},"label":{"type":"string","description":"Option text in the default language"},"labels":{"description":"Option text per language","type":"object","additionalProperties":{"type":"string"}},"order":{"type":"number","description":"Option display order"},"textColor":{"description":"Option text color (hex string)","type":"string"}},"required":["id","label","order"]}},{"type":"string"}]},"readRoles":{"description":"Roles allowed to read the field","type":"array","items":{"type":"string"}},"refTableName":{"description":"Reference table name","type":"string"},"required":{"description":"Field is required","type":"boolean"},"search":{"description":"Field is searchable","type":"boolean"},"syncedFrom":{"description":"Source column this field syncs from. Read-only unless the table has two-way sync with updates enabled, in which case every synced field except the key column is writable.","type":"string"},"type":{"type":"string","enum":["any","appointment","boolean","choice","color","date","dchoice","dmulti","file","function","html","icon","lambda","multi","number","react","reference","reverse","rowId","string","styled","time","timeinterval","timestamp","unknown","user","void"],"description":"Field type"},"unique":{"description":"Field is unique","type":"boolean"},"variant":{"description":"Field variant (for string type)","type":"string"},"writeRoles":{"description":"Roles allowed to write to the field","type":"array","items":{"type":"string"}}},"required":["name","type"]}},"hasFiles":{"description":"Enable files for the table","type":"boolean"},"hasGlobalSearch":{"description":"Enable global search for the table","type":"boolean"},"hasHistory":{"description":"Enable history for the table","type":"boolean"},"icon":{"description":"Table icon","type":"object","properties":{"color":{"description":"Icon color (hex string)","type":"string"},"filling":{"description":"Icon filling","anyOf":[{"type":"number","enum":[0]},{"type":"number","enum":[1]}]},"icon":{"type":"string","description":"Icon name"}},"required":["icon"]},"isEmailLinkingEnabled":{"description":"Enable email linking for the table","type":"boolean"},"isHidden":{"description":"Hide the table","type":"boolean"},"labels":{"description":"Table labels (localized)","type":"object","additionalProperties":{"type":"string"}},"name":{"type":"string"},"onCreate":{"description":"Script expression run as a trigger after a record is created","type":"string"},"onDelete":{"description":"Script expression run as a trigger when a record is deleted","type":"string"},"onUpdate":{"description":"Script expression run as a trigger after a record is updated","type":"string"},"readRoles":{"description":"Roles allowed to read records","type":"array","items":{"type":"string"}},"writeRoles":{"description":"Roles allowed to update records","type":"array","items":{"type":"string"}}},"required":["name"]}}},"description":"Module details"}},"required":["data"]},"ErrorResponse":{"type":"object","properties":{"error":{"type":"object","properties":{"message":{"type":"string","description":"Error message"}}}},"required":["error"]}}},"paths":{"/api/v1/workspace/{workspaceId}/modules":{"post":{"operationId":"ModulesV1Controller_createModule","summary":"Create a module","description":"Creates a new module in a workspace","parameters":[{"name":"workspaceId","required":true,"in":"path","description":"Workspace ID","schema":{"minLength":12,"maxLength":12,"pattern":"^[a-z0-9]+$","type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateModuleBody"}}}},"responses":{"201":{"description":"Module created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModuleResponse"}}}},"400":{"description":"Bad request (e.g., module already exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Workspace not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"tags":["Modules"]}}}}
```

## Get a specific module

> Retrieves detailed information about a specific module, including its tables

```json
{"openapi":"3.0.0","info":{"title":"Ninox Public API","version":"1.0.0"},"security":[{"bearer":[]}],"components":{"securitySchemes":{"bearer":{"scheme":"bearer","bearerFormat":"API Key","description":"Enter your Workspace API key. \n\n API keys can be generated and managed within the **Workspace Integration** settings in the Ninox app.","in":"header","name":"Authorization","type":"http"}},"schemas":{"ModuleResponse":{"type":"object","properties":{"data":{"type":"object","properties":{"afterOpen":{"description":"Script expression run in the browser each time the app is opened","type":"string"},"components":{"description":"Module components (pages, containers, widgets)","type":"array","items":{"type":"object","properties":{"afterHide":{"description":"Container directly under Tabs: script run when this tab stops being shown","type":"string"},"aggregation":{"description":"MetricCard: aggregation function","type":"string","enum":["avg","count","max","median","min","sum"]},"annualRecurring":{"description":"Calendar: render every record on the same day/month every year","type":"boolean"},"arrangement":{"description":"Page/Container: layout direction","type":"string","enum":["grid","ltr","row","ttb"]},"background":{"description":"Container/Page/Text: background","anyOf":[{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"beforeShow":{"description":"Container directly under Tabs: script run when this tab is shown","type":"string"},"border":{"description":"Container: border","anyOf":[{"type":"object","properties":{"color":{"type":"string"},"style":{"type":"string","enum":["dashed","dotted","double","none","solid"]},"width":{"type":"string"}},"required":["style","width"]},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"calendarType":{"description":"Calendar: display type","type":"string"},"cardBorder":{"description":"Kanban: card border CSS shorthand, Normal mode only","type":"string"},"cardFont":{"description":"Kanban: card font style tokens, Normal mode only","type":"string"},"cardPadding":{"description":"Kanban: card padding in px, Normal mode only","type":"number"},"cardRadius":{"description":"Kanban: card corner radius in px, Normal mode only","type":"number"},"chartConfig":{"description":"Chart: chart type, axes and data series","type":"object","properties":{"chartType":{"type":"string","enum":["bar","line","pie","funnel","ranking","board"]},"dataSets":{"type":"array","items":{"type":"object","properties":{"aggregation":{"type":"string","enum":["average","count","max","median","min","none","sum"]},"color":{"description":"Series color (hex string)","type":"string"},"fieldName":{"description":"Field name this series reads from","type":"string"},"labels":{"description":"Series labels (localized)","type":"object","additionalProperties":{"type":"string"}}}}},"donut":{"type":"boolean"},"labelPosition":{"type":"string","enum":["bottom","center","inside","outside","top"]},"legend":{"type":"object","properties":{"show":{"type":"boolean"}}},"limit":{"description":"ranking only: how many categories it shows","type":"integer","minimum":1,"maximum":20},"orientation":{"type":"string","enum":["horizontal","vertical"]},"showDataTable":{"type":"boolean"},"showLabels":{"type":"boolean"},"showPoints":{"type":"boolean"},"showTitle":{"type":"boolean"},"smooth":{"type":"boolean"},"stacked":{"type":"boolean"},"style":{"type":"string","enum":["default","half_donut","pad_angle","rounded_corner"]},"tooltips":{"type":"object","properties":{"show":{"type":"boolean"}}},"xAxis":{"type":"object","properties":{"fieldName":{"description":"X-axis field name, null removes it","type":["string","null"]},"groupBy":{"type":"string","enum":["daily","monthly","none","quarterly","weekly","yearly"]},"show":{"type":"boolean"}}},"yAxis":{"type":"object","properties":{"show":{"type":"boolean"}}}},"required":["chartType","dataSets","xAxis"]},"color":{"description":"Text: text color (hex string). Button: theme color name","anyOf":[{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"colorFieldName":{"description":"Map: marker color field name","type":"string"},"constraints":{"description":"FieldComponent: script limiting which records a reference can link to, needs schema:manage-permissions","type":"string"},"content":{"description":"Text: content, localized or a script expression","anyOf":[{"type":"object","additionalProperties":{"type":"string"}},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"customStyle":{"description":"Text: full custom style config, opaque, used only when quickStyle is \"custom\"","type":"object","additionalProperties":{}},"dataPoint":{"description":"'conditional' replaces table/filter/… with the `value` script","type":"string","enum":["conditional","normal"]},"defaultValue":{"description":"InputComponent: initial value, or { $nx: <script> }","anyOf":[{"type":"boolean"},{"type":"number"},{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"disabled":{"description":"Button/FieldComponent: disable the control, a boolean or a script","anyOf":[{"type":"boolean"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"display":{"description":"MetricCard: display formatting and trend configuration","type":"object","properties":{"color":{"type":"string"},"format":{"type":"string","enum":["compact","currency","number","percentage"]},"icon":{"type":"string"},"trend":{"type":"object","properties":{"customPeriodEnd":{"description":"ISO date (YYYY-MM-DD), for period \"custom\"","type":"string"},"customPeriodStart":{"description":"ISO date (YYYY-MM-DD), for period \"custom\"","type":"string"},"format":{"type":"string","enum":["absolute","percentage"]},"isShown":{"type":"boolean"},"period":{"type":"string","enum":["custom","last_month","last_week","last_year","previous_period","yesterday"]},"positiveDirection":{"type":"string","enum":["down","up"]}},"required":["format","isShown"]}},"required":["color","format","trend"]},"displayAs":{"description":"FieldComponent: how a yes/no field is shown","type":"string"},"expression":{"description":"DynamicHTMLComponent: script returning the HTML to render","type":"string"},"fieldIdDataPoint":{"description":"MetricCard: 'conditional' replaces table/filter/fieldName/aggregation with fieldIdValue","type":"string","enum":["conditional","normal"]},"fieldIdValue":{"description":"MetricCard: whole-dataset script producing the final number when fieldIdDataPoint is conditional","type":"string"},"fieldName":{"description":"MetricCard/Calendar/Map: primary bound field name","type":"string"},"filter":{"description":"MetricCard/Chart: stored filter conditions","type":"array","items":{"type":"object","properties":{"field":{"description":"Field name","type":"string"},"id":{"type":"string","description":"Stable condition id"},"operator":{"description":"Filter operator","type":"string"},"value":{"description":"Value compared against","type":"string"}},"required":["id"]}},"flex":{"description":"Container: flex sizing","anyOf":[{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"ganttConfig":{"description":"Gantt: which fields the bars/milestones/dependencies read from","type":"object","properties":{"baselineEndFieldName":{"description":"Planned end field, rendered as a ghost bar","type":["string","null"]},"baselineStartFieldName":{"description":"Planned start field, rendered as a ghost bar","type":["string","null"]},"dependencyDirection":{"type":"string","enum":["predecessor","successor"]},"dependencyFieldName":{"description":"A reference field pointing back at this table","type":["string","null"]},"disableDragAndDrop":{"type":"boolean"},"endFieldName":{"type":["string","null"]},"hideTitleColumn":{"type":"boolean"},"hideWeekends":{"type":"boolean"},"milestoneFieldName":{"type":["string","null"]},"progressFieldName":{"type":["string","null"]},"showCriticalPath":{"type":"boolean"},"showWeekends":{"type":"boolean"},"startFieldName":{"type":["string","null"]},"timeScale":{"type":"string","enum":["day","month","quarter","week"]},"titleColumnFieldName":{"type":["string","null"]},"titleColumnWidth":{"type":"number"}}},"gap":{"description":"Page/Container: gap between children","anyOf":[{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"globalFilterBinding":{"description":"MetricCard: field names this card reacts to for global page filters","type":"array","items":{"type":"string"}},"gridPreset":{"description":"Container: grid layout preset","anyOf":[{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"groupByFieldName":{"description":"Kanban: lane grouping field name","type":"string"},"height":{"description":"Component height","type":"number"},"icon":{"description":"Page: icon","type":"object","properties":{"color":{"description":"Icon color (hex string)","type":"string"},"filling":{"description":"Icon filling","anyOf":[{"type":"number","enum":[0]},{"type":"number","enum":[1]}]},"icon":{"type":"string","description":"Icon name"}},"required":["icon"]},"iconLeft":{"description":"Button/FieldComponent: icon before the label","anyOf":[{"type":"object","properties":{"color":{"description":"Icon color (hex string)","type":"string"},"filling":{"description":"Icon filling","anyOf":[{"type":"number","enum":[0]},{"type":"number","enum":[1]}]},"icon":{"type":"string","description":"Icon name"}},"required":["icon"]},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"iconRight":{"description":"Button/FieldComponent: icon after the label","anyOf":[{"type":"object","properties":{"color":{"description":"Icon color (hex string)","type":"string"},"filling":{"description":"Icon filling","anyOf":[{"type":"number","enum":[0]},{"type":"number","enum":[1]}]},"icon":{"type":"string","description":"Icon name"}},"required":["icon"]},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"id":{"type":"string","description":"Component id"},"imagePosition":{"description":"Kanban: card image crop/anchor, Normal mode only","type":"object","properties":{"position":{"type":"string"},"size":{"type":"string"}}},"isCompact":{"description":"Accordion: compact sections","type":"boolean"},"isHidden":{"description":"Page: hide from navigation","type":"boolean"},"isMarkdownEnabled":{"description":"FieldComponent: render a rich text field as markdown","type":"boolean"},"isSpreadsheetMode":{"description":"Table/FieldComponent: spreadsheet-style editing","type":"boolean"},"kind":{"type":"string","deprecated":true,"description":"Deprecated, use type. Same value, kept so existing integrations keep working"},"labelPosition":{"description":"FieldComponent: top, left, inside or hidden","type":"string"},"labels":{"description":"Component labels (localized)","type":"object","additionalProperties":{"type":"string"}},"mapTypeId":{"description":"Map: base layer type","type":"string"},"margin":{"description":"Container: margin","anyOf":[{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"name":{"description":"Component name","type":"string"},"onChange":{"description":"Tabs/FieldComponent: script run when the value changes","type":"string"},"onClick":{"description":"Button: script run on click","type":"string"},"order":{"description":"Component display order","type":"number"},"overflow":{"description":"Container: overflow behavior","anyOf":[{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"padding":{"description":"Page/Container: padding","anyOf":[{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"parentId":{"description":"Parent component id (forms the component tree)","type":"string"},"placeholder":{"description":"FieldComponent: placeholder, localized, plain or a script","anyOf":[{"type":"object","additionalProperties":{"type":"string"}},{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"quickStyle":{"description":"Text: style preset","anyOf":[{"type":"string","enum":["body-md","body-sm","custom","title-lg","title-md","title-sm"]},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"radius":{"description":"Container/Text: corner radius","anyOf":[{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"remember":{"description":"InputComponent: how long the value is kept","type":"string","enum":["localStorage","memory","url"]},"shadow":{"description":"Container: shadow","anyOf":[{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"shadowDom":{"description":"DynamicHTMLComponent: render inside a shadow DOM","type":"boolean"},"showAs":{"description":"FieldComponent: how the value is shown (e.g. popup, combobox)","type":"string"},"showBulkActions":{"description":"Table/FieldComponent: show bulk actions","type":"boolean"},"showCalendarType":{"description":"Calendar: show the calendar type switcher","type":"boolean"},"showCreateButton":{"description":"Table: show the create-record button","type":"boolean"},"showCreateRow":{"description":"Table: show the inline create row","type":"boolean"},"showDataAs":{"description":"FieldComponent: script formatting a linked record","type":"string"},"showEmptyLane":{"description":"Kanban: show lanes with no cards","type":"boolean"},"showLinkExistingRecord":{"description":"FieldComponent: offer linking an existing record","type":"boolean"},"showMetadata":{"description":"FieldComponent: show file metadata","type":"boolean"},"showOutlines":{"description":"Page: show layout outlines in the editor","type":"boolean"},"showSearchField":{"description":"Table/Kanban/Gantt/Calendar/Map: show the search field","type":"boolean"},"showTimeScaleSelector":{"description":"Gantt: let the viewer switch time scale","type":"boolean"},"showTitle":{"description":"Table: show the table title","type":"boolean"},"size":{"description":"Button: sm, md or lg","anyOf":[{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"tableName":{"description":"Table this component reads from (Chart/Table/Kanban/Gantt/Calendar/Map/MetricCard)","type":"string"},"textAlign":{"description":"Text: alignment","type":"string","enum":["text-center","text-left","text-right"]},"titleFieldName":{"description":"Map: marker title field name","type":"string"},"tooltip":{"description":"FieldComponent: tooltip text","type":"string"},"type":{"type":"string","description":"Component type (e.g. Container, Button, Text, Page), the property the create and update routes and the module definition take"},"value":{"description":"Script used instead of table/filter/… when dataPoint is conditional","type":"string"},"valueSpec":{"description":"InputComponent: the type of the value, shaped like a field type, a reference has refTableName","type":"object","properties":{"type":{"type":"string"}},"required":["type"],"additionalProperties":{}},"valueType":{"description":"InputComponent: legacy value type, valueSpec wins where both are set","type":"string"},"variant":{"description":"Button/Accordion/Tabs: visual variant, InputComponent: text, email, phone, url, ...","anyOf":[{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"view":{"description":"Table/MetricCard/Kanban/Gantt/Calendar/Map: columns/filter/groupBy/sort configuration","type":"object","properties":{"columns":{"description":"View columns","type":"array","items":{"type":"object","properties":{"agg":{"description":"Aggregation function applied to the column","type":"string"},"conditionalStyling":{"description":"Legacy per-column conditional styling rules","type":"array","items":{"type":"object","properties":{"background":{"description":"Background color (hex string)","type":"string"},"cell":{"description":"Target cell","type":"string"},"color":{"description":"Icon color (hex string)","type":"string"},"icon":{"description":"Icon name","type":"string"},"operand":{"type":"string","description":"Comparator"},"value":{"type":"string","description":"Value compared against"}},"required":["operand","value"]}},"field":{"type":"string","description":"Field name, or a script expression for a calculated column"},"hidden":{"description":"Column retained but hidden from the grid","type":"boolean"},"id":{"description":"Stable identity of a calculated column; send it back unchanged when updating the view","type":"string"},"labels":{"description":"Column labels (localized)","type":"object","additionalProperties":{"type":"string"}},"order":{"type":"number","description":"Column display order"},"role":{"description":"Column role (e.g. title, date, image, location, color)","type":"string"},"width":{"description":"Column width","type":"number"}},"required":["field","order"]}},"conditionalFormatting":{"description":"Conditional formatting rules","type":"array","items":{"type":"object","properties":{"backgroundColor":{"description":"Background color (hex string)","type":"string"},"bold":{"description":"Bold text","type":"boolean"},"comparator":{"type":"string","enum":["contains","does_not_contain","ends_with","gt","gte","is","is_empty","is_not","is_not_empty","logic","lt","lte","starts_with"],"description":"Comparator"},"expression":{"description":"Script expression, used only when comparator is 'logic'","type":"string"},"fieldName":{"type":"string","description":"Target field name"},"highlightColor":{"description":"Highlight color (hex string)","type":"string"},"icon":{"description":"Icon","type":"object","properties":{"color":{"description":"Icon color (hex string)","type":"string"},"filling":{"description":"Icon filling","anyOf":[{"type":"number","enum":[0]},{"type":"number","enum":[1]}]},"icon":{"type":"string","description":"Icon name"}},"required":["icon"]},"id":{"type":"string","description":"Stable rule id"},"italic":{"description":"Italic text","type":"boolean"},"order":{"type":"number","description":"Rule evaluation order"},"strikethrough":{"description":"Strikethrough text","type":"boolean"},"target":{"type":"string","enum":["cell","row"],"description":"Whether the rule styles a single cell or the whole row"},"textColor":{"description":"Text color (hex string)","type":"string"},"value":{"description":"Value compared against"}},"required":["comparator","fieldName","id","order","target"]}},"filter":{"description":"Stored filter conditions","type":"array","items":{"type":"object","properties":{"field":{"description":"Field name","type":"string"},"id":{"type":"string","description":"Stable condition id"},"operator":{"description":"Filter operator","type":"string"},"value":{"description":"Value compared against","type":"string"}},"required":["id"]}},"groupBy":{"description":"Grouping configuration","type":"array","items":{"type":"object","properties":{"direction":{"description":"Group order direction, defaults to ascending","type":"string","enum":["asc","desc"]},"fieldName":{"type":"string","description":"Field name"}},"required":["fieldName"]}},"sort":{"description":"Sort configuration","type":"object","properties":{"direction":{"type":"string","enum":["asc","desc"],"description":"Sort direction"},"fieldName":{"type":"string","description":"Field name"}},"required":["direction","fieldName"]}}},"visible":{"description":"Conditional visibility logic: a boolean, or a script expression (as { $nx: <script> }) evaluated at render time","anyOf":[{"type":"boolean"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"visibleRoles":{"description":"Page: roles allowed to view this page","type":"array","items":{"type":"string"}},"widgetName":{"description":"CustomWidget: folder name under the workspace widgets directory","type":"string"},"widgetProps":{"description":"CustomWidget: property values, each static or a script expression (as { $nx: <script> })","type":"object","additionalProperties":{"anyOf":[{"type":"boolean"},{"type":"number"},{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]}},"width":{"description":"Component width: number = legacy px, string = percentage e.g. \"50%\"","type":["number","string"]}},"required":["id","kind","type"]}},"hideNavigation":{"description":"Hide module from navigation","type":"boolean"},"icon":{"description":"Module icon","type":"object","properties":{"color":{"description":"Icon color (hex string)","type":"string"},"filling":{"description":"Icon filling","anyOf":[{"type":"number","enum":[0]},{"type":"number","enum":[1]}]},"icon":{"type":"string","description":"Icon name"}},"required":["icon"]},"isHidden":{"description":"Hide module","type":"boolean"},"labels":{"description":"Module labels (localized)","type":"object","additionalProperties":{"type":"string"}},"name":{"type":"string"},"openRoles":{"description":"Module open roles","type":"array","items":{"type":"string"}},"tables":{"type":"array","items":{"type":"object","properties":{"canCreate":{"description":"Script expression gating record creation","type":"string"},"canDelete":{"description":"Script expression gating record deletion","type":"string"},"canRead":{"description":"Script expression gating record read access","type":"string"},"canWrite":{"description":"Script expression gating record write access","type":"string"},"createRoles":{"description":"Roles allowed to create records","type":"array","items":{"type":"string"}},"deleteRoles":{"description":"Roles allowed to delete records","type":"array","items":{"type":"string"}},"fields":{"type":"array","items":{"type":"object","properties":{"binding":{"description":"Read-only: internal binding reference, format not yet specified","type":"string"},"canRead":{"description":"Script expression gating field-level read access","type":"string"},"canWrite":{"description":"Script expression gating field-level write access","type":"string"},"defaultValue":{"description":"Default value applied when a record is created: a literal value (an array of option ids for multi/dmulti), or a script expression (as { $nx: <script> }) evaluated at creation time","anyOf":[{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]},{"type":["boolean","null","number","string"]},{"type":"array","items":{"type":"string"}}]},"expression":{"description":"Expression (for function type)","type":"string"},"index":{"description":"Field is indexed","type":"boolean"},"labels":{"description":"Field labels (localized)","type":"object","additionalProperties":{"type":"string"}},"name":{"type":"string","description":"Field name"},"onUpdate":{"description":"Script expression run as a row trigger when the field value changes","type":"string"},"optionColor":{"description":"Color expression for dchoice/dmulti fields","type":"string"},"optionIcon":{"description":"Icon expression for dchoice/dmulti fields","type":"string"},"optionName":{"description":"Display name expression for dchoice/dmulti fields","type":"string"},"options":{"description":"Options array for choice/multi fields, or selection expression for dchoice/dmulti fields","anyOf":[{"type":"array","items":{"type":"object","properties":{"color":{"description":"Option color (hex string)","type":"string"},"icon":{"description":"Option icon name","type":"string"},"id":{"type":"string","description":"Option id, a string the caller can set and change"},"label":{"type":"string","description":"Option text in the default language"},"labels":{"description":"Option text per language","type":"object","additionalProperties":{"type":"string"}},"order":{"type":"number","description":"Option display order"},"textColor":{"description":"Option text color (hex string)","type":"string"}},"required":["id","label","order"]}},{"type":"string"}]},"readRoles":{"description":"Roles allowed to read the field","type":"array","items":{"type":"string"}},"refTableName":{"description":"Reference table name","type":"string"},"required":{"description":"Field is required","type":"boolean"},"search":{"description":"Field is searchable","type":"boolean"},"syncedFrom":{"description":"Source column this field syncs from. Read-only unless the table has two-way sync with updates enabled, in which case every synced field except the key column is writable.","type":"string"},"type":{"type":"string","enum":["any","appointment","boolean","choice","color","date","dchoice","dmulti","file","function","html","icon","lambda","multi","number","react","reference","reverse","rowId","string","styled","time","timeinterval","timestamp","unknown","user","void"],"description":"Field type"},"unique":{"description":"Field is unique","type":"boolean"},"variant":{"description":"Field variant (for string type)","type":"string"},"writeRoles":{"description":"Roles allowed to write to the field","type":"array","items":{"type":"string"}}},"required":["name","type"]}},"hasFiles":{"description":"Enable files for the table","type":"boolean"},"hasGlobalSearch":{"description":"Enable global search for the table","type":"boolean"},"hasHistory":{"description":"Enable history for the table","type":"boolean"},"icon":{"description":"Table icon","type":"object","properties":{"color":{"description":"Icon color (hex string)","type":"string"},"filling":{"description":"Icon filling","anyOf":[{"type":"number","enum":[0]},{"type":"number","enum":[1]}]},"icon":{"type":"string","description":"Icon name"}},"required":["icon"]},"isEmailLinkingEnabled":{"description":"Enable email linking for the table","type":"boolean"},"isHidden":{"description":"Hide the table","type":"boolean"},"labels":{"description":"Table labels (localized)","type":"object","additionalProperties":{"type":"string"}},"name":{"type":"string"},"onCreate":{"description":"Script expression run as a trigger after a record is created","type":"string"},"onDelete":{"description":"Script expression run as a trigger when a record is deleted","type":"string"},"onUpdate":{"description":"Script expression run as a trigger after a record is updated","type":"string"},"readRoles":{"description":"Roles allowed to read records","type":"array","items":{"type":"string"}},"writeRoles":{"description":"Roles allowed to update records","type":"array","items":{"type":"string"}}},"required":["name"]}}},"description":"Module details"}},"required":["data"]},"ErrorResponse":{"type":"object","properties":{"error":{"type":"object","properties":{"message":{"type":"string","description":"Error message"}}}},"required":["error"]}}},"paths":{"/api/v1/workspace/{workspaceId}/modules/{moduleName}":{"get":{"operationId":"ModulesV1Controller_getModule","summary":"Get a specific module","description":"Retrieves detailed information about a specific module, including its tables","parameters":[{"name":"moduleName","required":true,"in":"path","description":"Module name","schema":{"minLength":1,"maxLength":100,"pattern":"^[a-z0-9_]+$","type":"string"}},{"name":"workspaceId","required":true,"in":"path","description":"Workspace ID","schema":{"minLength":12,"maxLength":12,"pattern":"^[a-z0-9]+$","type":"string"}}],"responses":{"200":{"description":"Module details retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModuleResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Module not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"tags":["Modules"]}}}}
```

## Delete a module

> Deletes a module in a workspace

```json
{"openapi":"3.0.0","info":{"title":"Ninox Public API","version":"1.0.0"},"security":[{"bearer":[]}],"components":{"securitySchemes":{"bearer":{"scheme":"bearer","bearerFormat":"API Key","description":"Enter your Workspace API key. \n\n API keys can be generated and managed within the **Workspace Integration** settings in the Ninox app.","in":"header","name":"Authorization","type":"http"}},"schemas":{"DeleteModuleResponse":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Deleted module id"}}}},"required":["data"]},"ErrorResponse":{"type":"object","properties":{"error":{"type":"object","properties":{"message":{"type":"string","description":"Error message"}}}},"required":["error"]}}},"paths":{"/api/v1/workspace/{workspaceId}/modules/{moduleName}":{"delete":{"operationId":"ModulesV1Controller_deleteModule","summary":"Delete a module","description":"Deletes a module in a workspace","parameters":[{"name":"moduleName","required":true,"in":"path","description":"Module name","schema":{"minLength":1,"maxLength":100,"pattern":"^[a-z0-9_]+$","type":"string"}},{"name":"workspaceId","required":true,"in":"path","description":"Workspace ID","schema":{"minLength":12,"maxLength":12,"pattern":"^[a-z0-9]+$","type":"string"}}],"responses":{"200":{"description":"Module deleted successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteModuleResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Module not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"tags":["Modules"]}}}}
```

## Update a module

> Updates an existing module in a workspace

```json
{"openapi":"3.0.0","info":{"title":"Ninox Public API","version":"1.0.0"},"security":[{"bearer":[]}],"components":{"securitySchemes":{"bearer":{"scheme":"bearer","bearerFormat":"API Key","description":"Enter your Workspace API key. \n\n API keys can be generated and managed within the **Workspace Integration** settings in the Ninox app.","in":"header","name":"Authorization","type":"http"}},"schemas":{"UpdateModuleBody":{"type":"object","properties":{"afterOpen":{"description":"Script expression run in the browser each time the app is opened. Needs schema:write plus records:write; null removes the script and is accepted","type":"array","items":{"type":"string"}},"name":{"description":"Module name","type":"string","minLength":1,"maxLength":100,"pattern":"^[a-z0-9_]+$"},"hideNavigation":{"description":"Hide module from navigation","type":"boolean"},"icon":{"description":"Module icon","type":"object","properties":{"color":{"type":"string"},"filling":{"anyOf":[{"type":"number","enum":[0]},{"type":"number","enum":[1]}]},"icon":{"type":"string","minLength":1}}},"isHidden":{"description":"Hide module","type":"boolean"},"labels":{"description":"Module labels (localized)","type":"object","additionalProperties":{"type":"string","minLength":1,"maxLength":100}},"openRoles":{"description":"Module open roles","minItems":1,"maxItems":2,"type":"array","items":{"type":"string","enum":["admin","editor"]}}},"description":"Update Module request body"},"ModuleResponse":{"type":"object","properties":{"data":{"type":"object","properties":{"afterOpen":{"description":"Script expression run in the browser each time the app is opened","type":"string"},"components":{"description":"Module components (pages, containers, widgets)","type":"array","items":{"type":"object","properties":{"afterHide":{"description":"Container directly under Tabs: script run when this tab stops being shown","type":"string"},"aggregation":{"description":"MetricCard: aggregation function","type":"string","enum":["avg","count","max","median","min","sum"]},"annualRecurring":{"description":"Calendar: render every record on the same day/month every year","type":"boolean"},"arrangement":{"description":"Page/Container: layout direction","type":"string","enum":["grid","ltr","row","ttb"]},"background":{"description":"Container/Page/Text: background","anyOf":[{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"beforeShow":{"description":"Container directly under Tabs: script run when this tab is shown","type":"string"},"border":{"description":"Container: border","anyOf":[{"type":"object","properties":{"color":{"type":"string"},"style":{"type":"string","enum":["dashed","dotted","double","none","solid"]},"width":{"type":"string"}},"required":["style","width"]},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"calendarType":{"description":"Calendar: display type","type":"string"},"cardBorder":{"description":"Kanban: card border CSS shorthand, Normal mode only","type":"string"},"cardFont":{"description":"Kanban: card font style tokens, Normal mode only","type":"string"},"cardPadding":{"description":"Kanban: card padding in px, Normal mode only","type":"number"},"cardRadius":{"description":"Kanban: card corner radius in px, Normal mode only","type":"number"},"chartConfig":{"description":"Chart: chart type, axes and data series","type":"object","properties":{"chartType":{"type":"string","enum":["bar","line","pie","funnel","ranking","board"]},"dataSets":{"type":"array","items":{"type":"object","properties":{"aggregation":{"type":"string","enum":["average","count","max","median","min","none","sum"]},"color":{"description":"Series color (hex string)","type":"string"},"fieldName":{"description":"Field name this series reads from","type":"string"},"labels":{"description":"Series labels (localized)","type":"object","additionalProperties":{"type":"string"}}}}},"donut":{"type":"boolean"},"labelPosition":{"type":"string","enum":["bottom","center","inside","outside","top"]},"legend":{"type":"object","properties":{"show":{"type":"boolean"}}},"limit":{"description":"ranking only: how many categories it shows","type":"integer","minimum":1,"maximum":20},"orientation":{"type":"string","enum":["horizontal","vertical"]},"showDataTable":{"type":"boolean"},"showLabels":{"type":"boolean"},"showPoints":{"type":"boolean"},"showTitle":{"type":"boolean"},"smooth":{"type":"boolean"},"stacked":{"type":"boolean"},"style":{"type":"string","enum":["default","half_donut","pad_angle","rounded_corner"]},"tooltips":{"type":"object","properties":{"show":{"type":"boolean"}}},"xAxis":{"type":"object","properties":{"fieldName":{"description":"X-axis field name, null removes it","type":["string","null"]},"groupBy":{"type":"string","enum":["daily","monthly","none","quarterly","weekly","yearly"]},"show":{"type":"boolean"}}},"yAxis":{"type":"object","properties":{"show":{"type":"boolean"}}}},"required":["chartType","dataSets","xAxis"]},"color":{"description":"Text: text color (hex string). Button: theme color name","anyOf":[{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"colorFieldName":{"description":"Map: marker color field name","type":"string"},"constraints":{"description":"FieldComponent: script limiting which records a reference can link to, needs schema:manage-permissions","type":"string"},"content":{"description":"Text: content, localized or a script expression","anyOf":[{"type":"object","additionalProperties":{"type":"string"}},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"customStyle":{"description":"Text: full custom style config, opaque, used only when quickStyle is \"custom\"","type":"object","additionalProperties":{}},"dataPoint":{"description":"'conditional' replaces table/filter/… with the `value` script","type":"string","enum":["conditional","normal"]},"defaultValue":{"description":"InputComponent: initial value, or { $nx: <script> }","anyOf":[{"type":"boolean"},{"type":"number"},{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"disabled":{"description":"Button/FieldComponent: disable the control, a boolean or a script","anyOf":[{"type":"boolean"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"display":{"description":"MetricCard: display formatting and trend configuration","type":"object","properties":{"color":{"type":"string"},"format":{"type":"string","enum":["compact","currency","number","percentage"]},"icon":{"type":"string"},"trend":{"type":"object","properties":{"customPeriodEnd":{"description":"ISO date (YYYY-MM-DD), for period \"custom\"","type":"string"},"customPeriodStart":{"description":"ISO date (YYYY-MM-DD), for period \"custom\"","type":"string"},"format":{"type":"string","enum":["absolute","percentage"]},"isShown":{"type":"boolean"},"period":{"type":"string","enum":["custom","last_month","last_week","last_year","previous_period","yesterday"]},"positiveDirection":{"type":"string","enum":["down","up"]}},"required":["format","isShown"]}},"required":["color","format","trend"]},"displayAs":{"description":"FieldComponent: how a yes/no field is shown","type":"string"},"expression":{"description":"DynamicHTMLComponent: script returning the HTML to render","type":"string"},"fieldIdDataPoint":{"description":"MetricCard: 'conditional' replaces table/filter/fieldName/aggregation with fieldIdValue","type":"string","enum":["conditional","normal"]},"fieldIdValue":{"description":"MetricCard: whole-dataset script producing the final number when fieldIdDataPoint is conditional","type":"string"},"fieldName":{"description":"MetricCard/Calendar/Map: primary bound field name","type":"string"},"filter":{"description":"MetricCard/Chart: stored filter conditions","type":"array","items":{"type":"object","properties":{"field":{"description":"Field name","type":"string"},"id":{"type":"string","description":"Stable condition id"},"operator":{"description":"Filter operator","type":"string"},"value":{"description":"Value compared against","type":"string"}},"required":["id"]}},"flex":{"description":"Container: flex sizing","anyOf":[{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"ganttConfig":{"description":"Gantt: which fields the bars/milestones/dependencies read from","type":"object","properties":{"baselineEndFieldName":{"description":"Planned end field, rendered as a ghost bar","type":["string","null"]},"baselineStartFieldName":{"description":"Planned start field, rendered as a ghost bar","type":["string","null"]},"dependencyDirection":{"type":"string","enum":["predecessor","successor"]},"dependencyFieldName":{"description":"A reference field pointing back at this table","type":["string","null"]},"disableDragAndDrop":{"type":"boolean"},"endFieldName":{"type":["string","null"]},"hideTitleColumn":{"type":"boolean"},"hideWeekends":{"type":"boolean"},"milestoneFieldName":{"type":["string","null"]},"progressFieldName":{"type":["string","null"]},"showCriticalPath":{"type":"boolean"},"showWeekends":{"type":"boolean"},"startFieldName":{"type":["string","null"]},"timeScale":{"type":"string","enum":["day","month","quarter","week"]},"titleColumnFieldName":{"type":["string","null"]},"titleColumnWidth":{"type":"number"}}},"gap":{"description":"Page/Container: gap between children","anyOf":[{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"globalFilterBinding":{"description":"MetricCard: field names this card reacts to for global page filters","type":"array","items":{"type":"string"}},"gridPreset":{"description":"Container: grid layout preset","anyOf":[{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"groupByFieldName":{"description":"Kanban: lane grouping field name","type":"string"},"height":{"description":"Component height","type":"number"},"icon":{"description":"Page: icon","type":"object","properties":{"color":{"description":"Icon color (hex string)","type":"string"},"filling":{"description":"Icon filling","anyOf":[{"type":"number","enum":[0]},{"type":"number","enum":[1]}]},"icon":{"type":"string","description":"Icon name"}},"required":["icon"]},"iconLeft":{"description":"Button/FieldComponent: icon before the label","anyOf":[{"type":"object","properties":{"color":{"description":"Icon color (hex string)","type":"string"},"filling":{"description":"Icon filling","anyOf":[{"type":"number","enum":[0]},{"type":"number","enum":[1]}]},"icon":{"type":"string","description":"Icon name"}},"required":["icon"]},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"iconRight":{"description":"Button/FieldComponent: icon after the label","anyOf":[{"type":"object","properties":{"color":{"description":"Icon color (hex string)","type":"string"},"filling":{"description":"Icon filling","anyOf":[{"type":"number","enum":[0]},{"type":"number","enum":[1]}]},"icon":{"type":"string","description":"Icon name"}},"required":["icon"]},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"id":{"type":"string","description":"Component id"},"imagePosition":{"description":"Kanban: card image crop/anchor, Normal mode only","type":"object","properties":{"position":{"type":"string"},"size":{"type":"string"}}},"isCompact":{"description":"Accordion: compact sections","type":"boolean"},"isHidden":{"description":"Page: hide from navigation","type":"boolean"},"isMarkdownEnabled":{"description":"FieldComponent: render a rich text field as markdown","type":"boolean"},"isSpreadsheetMode":{"description":"Table/FieldComponent: spreadsheet-style editing","type":"boolean"},"kind":{"type":"string","deprecated":true,"description":"Deprecated, use type. Same value, kept so existing integrations keep working"},"labelPosition":{"description":"FieldComponent: top, left, inside or hidden","type":"string"},"labels":{"description":"Component labels (localized)","type":"object","additionalProperties":{"type":"string"}},"mapTypeId":{"description":"Map: base layer type","type":"string"},"margin":{"description":"Container: margin","anyOf":[{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"name":{"description":"Component name","type":"string"},"onChange":{"description":"Tabs/FieldComponent: script run when the value changes","type":"string"},"onClick":{"description":"Button: script run on click","type":"string"},"order":{"description":"Component display order","type":"number"},"overflow":{"description":"Container: overflow behavior","anyOf":[{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"padding":{"description":"Page/Container: padding","anyOf":[{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"parentId":{"description":"Parent component id (forms the component tree)","type":"string"},"placeholder":{"description":"FieldComponent: placeholder, localized, plain or a script","anyOf":[{"type":"object","additionalProperties":{"type":"string"}},{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"quickStyle":{"description":"Text: style preset","anyOf":[{"type":"string","enum":["body-md","body-sm","custom","title-lg","title-md","title-sm"]},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"radius":{"description":"Container/Text: corner radius","anyOf":[{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"remember":{"description":"InputComponent: how long the value is kept","type":"string","enum":["localStorage","memory","url"]},"shadow":{"description":"Container: shadow","anyOf":[{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"shadowDom":{"description":"DynamicHTMLComponent: render inside a shadow DOM","type":"boolean"},"showAs":{"description":"FieldComponent: how the value is shown (e.g. popup, combobox)","type":"string"},"showBulkActions":{"description":"Table/FieldComponent: show bulk actions","type":"boolean"},"showCalendarType":{"description":"Calendar: show the calendar type switcher","type":"boolean"},"showCreateButton":{"description":"Table: show the create-record button","type":"boolean"},"showCreateRow":{"description":"Table: show the inline create row","type":"boolean"},"showDataAs":{"description":"FieldComponent: script formatting a linked record","type":"string"},"showEmptyLane":{"description":"Kanban: show lanes with no cards","type":"boolean"},"showLinkExistingRecord":{"description":"FieldComponent: offer linking an existing record","type":"boolean"},"showMetadata":{"description":"FieldComponent: show file metadata","type":"boolean"},"showOutlines":{"description":"Page: show layout outlines in the editor","type":"boolean"},"showSearchField":{"description":"Table/Kanban/Gantt/Calendar/Map: show the search field","type":"boolean"},"showTimeScaleSelector":{"description":"Gantt: let the viewer switch time scale","type":"boolean"},"showTitle":{"description":"Table: show the table title","type":"boolean"},"size":{"description":"Button: sm, md or lg","anyOf":[{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"tableName":{"description":"Table this component reads from (Chart/Table/Kanban/Gantt/Calendar/Map/MetricCard)","type":"string"},"textAlign":{"description":"Text: alignment","type":"string","enum":["text-center","text-left","text-right"]},"titleFieldName":{"description":"Map: marker title field name","type":"string"},"tooltip":{"description":"FieldComponent: tooltip text","type":"string"},"type":{"type":"string","description":"Component type (e.g. Container, Button, Text, Page), the property the create and update routes and the module definition take"},"value":{"description":"Script used instead of table/filter/… when dataPoint is conditional","type":"string"},"valueSpec":{"description":"InputComponent: the type of the value, shaped like a field type, a reference has refTableName","type":"object","properties":{"type":{"type":"string"}},"required":["type"],"additionalProperties":{}},"valueType":{"description":"InputComponent: legacy value type, valueSpec wins where both are set","type":"string"},"variant":{"description":"Button/Accordion/Tabs: visual variant, InputComponent: text, email, phone, url, ...","anyOf":[{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"view":{"description":"Table/MetricCard/Kanban/Gantt/Calendar/Map: columns/filter/groupBy/sort configuration","type":"object","properties":{"columns":{"description":"View columns","type":"array","items":{"type":"object","properties":{"agg":{"description":"Aggregation function applied to the column","type":"string"},"conditionalStyling":{"description":"Legacy per-column conditional styling rules","type":"array","items":{"type":"object","properties":{"background":{"description":"Background color (hex string)","type":"string"},"cell":{"description":"Target cell","type":"string"},"color":{"description":"Icon color (hex string)","type":"string"},"icon":{"description":"Icon name","type":"string"},"operand":{"type":"string","description":"Comparator"},"value":{"type":"string","description":"Value compared against"}},"required":["operand","value"]}},"field":{"type":"string","description":"Field name, or a script expression for a calculated column"},"hidden":{"description":"Column retained but hidden from the grid","type":"boolean"},"id":{"description":"Stable identity of a calculated column; send it back unchanged when updating the view","type":"string"},"labels":{"description":"Column labels (localized)","type":"object","additionalProperties":{"type":"string"}},"order":{"type":"number","description":"Column display order"},"role":{"description":"Column role (e.g. title, date, image, location, color)","type":"string"},"width":{"description":"Column width","type":"number"}},"required":["field","order"]}},"conditionalFormatting":{"description":"Conditional formatting rules","type":"array","items":{"type":"object","properties":{"backgroundColor":{"description":"Background color (hex string)","type":"string"},"bold":{"description":"Bold text","type":"boolean"},"comparator":{"type":"string","enum":["contains","does_not_contain","ends_with","gt","gte","is","is_empty","is_not","is_not_empty","logic","lt","lte","starts_with"],"description":"Comparator"},"expression":{"description":"Script expression, used only when comparator is 'logic'","type":"string"},"fieldName":{"type":"string","description":"Target field name"},"highlightColor":{"description":"Highlight color (hex string)","type":"string"},"icon":{"description":"Icon","type":"object","properties":{"color":{"description":"Icon color (hex string)","type":"string"},"filling":{"description":"Icon filling","anyOf":[{"type":"number","enum":[0]},{"type":"number","enum":[1]}]},"icon":{"type":"string","description":"Icon name"}},"required":["icon"]},"id":{"type":"string","description":"Stable rule id"},"italic":{"description":"Italic text","type":"boolean"},"order":{"type":"number","description":"Rule evaluation order"},"strikethrough":{"description":"Strikethrough text","type":"boolean"},"target":{"type":"string","enum":["cell","row"],"description":"Whether the rule styles a single cell or the whole row"},"textColor":{"description":"Text color (hex string)","type":"string"},"value":{"description":"Value compared against"}},"required":["comparator","fieldName","id","order","target"]}},"filter":{"description":"Stored filter conditions","type":"array","items":{"type":"object","properties":{"field":{"description":"Field name","type":"string"},"id":{"type":"string","description":"Stable condition id"},"operator":{"description":"Filter operator","type":"string"},"value":{"description":"Value compared against","type":"string"}},"required":["id"]}},"groupBy":{"description":"Grouping configuration","type":"array","items":{"type":"object","properties":{"direction":{"description":"Group order direction, defaults to ascending","type":"string","enum":["asc","desc"]},"fieldName":{"type":"string","description":"Field name"}},"required":["fieldName"]}},"sort":{"description":"Sort configuration","type":"object","properties":{"direction":{"type":"string","enum":["asc","desc"],"description":"Sort direction"},"fieldName":{"type":"string","description":"Field name"}},"required":["direction","fieldName"]}}},"visible":{"description":"Conditional visibility logic: a boolean, or a script expression (as { $nx: <script> }) evaluated at render time","anyOf":[{"type":"boolean"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"visibleRoles":{"description":"Page: roles allowed to view this page","type":"array","items":{"type":"string"}},"widgetName":{"description":"CustomWidget: folder name under the workspace widgets directory","type":"string"},"widgetProps":{"description":"CustomWidget: property values, each static or a script expression (as { $nx: <script> })","type":"object","additionalProperties":{"anyOf":[{"type":"boolean"},{"type":"number"},{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]}},"width":{"description":"Component width: number = legacy px, string = percentage e.g. \"50%\"","type":["number","string"]}},"required":["id","kind","type"]}},"hideNavigation":{"description":"Hide module from navigation","type":"boolean"},"icon":{"description":"Module icon","type":"object","properties":{"color":{"description":"Icon color (hex string)","type":"string"},"filling":{"description":"Icon filling","anyOf":[{"type":"number","enum":[0]},{"type":"number","enum":[1]}]},"icon":{"type":"string","description":"Icon name"}},"required":["icon"]},"isHidden":{"description":"Hide module","type":"boolean"},"labels":{"description":"Module labels (localized)","type":"object","additionalProperties":{"type":"string"}},"name":{"type":"string"},"openRoles":{"description":"Module open roles","type":"array","items":{"type":"string"}},"tables":{"type":"array","items":{"type":"object","properties":{"canCreate":{"description":"Script expression gating record creation","type":"string"},"canDelete":{"description":"Script expression gating record deletion","type":"string"},"canRead":{"description":"Script expression gating record read access","type":"string"},"canWrite":{"description":"Script expression gating record write access","type":"string"},"createRoles":{"description":"Roles allowed to create records","type":"array","items":{"type":"string"}},"deleteRoles":{"description":"Roles allowed to delete records","type":"array","items":{"type":"string"}},"fields":{"type":"array","items":{"type":"object","properties":{"binding":{"description":"Read-only: internal binding reference, format not yet specified","type":"string"},"canRead":{"description":"Script expression gating field-level read access","type":"string"},"canWrite":{"description":"Script expression gating field-level write access","type":"string"},"defaultValue":{"description":"Default value applied when a record is created: a literal value (an array of option ids for multi/dmulti), or a script expression (as { $nx: <script> }) evaluated at creation time","anyOf":[{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]},{"type":["boolean","null","number","string"]},{"type":"array","items":{"type":"string"}}]},"expression":{"description":"Expression (for function type)","type":"string"},"index":{"description":"Field is indexed","type":"boolean"},"labels":{"description":"Field labels (localized)","type":"object","additionalProperties":{"type":"string"}},"name":{"type":"string","description":"Field name"},"onUpdate":{"description":"Script expression run as a row trigger when the field value changes","type":"string"},"optionColor":{"description":"Color expression for dchoice/dmulti fields","type":"string"},"optionIcon":{"description":"Icon expression for dchoice/dmulti fields","type":"string"},"optionName":{"description":"Display name expression for dchoice/dmulti fields","type":"string"},"options":{"description":"Options array for choice/multi fields, or selection expression for dchoice/dmulti fields","anyOf":[{"type":"array","items":{"type":"object","properties":{"color":{"description":"Option color (hex string)","type":"string"},"icon":{"description":"Option icon name","type":"string"},"id":{"type":"string","description":"Option id, a string the caller can set and change"},"label":{"type":"string","description":"Option text in the default language"},"labels":{"description":"Option text per language","type":"object","additionalProperties":{"type":"string"}},"order":{"type":"number","description":"Option display order"},"textColor":{"description":"Option text color (hex string)","type":"string"}},"required":["id","label","order"]}},{"type":"string"}]},"readRoles":{"description":"Roles allowed to read the field","type":"array","items":{"type":"string"}},"refTableName":{"description":"Reference table name","type":"string"},"required":{"description":"Field is required","type":"boolean"},"search":{"description":"Field is searchable","type":"boolean"},"syncedFrom":{"description":"Source column this field syncs from. Read-only unless the table has two-way sync with updates enabled, in which case every synced field except the key column is writable.","type":"string"},"type":{"type":"string","enum":["any","appointment","boolean","choice","color","date","dchoice","dmulti","file","function","html","icon","lambda","multi","number","react","reference","reverse","rowId","string","styled","time","timeinterval","timestamp","unknown","user","void"],"description":"Field type"},"unique":{"description":"Field is unique","type":"boolean"},"variant":{"description":"Field variant (for string type)","type":"string"},"writeRoles":{"description":"Roles allowed to write to the field","type":"array","items":{"type":"string"}}},"required":["name","type"]}},"hasFiles":{"description":"Enable files for the table","type":"boolean"},"hasGlobalSearch":{"description":"Enable global search for the table","type":"boolean"},"hasHistory":{"description":"Enable history for the table","type":"boolean"},"icon":{"description":"Table icon","type":"object","properties":{"color":{"description":"Icon color (hex string)","type":"string"},"filling":{"description":"Icon filling","anyOf":[{"type":"number","enum":[0]},{"type":"number","enum":[1]}]},"icon":{"type":"string","description":"Icon name"}},"required":["icon"]},"isEmailLinkingEnabled":{"description":"Enable email linking for the table","type":"boolean"},"isHidden":{"description":"Hide the table","type":"boolean"},"labels":{"description":"Table labels (localized)","type":"object","additionalProperties":{"type":"string"}},"name":{"type":"string"},"onCreate":{"description":"Script expression run as a trigger after a record is created","type":"string"},"onDelete":{"description":"Script expression run as a trigger when a record is deleted","type":"string"},"onUpdate":{"description":"Script expression run as a trigger after a record is updated","type":"string"},"readRoles":{"description":"Roles allowed to read records","type":"array","items":{"type":"string"}},"writeRoles":{"description":"Roles allowed to update records","type":"array","items":{"type":"string"}}},"required":["name"]}}},"description":"Module details"}},"required":["data"]},"ErrorResponse":{"type":"object","properties":{"error":{"type":"object","properties":{"message":{"type":"string","description":"Error message"}}}},"required":["error"]}}},"paths":{"/api/v1/workspace/{workspaceId}/modules/{moduleName}":{"patch":{"operationId":"ModulesV1Controller_updateModule","summary":"Update a module","description":"Updates an existing module in a workspace","parameters":[{"name":"moduleName","required":true,"in":"path","description":"Module name","schema":{"minLength":1,"maxLength":100,"pattern":"^[a-z0-9_]+$","type":"string"}},{"name":"workspaceId","required":true,"in":"path","description":"Workspace ID","schema":{"minLength":12,"maxLength":12,"pattern":"^[a-z0-9]+$","type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateModuleBody"}}}},"responses":{"200":{"description":"Module updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModuleResponse"}}}},"400":{"description":"Bad request (e.g., module already exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Module not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"tags":["Modules"]}}}}
```

## Update module, table, field, and option labels (batch)

> Updates labels across a module, its tables, their fields, and choice/multi option labels in a single transaction. Labels are replaced wholesale per object, same as the single-field PATCH — send every locale you want kept, not just the one changing. Every option id in an \`options\` entry must already exist on that field; an unknown id rejects the whole request. Writes against a synced field are rejected.

```json
{"openapi":"3.0.0","info":{"title":"Ninox Public API","version":"1.0.0"},"security":[{"bearer":[]}],"components":{"securitySchemes":{"bearer":{"scheme":"bearer","bearerFormat":"API Key","description":"Enter your Workspace API key. \n\n API keys can be generated and managed within the **Workspace Integration** settings in the Ninox app.","in":"header","name":"Authorization","type":"http"}},"schemas":{"UpdateModuleLabelsBody":{"type":"object","properties":{"labels":{"type":"object","additionalProperties":{"type":"string","minLength":1,"maxLength":100}},"tables":{"type":"object","additionalProperties":{"type":"object","properties":{"fields":{"type":"object","additionalProperties":{"type":"object","properties":{"labels":{"type":"object","additionalProperties":{"type":"string","minLength":1,"maxLength":100}},"options":{"description":"Choice/multi option labels — every id must already exist on the field","type":"array","items":{"type":"object","properties":{"id":{"type":"string","minLength":1,"description":"Existing option id — must already exist on the field"},"labels":{"type":"object","additionalProperties":{"type":"string","minLength":1,"maxLength":100}}},"required":["id","labels"],"additionalProperties":false}}},"additionalProperties":false}},"labels":{"type":"object","additionalProperties":{"type":"string","minLength":1,"maxLength":100}}},"additionalProperties":false}}},"additionalProperties":false},"ModuleLabelsResponse":{"type":"object","properties":{"data":{"type":"object","properties":{"fields":{"type":"array","items":{"type":"object","properties":{"binding":{"description":"Read-only: internal binding reference, format not yet specified","type":"string"},"canRead":{"description":"Script expression gating field-level read access","type":"string"},"canWrite":{"description":"Script expression gating field-level write access","type":"string"},"defaultValue":{"description":"Default value applied when a record is created: a literal value (an array of option ids for multi/dmulti), or a script expression (as { $nx: <script> }) evaluated at creation time","anyOf":[{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]},{"type":["boolean","null","number","string"]},{"type":"array","items":{"type":"string"}}]},"expression":{"description":"Expression (for function type)","type":"string"},"index":{"description":"Field is indexed","type":"boolean"},"labels":{"description":"Field labels (localized)","type":"object","additionalProperties":{"type":"string"}},"name":{"type":"string","description":"Field name"},"onUpdate":{"description":"Script expression run as a row trigger when the field value changes","type":"string"},"optionColor":{"description":"Color expression for dchoice/dmulti fields","type":"string"},"optionIcon":{"description":"Icon expression for dchoice/dmulti fields","type":"string"},"optionName":{"description":"Display name expression for dchoice/dmulti fields","type":"string"},"options":{"description":"Options array for choice/multi fields, or selection expression for dchoice/dmulti fields","anyOf":[{"type":"array","items":{"type":"object","properties":{"color":{"description":"Option color (hex string)","type":"string"},"icon":{"description":"Option icon name","type":"string"},"id":{"type":"string","description":"Option id, a string the caller can set and change"},"label":{"type":"string","description":"Option text in the default language"},"labels":{"description":"Option text per language","type":"object","additionalProperties":{"type":"string"}},"order":{"type":"number","description":"Option display order"},"textColor":{"description":"Option text color (hex string)","type":"string"}},"required":["id","label","order"]}},{"type":"string"}]},"readRoles":{"description":"Roles allowed to read the field","type":"array","items":{"type":"string"}},"refTableName":{"description":"Reference table name","type":"string"},"required":{"description":"Field is required","type":"boolean"},"search":{"description":"Field is searchable","type":"boolean"},"syncedFrom":{"description":"Source column this field syncs from. Read-only unless the table has two-way sync with updates enabled, in which case every synced field except the key column is writable.","type":"string"},"type":{"type":"string","enum":["any","appointment","boolean","choice","color","date","dchoice","dmulti","file","function","html","icon","lambda","multi","number","react","reference","reverse","rowId","string","styled","time","timeinterval","timestamp","unknown","user","void"],"description":"Field type"},"unique":{"description":"Field is unique","type":"boolean"},"variant":{"description":"Field variant (for string type)","type":"string"},"writeRoles":{"description":"Roles allowed to write to the field","type":"array","items":{"type":"string"}}},"required":["name","type"]},"description":"Fields whose labels were updated"},"module":{"type":"object","properties":{"afterOpen":{"description":"Script expression run in the browser each time the app is opened","type":"string"},"components":{"description":"Module components (pages, containers, widgets)","type":"array","items":{"type":"object","properties":{"afterHide":{"description":"Container directly under Tabs: script run when this tab stops being shown","type":"string"},"aggregation":{"description":"MetricCard: aggregation function","type":"string","enum":["avg","count","max","median","min","sum"]},"annualRecurring":{"description":"Calendar: render every record on the same day/month every year","type":"boolean"},"arrangement":{"description":"Page/Container: layout direction","type":"string","enum":["grid","ltr","row","ttb"]},"background":{"description":"Container/Page/Text: background","anyOf":[{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"beforeShow":{"description":"Container directly under Tabs: script run when this tab is shown","type":"string"},"border":{"description":"Container: border","anyOf":[{"type":"object","properties":{"color":{"type":"string"},"style":{"type":"string","enum":["dashed","dotted","double","none","solid"]},"width":{"type":"string"}},"required":["style","width"]},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"calendarType":{"description":"Calendar: display type","type":"string"},"cardBorder":{"description":"Kanban: card border CSS shorthand, Normal mode only","type":"string"},"cardFont":{"description":"Kanban: card font style tokens, Normal mode only","type":"string"},"cardPadding":{"description":"Kanban: card padding in px, Normal mode only","type":"number"},"cardRadius":{"description":"Kanban: card corner radius in px, Normal mode only","type":"number"},"chartConfig":{"description":"Chart: chart type, axes and data series","type":"object","properties":{"chartType":{"type":"string","enum":["bar","line","pie","funnel","ranking","board"]},"dataSets":{"type":"array","items":{"type":"object","properties":{"aggregation":{"type":"string","enum":["average","count","max","median","min","none","sum"]},"color":{"description":"Series color (hex string)","type":"string"},"fieldName":{"description":"Field name this series reads from","type":"string"},"labels":{"description":"Series labels (localized)","type":"object","additionalProperties":{"type":"string"}}}}},"donut":{"type":"boolean"},"labelPosition":{"type":"string","enum":["bottom","center","inside","outside","top"]},"legend":{"type":"object","properties":{"show":{"type":"boolean"}}},"limit":{"description":"ranking only: how many categories it shows","type":"integer","minimum":1,"maximum":20},"orientation":{"type":"string","enum":["horizontal","vertical"]},"showDataTable":{"type":"boolean"},"showLabels":{"type":"boolean"},"showPoints":{"type":"boolean"},"showTitle":{"type":"boolean"},"smooth":{"type":"boolean"},"stacked":{"type":"boolean"},"style":{"type":"string","enum":["default","half_donut","pad_angle","rounded_corner"]},"tooltips":{"type":"object","properties":{"show":{"type":"boolean"}}},"xAxis":{"type":"object","properties":{"fieldName":{"description":"X-axis field name, null removes it","type":["string","null"]},"groupBy":{"type":"string","enum":["daily","monthly","none","quarterly","weekly","yearly"]},"show":{"type":"boolean"}}},"yAxis":{"type":"object","properties":{"show":{"type":"boolean"}}}},"required":["chartType","dataSets","xAxis"]},"color":{"description":"Text: text color (hex string). Button: theme color name","anyOf":[{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"colorFieldName":{"description":"Map: marker color field name","type":"string"},"constraints":{"description":"FieldComponent: script limiting which records a reference can link to, needs schema:manage-permissions","type":"string"},"content":{"description":"Text: content, localized or a script expression","anyOf":[{"type":"object","additionalProperties":{"type":"string"}},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"customStyle":{"description":"Text: full custom style config, opaque, used only when quickStyle is \"custom\"","type":"object","additionalProperties":{}},"dataPoint":{"description":"'conditional' replaces table/filter/… with the `value` script","type":"string","enum":["conditional","normal"]},"defaultValue":{"description":"InputComponent: initial value, or { $nx: <script> }","anyOf":[{"type":"boolean"},{"type":"number"},{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"disabled":{"description":"Button/FieldComponent: disable the control, a boolean or a script","anyOf":[{"type":"boolean"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"display":{"description":"MetricCard: display formatting and trend configuration","type":"object","properties":{"color":{"type":"string"},"format":{"type":"string","enum":["compact","currency","number","percentage"]},"icon":{"type":"string"},"trend":{"type":"object","properties":{"customPeriodEnd":{"description":"ISO date (YYYY-MM-DD), for period \"custom\"","type":"string"},"customPeriodStart":{"description":"ISO date (YYYY-MM-DD), for period \"custom\"","type":"string"},"format":{"type":"string","enum":["absolute","percentage"]},"isShown":{"type":"boolean"},"period":{"type":"string","enum":["custom","last_month","last_week","last_year","previous_period","yesterday"]},"positiveDirection":{"type":"string","enum":["down","up"]}},"required":["format","isShown"]}},"required":["color","format","trend"]},"displayAs":{"description":"FieldComponent: how a yes/no field is shown","type":"string"},"expression":{"description":"DynamicHTMLComponent: script returning the HTML to render","type":"string"},"fieldIdDataPoint":{"description":"MetricCard: 'conditional' replaces table/filter/fieldName/aggregation with fieldIdValue","type":"string","enum":["conditional","normal"]},"fieldIdValue":{"description":"MetricCard: whole-dataset script producing the final number when fieldIdDataPoint is conditional","type":"string"},"fieldName":{"description":"MetricCard/Calendar/Map: primary bound field name","type":"string"},"filter":{"description":"MetricCard/Chart: stored filter conditions","type":"array","items":{"type":"object","properties":{"field":{"description":"Field name","type":"string"},"id":{"type":"string","description":"Stable condition id"},"operator":{"description":"Filter operator","type":"string"},"value":{"description":"Value compared against","type":"string"}},"required":["id"]}},"flex":{"description":"Container: flex sizing","anyOf":[{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"ganttConfig":{"description":"Gantt: which fields the bars/milestones/dependencies read from","type":"object","properties":{"baselineEndFieldName":{"description":"Planned end field, rendered as a ghost bar","type":["string","null"]},"baselineStartFieldName":{"description":"Planned start field, rendered as a ghost bar","type":["string","null"]},"dependencyDirection":{"type":"string","enum":["predecessor","successor"]},"dependencyFieldName":{"description":"A reference field pointing back at this table","type":["string","null"]},"disableDragAndDrop":{"type":"boolean"},"endFieldName":{"type":["string","null"]},"hideTitleColumn":{"type":"boolean"},"hideWeekends":{"type":"boolean"},"milestoneFieldName":{"type":["string","null"]},"progressFieldName":{"type":["string","null"]},"showCriticalPath":{"type":"boolean"},"showWeekends":{"type":"boolean"},"startFieldName":{"type":["string","null"]},"timeScale":{"type":"string","enum":["day","month","quarter","week"]},"titleColumnFieldName":{"type":["string","null"]},"titleColumnWidth":{"type":"number"}}},"gap":{"description":"Page/Container: gap between children","anyOf":[{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"globalFilterBinding":{"description":"MetricCard: field names this card reacts to for global page filters","type":"array","items":{"type":"string"}},"gridPreset":{"description":"Container: grid layout preset","anyOf":[{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"groupByFieldName":{"description":"Kanban: lane grouping field name","type":"string"},"height":{"description":"Component height","type":"number"},"icon":{"description":"Page: icon","type":"object","properties":{"color":{"description":"Icon color (hex string)","type":"string"},"filling":{"description":"Icon filling","anyOf":[{"type":"number","enum":[0]},{"type":"number","enum":[1]}]},"icon":{"type":"string","description":"Icon name"}},"required":["icon"]},"iconLeft":{"description":"Button/FieldComponent: icon before the label","anyOf":[{"type":"object","properties":{"color":{"description":"Icon color (hex string)","type":"string"},"filling":{"description":"Icon filling","anyOf":[{"type":"number","enum":[0]},{"type":"number","enum":[1]}]},"icon":{"type":"string","description":"Icon name"}},"required":["icon"]},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"iconRight":{"description":"Button/FieldComponent: icon after the label","anyOf":[{"type":"object","properties":{"color":{"description":"Icon color (hex string)","type":"string"},"filling":{"description":"Icon filling","anyOf":[{"type":"number","enum":[0]},{"type":"number","enum":[1]}]},"icon":{"type":"string","description":"Icon name"}},"required":["icon"]},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"id":{"type":"string","description":"Component id"},"imagePosition":{"description":"Kanban: card image crop/anchor, Normal mode only","type":"object","properties":{"position":{"type":"string"},"size":{"type":"string"}}},"isCompact":{"description":"Accordion: compact sections","type":"boolean"},"isHidden":{"description":"Page: hide from navigation","type":"boolean"},"isMarkdownEnabled":{"description":"FieldComponent: render a rich text field as markdown","type":"boolean"},"isSpreadsheetMode":{"description":"Table/FieldComponent: spreadsheet-style editing","type":"boolean"},"kind":{"type":"string","deprecated":true,"description":"Deprecated, use type. Same value, kept so existing integrations keep working"},"labelPosition":{"description":"FieldComponent: top, left, inside or hidden","type":"string"},"labels":{"description":"Component labels (localized)","type":"object","additionalProperties":{"type":"string"}},"mapTypeId":{"description":"Map: base layer type","type":"string"},"margin":{"description":"Container: margin","anyOf":[{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"name":{"description":"Component name","type":"string"},"onChange":{"description":"Tabs/FieldComponent: script run when the value changes","type":"string"},"onClick":{"description":"Button: script run on click","type":"string"},"order":{"description":"Component display order","type":"number"},"overflow":{"description":"Container: overflow behavior","anyOf":[{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"padding":{"description":"Page/Container: padding","anyOf":[{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"parentId":{"description":"Parent component id (forms the component tree)","type":"string"},"placeholder":{"description":"FieldComponent: placeholder, localized, plain or a script","anyOf":[{"type":"object","additionalProperties":{"type":"string"}},{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"quickStyle":{"description":"Text: style preset","anyOf":[{"type":"string","enum":["body-md","body-sm","custom","title-lg","title-md","title-sm"]},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"radius":{"description":"Container/Text: corner radius","anyOf":[{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"remember":{"description":"InputComponent: how long the value is kept","type":"string","enum":["localStorage","memory","url"]},"shadow":{"description":"Container: shadow","anyOf":[{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"shadowDom":{"description":"DynamicHTMLComponent: render inside a shadow DOM","type":"boolean"},"showAs":{"description":"FieldComponent: how the value is shown (e.g. popup, combobox)","type":"string"},"showBulkActions":{"description":"Table/FieldComponent: show bulk actions","type":"boolean"},"showCalendarType":{"description":"Calendar: show the calendar type switcher","type":"boolean"},"showCreateButton":{"description":"Table: show the create-record button","type":"boolean"},"showCreateRow":{"description":"Table: show the inline create row","type":"boolean"},"showDataAs":{"description":"FieldComponent: script formatting a linked record","type":"string"},"showEmptyLane":{"description":"Kanban: show lanes with no cards","type":"boolean"},"showLinkExistingRecord":{"description":"FieldComponent: offer linking an existing record","type":"boolean"},"showMetadata":{"description":"FieldComponent: show file metadata","type":"boolean"},"showOutlines":{"description":"Page: show layout outlines in the editor","type":"boolean"},"showSearchField":{"description":"Table/Kanban/Gantt/Calendar/Map: show the search field","type":"boolean"},"showTimeScaleSelector":{"description":"Gantt: let the viewer switch time scale","type":"boolean"},"showTitle":{"description":"Table: show the table title","type":"boolean"},"size":{"description":"Button: sm, md or lg","anyOf":[{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"tableName":{"description":"Table this component reads from (Chart/Table/Kanban/Gantt/Calendar/Map/MetricCard)","type":"string"},"textAlign":{"description":"Text: alignment","type":"string","enum":["text-center","text-left","text-right"]},"titleFieldName":{"description":"Map: marker title field name","type":"string"},"tooltip":{"description":"FieldComponent: tooltip text","type":"string"},"type":{"type":"string","description":"Component type (e.g. Container, Button, Text, Page), the property the create and update routes and the module definition take"},"value":{"description":"Script used instead of table/filter/… when dataPoint is conditional","type":"string"},"valueSpec":{"description":"InputComponent: the type of the value, shaped like a field type, a reference has refTableName","type":"object","properties":{"type":{"type":"string"}},"required":["type"],"additionalProperties":{}},"valueType":{"description":"InputComponent: legacy value type, valueSpec wins where both are set","type":"string"},"variant":{"description":"Button/Accordion/Tabs: visual variant, InputComponent: text, email, phone, url, ...","anyOf":[{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"view":{"description":"Table/MetricCard/Kanban/Gantt/Calendar/Map: columns/filter/groupBy/sort configuration","type":"object","properties":{"columns":{"description":"View columns","type":"array","items":{"type":"object","properties":{"agg":{"description":"Aggregation function applied to the column","type":"string"},"conditionalStyling":{"description":"Legacy per-column conditional styling rules","type":"array","items":{"type":"object","properties":{"background":{"description":"Background color (hex string)","type":"string"},"cell":{"description":"Target cell","type":"string"},"color":{"description":"Icon color (hex string)","type":"string"},"icon":{"description":"Icon name","type":"string"},"operand":{"type":"string","description":"Comparator"},"value":{"type":"string","description":"Value compared against"}},"required":["operand","value"]}},"field":{"type":"string","description":"Field name, or a script expression for a calculated column"},"hidden":{"description":"Column retained but hidden from the grid","type":"boolean"},"id":{"description":"Stable identity of a calculated column; send it back unchanged when updating the view","type":"string"},"labels":{"description":"Column labels (localized)","type":"object","additionalProperties":{"type":"string"}},"order":{"type":"number","description":"Column display order"},"role":{"description":"Column role (e.g. title, date, image, location, color)","type":"string"},"width":{"description":"Column width","type":"number"}},"required":["field","order"]}},"conditionalFormatting":{"description":"Conditional formatting rules","type":"array","items":{"type":"object","properties":{"backgroundColor":{"description":"Background color (hex string)","type":"string"},"bold":{"description":"Bold text","type":"boolean"},"comparator":{"type":"string","enum":["contains","does_not_contain","ends_with","gt","gte","is","is_empty","is_not","is_not_empty","logic","lt","lte","starts_with"],"description":"Comparator"},"expression":{"description":"Script expression, used only when comparator is 'logic'","type":"string"},"fieldName":{"type":"string","description":"Target field name"},"highlightColor":{"description":"Highlight color (hex string)","type":"string"},"icon":{"description":"Icon","type":"object","properties":{"color":{"description":"Icon color (hex string)","type":"string"},"filling":{"description":"Icon filling","anyOf":[{"type":"number","enum":[0]},{"type":"number","enum":[1]}]},"icon":{"type":"string","description":"Icon name"}},"required":["icon"]},"id":{"type":"string","description":"Stable rule id"},"italic":{"description":"Italic text","type":"boolean"},"order":{"type":"number","description":"Rule evaluation order"},"strikethrough":{"description":"Strikethrough text","type":"boolean"},"target":{"type":"string","enum":["cell","row"],"description":"Whether the rule styles a single cell or the whole row"},"textColor":{"description":"Text color (hex string)","type":"string"},"value":{"description":"Value compared against"}},"required":["comparator","fieldName","id","order","target"]}},"filter":{"description":"Stored filter conditions","type":"array","items":{"type":"object","properties":{"field":{"description":"Field name","type":"string"},"id":{"type":"string","description":"Stable condition id"},"operator":{"description":"Filter operator","type":"string"},"value":{"description":"Value compared against","type":"string"}},"required":["id"]}},"groupBy":{"description":"Grouping configuration","type":"array","items":{"type":"object","properties":{"direction":{"description":"Group order direction, defaults to ascending","type":"string","enum":["asc","desc"]},"fieldName":{"type":"string","description":"Field name"}},"required":["fieldName"]}},"sort":{"description":"Sort configuration","type":"object","properties":{"direction":{"type":"string","enum":["asc","desc"],"description":"Sort direction"},"fieldName":{"type":"string","description":"Field name"}},"required":["direction","fieldName"]}}},"visible":{"description":"Conditional visibility logic: a boolean, or a script expression (as { $nx: <script> }) evaluated at render time","anyOf":[{"type":"boolean"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]},"visibleRoles":{"description":"Page: roles allowed to view this page","type":"array","items":{"type":"string"}},"widgetName":{"description":"CustomWidget: folder name under the workspace widgets directory","type":"string"},"widgetProps":{"description":"CustomWidget: property values, each static or a script expression (as { $nx: <script> })","type":"object","additionalProperties":{"anyOf":[{"type":"boolean"},{"type":"number"},{"type":"string"},{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]}]}},"width":{"description":"Component width: number = legacy px, string = percentage e.g. \"50%\"","type":["number","string"]}},"required":["id","kind","type"]}},"hideNavigation":{"description":"Hide module from navigation","type":"boolean"},"icon":{"description":"Module icon","type":"object","properties":{"color":{"description":"Icon color (hex string)","type":"string"},"filling":{"description":"Icon filling","anyOf":[{"type":"number","enum":[0]},{"type":"number","enum":[1]}]},"icon":{"type":"string","description":"Icon name"}},"required":["icon"]},"isHidden":{"description":"Hide module","type":"boolean"},"labels":{"description":"Module labels (localized)","type":"object","additionalProperties":{"type":"string"}},"name":{"type":"string"},"openRoles":{"description":"Module open roles","type":"array","items":{"type":"string"}},"tables":{"type":"array","items":{"type":"object","properties":{"canCreate":{"description":"Script expression gating record creation","type":"string"},"canDelete":{"description":"Script expression gating record deletion","type":"string"},"canRead":{"description":"Script expression gating record read access","type":"string"},"canWrite":{"description":"Script expression gating record write access","type":"string"},"createRoles":{"description":"Roles allowed to create records","type":"array","items":{"type":"string"}},"deleteRoles":{"description":"Roles allowed to delete records","type":"array","items":{"type":"string"}},"fields":{"type":"array","items":{"type":"object","properties":{"binding":{"description":"Read-only: internal binding reference, format not yet specified","type":"string"},"canRead":{"description":"Script expression gating field-level read access","type":"string"},"canWrite":{"description":"Script expression gating field-level write access","type":"string"},"defaultValue":{"description":"Default value applied when a record is created: a literal value (an array of option ids for multi/dmulti), or a script expression (as { $nx: <script> }) evaluated at creation time","anyOf":[{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]},{"type":["boolean","null","number","string"]},{"type":"array","items":{"type":"string"}}]},"expression":{"description":"Expression (for function type)","type":"string"},"index":{"description":"Field is indexed","type":"boolean"},"labels":{"description":"Field labels (localized)","type":"object","additionalProperties":{"type":"string"}},"name":{"type":"string","description":"Field name"},"onUpdate":{"description":"Script expression run as a row trigger when the field value changes","type":"string"},"optionColor":{"description":"Color expression for dchoice/dmulti fields","type":"string"},"optionIcon":{"description":"Icon expression for dchoice/dmulti fields","type":"string"},"optionName":{"description":"Display name expression for dchoice/dmulti fields","type":"string"},"options":{"description":"Options array for choice/multi fields, or selection expression for dchoice/dmulti fields","anyOf":[{"type":"array","items":{"type":"object","properties":{"color":{"description":"Option color (hex string)","type":"string"},"icon":{"description":"Option icon name","type":"string"},"id":{"type":"string","description":"Option id, a string the caller can set and change"},"label":{"type":"string","description":"Option text in the default language"},"labels":{"description":"Option text per language","type":"object","additionalProperties":{"type":"string"}},"order":{"type":"number","description":"Option display order"},"textColor":{"description":"Option text color (hex string)","type":"string"}},"required":["id","label","order"]}},{"type":"string"}]},"readRoles":{"description":"Roles allowed to read the field","type":"array","items":{"type":"string"}},"refTableName":{"description":"Reference table name","type":"string"},"required":{"description":"Field is required","type":"boolean"},"search":{"description":"Field is searchable","type":"boolean"},"syncedFrom":{"description":"Source column this field syncs from. Read-only unless the table has two-way sync with updates enabled, in which case every synced field except the key column is writable.","type":"string"},"type":{"type":"string","enum":["any","appointment","boolean","choice","color","date","dchoice","dmulti","file","function","html","icon","lambda","multi","number","react","reference","reverse","rowId","string","styled","time","timeinterval","timestamp","unknown","user","void"],"description":"Field type"},"unique":{"description":"Field is unique","type":"boolean"},"variant":{"description":"Field variant (for string type)","type":"string"},"writeRoles":{"description":"Roles allowed to write to the field","type":"array","items":{"type":"string"}}},"required":["name","type"]}},"hasFiles":{"description":"Enable files for the table","type":"boolean"},"hasGlobalSearch":{"description":"Enable global search for the table","type":"boolean"},"hasHistory":{"description":"Enable history for the table","type":"boolean"},"icon":{"description":"Table icon","type":"object","properties":{"color":{"description":"Icon color (hex string)","type":"string"},"filling":{"description":"Icon filling","anyOf":[{"type":"number","enum":[0]},{"type":"number","enum":[1]}]},"icon":{"type":"string","description":"Icon name"}},"required":["icon"]},"isEmailLinkingEnabled":{"description":"Enable email linking for the table","type":"boolean"},"isHidden":{"description":"Hide the table","type":"boolean"},"labels":{"description":"Table labels (localized)","type":"object","additionalProperties":{"type":"string"}},"name":{"type":"string"},"onCreate":{"description":"Script expression run as a trigger after a record is created","type":"string"},"onDelete":{"description":"Script expression run as a trigger when a record is deleted","type":"string"},"onUpdate":{"description":"Script expression run as a trigger after a record is updated","type":"string"},"readRoles":{"description":"Roles allowed to read records","type":"array","items":{"type":"string"}},"writeRoles":{"description":"Roles allowed to update records","type":"array","items":{"type":"string"}}},"required":["name"]}}},"required":["name"],"description":"The module, with its updated labels if any"},"tables":{"type":"array","items":{"type":"object","properties":{"canCreate":{"description":"Script expression gating record creation","type":"string"},"canDelete":{"description":"Script expression gating record deletion","type":"string"},"canRead":{"description":"Script expression gating record read access","type":"string"},"canWrite":{"description":"Script expression gating record write access","type":"string"},"createRoles":{"description":"Roles allowed to create records","type":"array","items":{"type":"string"}},"deleteRoles":{"description":"Roles allowed to delete records","type":"array","items":{"type":"string"}},"fields":{"type":"array","items":{"type":"object","properties":{"binding":{"description":"Read-only: internal binding reference, format not yet specified","type":"string"},"canRead":{"description":"Script expression gating field-level read access","type":"string"},"canWrite":{"description":"Script expression gating field-level write access","type":"string"},"defaultValue":{"description":"Default value applied when a record is created: a literal value (an array of option ids for multi/dmulti), or a script expression (as { $nx: <script> }) evaluated at creation time","anyOf":[{"type":"object","properties":{"$nx":{"type":"string","description":"Script expression. Writing one needs records:write as well as schema:write"}},"required":["$nx"]},{"type":["boolean","null","number","string"]},{"type":"array","items":{"type":"string"}}]},"expression":{"description":"Expression (for function type)","type":"string"},"index":{"description":"Field is indexed","type":"boolean"},"labels":{"description":"Field labels (localized)","type":"object","additionalProperties":{"type":"string"}},"name":{"type":"string","description":"Field name"},"onUpdate":{"description":"Script expression run as a row trigger when the field value changes","type":"string"},"optionColor":{"description":"Color expression for dchoice/dmulti fields","type":"string"},"optionIcon":{"description":"Icon expression for dchoice/dmulti fields","type":"string"},"optionName":{"description":"Display name expression for dchoice/dmulti fields","type":"string"},"options":{"description":"Options array for choice/multi fields, or selection expression for dchoice/dmulti fields","anyOf":[{"type":"array","items":{"type":"object","properties":{"color":{"description":"Option color (hex string)","type":"string"},"icon":{"description":"Option icon name","type":"string"},"id":{"type":"string","description":"Option id, a string the caller can set and change"},"label":{"type":"string","description":"Option text in the default language"},"labels":{"description":"Option text per language","type":"object","additionalProperties":{"type":"string"}},"order":{"type":"number","description":"Option display order"},"textColor":{"description":"Option text color (hex string)","type":"string"}},"required":["id","label","order"]}},{"type":"string"}]},"readRoles":{"description":"Roles allowed to read the field","type":"array","items":{"type":"string"}},"refTableName":{"description":"Reference table name","type":"string"},"required":{"description":"Field is required","type":"boolean"},"search":{"description":"Field is searchable","type":"boolean"},"syncedFrom":{"description":"Source column this field syncs from. Read-only unless the table has two-way sync with updates enabled, in which case every synced field except the key column is writable.","type":"string"},"type":{"type":"string","enum":["any","appointment","boolean","choice","color","date","dchoice","dmulti","file","function","html","icon","lambda","multi","number","react","reference","reverse","rowId","string","styled","time","timeinterval","timestamp","unknown","user","void"],"description":"Field type"},"unique":{"description":"Field is unique","type":"boolean"},"variant":{"description":"Field variant (for string type)","type":"string"},"writeRoles":{"description":"Roles allowed to write to the field","type":"array","items":{"type":"string"}}},"required":["name","type"]}},"hasFiles":{"description":"Enable files for the table","type":"boolean"},"hasGlobalSearch":{"description":"Enable global search for the table","type":"boolean"},"hasHistory":{"description":"Enable history for the table","type":"boolean"},"icon":{"description":"Table icon","type":"object","properties":{"color":{"description":"Icon color (hex string)","type":"string"},"filling":{"description":"Icon filling","anyOf":[{"type":"number","enum":[0]},{"type":"number","enum":[1]}]},"icon":{"type":"string","description":"Icon name"}},"required":["icon"]},"isEmailLinkingEnabled":{"description":"Enable email linking for the table","type":"boolean"},"isHidden":{"description":"Hide the table","type":"boolean"},"labels":{"description":"Table labels (localized)","type":"object","additionalProperties":{"type":"string"}},"name":{"type":"string"},"onCreate":{"description":"Script expression run as a trigger after a record is created","type":"string"},"onDelete":{"description":"Script expression run as a trigger when a record is deleted","type":"string"},"onUpdate":{"description":"Script expression run as a trigger after a record is updated","type":"string"},"readRoles":{"description":"Roles allowed to read records","type":"array","items":{"type":"string"}},"writeRoles":{"description":"Roles allowed to update records","type":"array","items":{"type":"string"}}},"required":["name"]},"description":"Tables whose labels were updated"}}}},"required":["data"]},"ErrorResponse":{"type":"object","properties":{"error":{"type":"object","properties":{"message":{"type":"string","description":"Error message"}}}},"required":["error"]}}},"paths":{"/api/v1/workspace/{workspaceId}/modules/{moduleName}/labels":{"patch":{"operationId":"ModulesV1Controller_updateModuleLabels","summary":"Update module, table, field, and option labels (batch)","description":"Updates labels across a module, its tables, their fields, and choice/multi option labels in a single transaction. Labels are replaced wholesale per object, same as the single-field PATCH — send every locale you want kept, not just the one changing. Every option id in an `options` entry must already exist on that field; an unknown id rejects the whole request. Writes against a synced field are rejected.","parameters":[{"name":"moduleName","required":true,"in":"path","description":"Module name","schema":{"minLength":1,"maxLength":100,"pattern":"^[a-z0-9_]+$","type":"string"}},{"name":"workspaceId","required":true,"in":"path","description":"Workspace ID","schema":{"minLength":12,"maxLength":12,"pattern":"^[a-z0-9]+$","type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateModuleLabelsBody"}}}},"responses":{"200":{"description":"Labels updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModuleLabelsResponse"}}}},"400":{"description":"Bad request (e.g., unknown option id, table/field not found)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Write rejected: field is synced from an external source (read-only)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Module not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"tags":["Modules"]}}}}
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.ninox.com/ninox-api/api-reference/api-endpoints/modules.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
