Boards configuration walkthrough
This walkthrough builds a working process board over the SupportTicket
record type from the
Configuration quickstart: a
triage board where new tickets land in Triage, move to In progress,
and finish in Resolved. Everything happens through the Configuration API,
so the same flow works for an AI agent with a service-account key.
All examples were executed against a real Moltaro installation; response bodies are real, trimmed for length. For what boards are and how users work with them, see the Boards user documentation; for the complete contract, see the Configuration API reference.
An agent starts only with the prepared workspace guide, URL, key, and roles. If access or module administration is missing, ask the user to complete it in the Portal or administrative interface. Do not provision or elevate the agent through these APIs. Follow Reliable API automation for idempotent discovery, conflicts, and safe mutation rules.
One convention to know up front: every board administration mutation returns
the full board administration model — the created status, transition, or
target definition appears inside its Statuses, Transitions, or
TargetDefinitions array rather than as the response root. Read the ids from
there.
Prerequisites
Section titled “Prerequisites”- Admin or Configurator role for enabling the module and creating boards. Per-board changes are also open to subjects granted the board-scoped Manage configuration permission.
- An existing entity definition to bind — this page uses
SupportTicket(idpYZqCLZWb0K1) from the Configuration quickstart.
Step 1 — Enable the Boards module
Section titled “Step 1 — Enable the Boards module”Boards ship disabled. POST /api/workspace/admin/boards/enable
(operation)
turns the module on for the workspace; the body is optional:
curl -s -X POST https://ops.example.com/api/workspace/admin/boards/enable \ -H "Authorization: Bearer <token>" -H "Content-Type: application/json" -d '{}'GET /api/workspace/admin/boards/setup
(operation)
reports the module state at any time — useful as the idempotent first call of
an automation.
Step 2 — Create the board
Section titled “Step 2 — Create the board”POST /api/workspace/admin/boards/boards
(operation).
The Key must start with a letter and may contain only ASCII letters,
numbers, and underscores (support-triage would be rejected with
moltaroBoards.validation.boardKeyInvalid):
curl -s -X POST https://ops.example.com/api/workspace/admin/boards/boards \ -H "Authorization: Bearer <token>" -H "Content-Type: application/json" \ -d '{ "Key": "support_triage", "DisplayName": "Support triage", "Description": "Incoming ticket triage and resolution.", "BoardType": 0, "CreateDefaultStatuses": false }'{ "Data": { "Id": "zuq5JQx4kLF1", "Key": "support_triage", "DataEntityDefinitionId": "wJ8wB2plyd7F", "DisplayName": "Support triage", "IsActive": false, "BoardType": 0, "AllowedActions": { "CanUpdate": true, "CanActivate": false, "CanManageConfiguration": true }, "TargetDefinitions": [], "Statuses": [], "Transitions": [] }, "Success": true}BoardType: 0 is a Kanban board (1 adds planned operating cycles and then
requires BoardCycleActivationMode). CreateDefaultStatuses: false starts
with an empty status set so this walkthrough can build the process explicitly;
with true the board is created with a ready
Initial/Active/Terminal status trio instead.
All starter display metadata is created in the workspace locale: status
labels, the Board Data entity and its Subject and Description fields, system
link types, and initial-mapping destination labels. Their technical keys
remain stable (init, active, terminal, child, related, Subject,
and Description).
The response shows what a board brings along: it is inactive (invisible
to end users until activated — which is what makes the configure-then-activate
flow safe against a live workspace), it owns a board data model
(DataEntityDefinitionId — process-specific fields that live on the board
item rather than the record, see
board data fields below). Board Security starts empty:
configure Responsibilities, Access Policies, and Permissions explicitly.
Step 3 — Activating too early fails
Section titled “Step 3 — Activating too early fails”Activation validates the configuration, so an agent can probe readiness honestly. Activating right after creation:
curl -s -X POST https://ops.example.com/api/workspace/admin/boards/boards/zuq5JQx4kLF1/activate \ -H "Authorization: Bearer <token>" -H "Content-Type: application/json" -d '{}'{ "Data": null, "Errors": [ { "Code": "moltaroBoards.domain.initialStatusRequired", "Message": "An active board must have exactly one active, non-deleted initial status.", "Field": "Initial", "Type": 1, "Severity": 2 }, { "Code": "moltaroBoards.domain.terminalStatusRequired", "Message": "An active board must have at least one active, non-deleted terminal status.", "Field": "Terminal", "Type": 1, "Severity": 2 } ], "Success": false}Activation requires exactly one initial status and at least one terminal status. Transitions are not an activation requirement — but without them no status change is allowed at runtime, so a useful board defines both.
Step 4 — Bind the record type target
Section titled “Step 4 — Bind the record type target”A target definition connects the board to the records it manages.
POST /api/workspace/admin/boards/boards/{boardId}/target-definitions
(operation):
curl -s -X POST https://ops.example.com/api/workspace/admin/boards/boards/zuq5JQx4kLF1/target-definitions \ -H "Authorization: Bearer <token>" -H "Content-Type: application/json" \ -d '{ "TargetKind": 0, "TargetModelId": "pYZqCLZWb0K1" }'{ "Data": { "Id": "zuq5JQx4kLF1", "TargetDefinitions": [ { "Id": "ojmxCpYFwfCY", "TargetKind": 0, "TargetModelId": "pYZqCLZWb0K1", "IsActive": true, "RepeatPolicy": 0, "RowVersion": "1c0b2008-f9da-46ff-96ea-8a85c683843c" } ] }, "Success": true}TargetKind: 0 binds an entity definition; TargetModelId is the entity
definition id. The created target definition id (ojmxCpYFwfCY here) comes
back inside TargetDefinitions — the runtime item APIs will need it. One
board can carry several target definitions, so records of different types
share one process.
Step 5 — Create the statuses
Section titled “Step 5 — Create the statuses”POST /api/workspace/admin/boards/boards/{boardId}/statuses
(operation),
one call per status. MetaType gives each status its role in the process:
0 Initial (new items land here), 1 Active, 2 Terminal:
curl -s -X POST https://ops.example.com/api/workspace/admin/boards/boards/zuq5JQx4kLF1/statuses \ -H "Authorization: Bearer <token>" -H "Content-Type: application/json" \ -d '{ "DisplayName": "Triage", "MetaType": 0, "SortOrder": 1 }'| Status | Request body | Created id |
|---|---|---|
| Triage | { "DisplayName": "Triage", "MetaType": 0, "SortOrder": 1 } | 2FEzzRX4vMNg |
| In progress | { "DisplayName": "In progress", "MetaType": 1, "SortOrder": 2 } | x2lpSYpWQ3q6 |
| Resolved | { "DisplayName": "Resolved", "MetaType": 2, "SortOrder": 3 } | gc3NgI61wO4D |
As with every board mutation, each response is the full board model — the new
status id appears in Data.Statuses.
Step 6 — Create the transitions
Section titled “Step 6 — Create the transitions”Transitions define which status moves are allowed.
POST /api/workspace/admin/boards/boards/{boardId}/transitions
(operation)
takes the two status ids from the previous step:
curl -s -X POST https://ops.example.com/api/workspace/admin/boards/boards/zuq5JQx4kLF1/transitions \ -H "Authorization: Bearer <token>" -H "Content-Type: application/json" \ -d '{ "FromBoardStatusId": "2FEzzRX4vMNg", "ToBoardStatusId": "x2lpSYpWQ3q6" }'Create one per allowed move — here Triage → In progress and
In progress → Resolved. Moves without a matching transition are rejected at
runtime with moltaroBoards.runtime.transitionNotFound, and the runtime API
exposes the allowed set per item through move-options, so an agent never
has to guess.
Require links before a transition
Section titled “Require links before a transition”LinkPrerequisites can require active item links before a transition is
allowed. A prerequisite fixes the link system kind (0 Child, 1 Related),
its direction relative to the item being moved (0 outgoing, 1 incoming),
the target Board and exact target definition, and a minimum/optional maximum
count. For example, this transition requires one incoming Child link from an
item on the specified target definition:
{ "FromBoardStatusId": "2FEzzRX4vMNg", "ToBoardStatusId": "x2lpSYpWQ3q6", "LinkPrerequisites": [ { "LinkType": 0, "Direction": 1, "TargetBoardId": "zuq5JQx4kLF1", "TargetBoardTargetDefinitionId": "ojmxCpYFwfCY", "MinimumCount": 1, "MaximumCount": 1 } ]}The target Board and target definition must exist, be active, and match each
other. Duplicate scopes and invalid count ranges are rejected. On update,
omit LinkPrerequisites to preserve them or send an empty array to clear them.
Step 7 — Configure Board Security
Section titled “Step 7 — Configure Board Security”Board Security is empty on a new board and therefore fails closed. Before the
runtime walkthrough, create an enabled BoardItem Security Statement and
assign the permissions used by that walkthrough to it. Start by reading the
shared concurrency token and the server-owned permission catalog:
curl -s https://ops.example.com/api/workspace/admin/boards/boards/zuq5JQx4kLF1/security \ -H "Authorization: Bearer <token>"
curl -s https://ops.example.com/api/workspace/admin/boards/boards/zuq5JQx4kLF1/security/profiles/BoardItem/permissions \ -H "Authorization: Bearer <token>"Create a Statement for the actors that will operate this example. The source
below deliberately limits the walkthrough to the workspace ADMIN role; use
the exact role design required by your workspace instead:
curl -s -X POST https://ops.example.com/api/workspace/admin/boards/boards/zuq5JQx4kLF1/security/profiles/BoardItem/statements \ -H "Authorization: Bearer <token>" -H "Content-Type: application/json" \ -d "{ \"OperationKey\": \"ae8fa130-25eb-4570-ab1c-ed372eef8380\", \"RowVersion\": \"00000000-0000-0000-0000-000000000000\", \"Key\": \"RuntimeAdmin\", \"Source\": \"HAS_ROLE('ADMIN')\", \"Enabled\": true }"Then create one Permission Assignment per required catalog entry. Use each
entry’s returned PermissionId, a unique assignment Key and OperationKey,
and the latest RowVersion returned by the previous mutation:
curl -s -X POST https://ops.example.com/api/workspace/admin/boards/boards/zuq5JQx4kLF1/security/profiles/BoardItem/permission-assignments \ -H "Authorization: Bearer <token>" -H "Content-Type: application/json" \ -d '{ "OperationKey": "760eb25c-8f36-4b3c-9c0f-da1945750c8a", "RowVersion": "<latest-security-row-version>", "Key": "RuntimeAdminView", "PermissionId": "Resource|View|", "StatementKey": "RuntimeAdmin" }'Repeat that assignment for AddItem, MoveItem, EditBoardData,
ViewAuditTrail, ManageItemLinks, Target:View, and the exact
UseTransition entries returned for the two transitions. These entries match
the action flags and link-candidate call shown in the runtime walkthrough. If
you extend the example to change custom Board Data fields, also assign
Field:Write for each changed field. The target Entity Definition must
separately grant the same actor its own Create, View, and required field
permissions, as described in
Configure Entity Security.
Responsibilities are optional: omit them when this board has no named
responsibility assignments.
Step 8 — Activate
Section titled “Step 8 — Activate”With statuses, process wiring, and explicit Security in place, activation
succeeds and the same board model comes back with IsActive: true:
curl -s -X POST https://ops.example.com/api/workspace/admin/boards/boards/zuq5JQx4kLF1/activate \ -H "Authorization: Bearer <token>" -H "Content-Type: application/json" -d '{}'{ "Data": { "Id": "zuq5JQx4kLF1", "Key": "support_triage", "IsActive": true, "AllowedActions": { "CanActivate": false, "CanDeactivate": true } }, "Success": true}The board is now live for actors allowed by the configured Statements and Permissions. Continue with the Boards runtime walkthrough to create and move items through the public API.
Board data fields
Section titled “Board data fields”Process-specific fields — an escalation flag, a triage note — belong to the
board item, not the record. They live on the board-owned data model
(DataEntityDefinitionId above) and are managed with
POST /api/workspace/admin/boards/boards/{boardId}/data-model/fields
(operation),
which reuses the exact field request shape from the
Configuration quickstart.
The record keeps its own schema; the board carries the process context.
Board Statements
Section titled “Board Statements”Board Statements are reusable Board-owned boolean expressions. Configure them
through
/api/workspace/admin/boards/boards/{boardId}/statements; the server-generated
GET .../authoring response is the authoritative set of roots, typed paths,
operators, functions, variables, examples, and diagnostic codes for the chosen
optional target definition.
Use POST .../validate before create or update, and use POST .../preview with
an explicit proposed values/collections payload when an integration needs a
deterministic authoring check. Create and update persist source, normalized
expression, dependency metadata, eligibility, fingerprints, and RowVersion.
Installation package export persists portable source and recompiles it against
the destination workspace during apply.
See the complete Board Statement DSL reference. Statements are not runtime gates by themselves.
Board Constraints and Bindings
Section titled “Board Constraints and Bindings”Board Constraint configuration is available through the Board administration
screen and the Configuration API. A Constraint owns its safe failure message;
each ordered Binding selects Transition, EnterStatus, ExitStatus, or
StatusInvariant, and combines a non-empty ordered Statement set with And
or Or.
GET /api/workspace/admin/boards/boards/{boardId}/constraintsPOST /api/workspace/admin/boards/boards/{boardId}/constraintsPUT /api/workspace/admin/boards/boards/{boardId}/constraints/{constraintId}DELETE /api/workspace/admin/boards/boards/{boardId}/constraints/{constraintId}POST /api/workspace/admin/boards/boards/{boardId}/constraints/reorderPOST /api/workspace/admin/boards/boards/{boardId}/constraints/bindings/validatePOST /api/workspace/admin/boards/boards/{boardId}/constraints/{constraintId}/bindingsPUT /api/workspace/admin/boards/boards/{boardId}/constraints/{constraintId}/bindings/{bindingId}DELETE /api/workspace/admin/boards/boards/{boardId}/constraints/{constraintId}/bindings/{bindingId}POST /api/workspace/admin/boards/boards/{boardId}/constraints/{constraintId}/bindings/reorderValidation returns configuration health separately from runtime availability.
Healthy Transition, EnterStatus, and ExitStatus Bindings report runtime
availability and can be enabled. A Constraint can be enabled only after it has
at least one enabled, healthy Binding; disabling or deleting its last enforcing
Binding is rejected. IsEnforcing requires an enabled Constraint, an enabled
Binding, valid configuration, an available trigger runtime, and an active
Board.
StatusInvariant Bindings can be enabled when every referenced Statement is
invariant-safe. Moltaro enforces them against the complete proposed Target or
Board Data aggregate before supported Entity API, NetOperationProject, and
Package SDK writes commit. Package YAML applies the same health and activation
checks and never silently downgrades an enabled definition.
The Board resource keeps portable Statement source and Binding references. A minimal fragment is shown below; use stable ids within the resource and let the installer recompile the expression for the destination workspace.
Statements: - Id: owner-present Name: OwnerPresent DisplayName: Owner is present BoardTargetDefinitionId: null Expression: BoardData.Owner IS NOT NULL SortOrder: 0 IsEnabled: trueConstraints: - Id: ready-requires-owner Name: ReadyRequiresOwner DisplayName: Ready requires an owner FailureMessage: Select an owner before moving this item to Ready. SortOrder: 0 IsEnabled: true Bindings: - Id: enter-ready TriggerType: EnterStatus BoardStatusId: ready EvaluatorType: Statements LogicalOperator: And SortOrder: 0 IsEnabled: true BoardStatementIds: - owner-presentPackage validation, planning, and apply reject unknown Statement ids, invalid trigger shapes, missing target coverage, unhealthy expressions, and active configuration that cannot enforce. Export writes current portable source; it does not serialize a compiled plan or retain a destination-specific schema fingerprint as executable state.
See Board constraints for the product model and the event/status-invariant enforcement boundaries.
Board Security
Section titled “Board Security”Board Security uses the same three administration concepts as Entity Security:
- Responsibilities define optional named assignments for Board Items or Board Statuses and the rules that may change them;
- Access Policies project one reusable Security Statement condition plus all exact Permissions assigned to it and use atomic Plan/Apply;
- Permissions expose inherited field access, explicit field refinements and exact transition coverage. Multiple Statements assigned to a Permission use OR semantics.
Raw Security Statement and Permission Assignment operations remain available through the Configuration API as an immediate Advanced surface.
An empty configuration fails closed for Board Item and direct Board Status access.
Board Item collections, search, saved filters, link candidates and cycle item
counts evaluate BoardItem.View before count, ordering and pagination. Direct
reads use the same policy. Owner, Admin and Configurator can manage Board
configuration, but those roles do not bypass Board Item data authorization.
Runtime operations compose View with one exact Permission: for example,
MoveItem and UseTransition:<transition-key> for a configured transition,
or EditBoardData plus each changed Field:Write Permission for Board Data.
Responsibility changes are different: they require the resource profile’s
View and an active Assignment Rule for the exact responsibility key and
action. Board cycle administration is Owner/Admin or ManageCycles;
Configurator has no implicit cycle authority.
Target display and Security conditions are separate. Cards project the target
selected by BoardTargetDefinition and require BoardItem.View, the separate
Target:View Permission, and that target resource’s own access. Inside a
Security Statement,
target(<TargetKind>, '<TargetModelKey?>').<path> selects one exact target
type; target.<path> selects the first configured Target Definition by
SortOrder, then Id. Predicate traversal does not require or grant
Target:View.
Board status columns remain part of the process shell. A Board Item requires
BoardItem.View; it does not additionally require BoardStatus.View.
BoardStatus.View governs direct status responsibility and history access.
Workspace C# automation and background Board work enter the same captured authorization scope as HTTP operations. A confirmed trusted system invocation may use the reserved system actor identity, but it receives no automatic Permission and must satisfy the configured Statements. A package host without the Moltaro Boards evaluator fails closed.
Where to go next
Section titled “Where to go next”- Boards runtime walkthrough — items, moves, and process collaboration through the public API.
- Board Security — configure Responsibilities, Access Policies, and Permissions through the Configuration API reference.
- Due-date and attention-signal policies — per-board operational policies in the same administration group.