Workflow Structure

The DTOs that make up a workflow definition — transitions, end states, actions, and authorisation.

A workflow is an array of WorkflowTransitionDto objects forming a state machine.

WorkflowTransitionDto

FieldTypeRequiredDescription
startStatestringYesCurrent state (UPPER_SNAKE_CASE)
eventstringYesTrigger event (UPPER_SNAKE_CASE verb)
endStateOneWorkflowEndStateDtoYesPrimary destination state
endStateTwoWorkflowEndStateDtoNoAlternate destination (conditional)
endStateConditionWorkflowEndStateConditionDtoNoCondition for choosing endStateTwo
authorisationWorkflowAuthorisationDtoYesWho can trigger this event
position{x, y}NoVisual editor position
eventNamesMap<string, string>NoLocalized event names (en, fr, rw)
eventConfigsWorkflowEventConfigsDtoNoEvent configuration

WorkflowEndStateDto

FieldTypeRequiredDescription
stateCodestringYesUPPER_SNAKE_CASE state identifier
stateNamestringYesDefault display name
stateNamesMap<string, string>NoLocalized names {en, fr, rw}
breakingActionWorkflowActionDtoNoSingle breaking action (legacy, prefer breakingActions)
breakingActionsWorkflowActionDto[]NoBreaking actions (rejection/cancellation notifications)
nonBreakingActionsWorkflowActionDto[]NoNon-breaking actions (certificates, integrations)
nextEventstringNoAuto-trigger next event after reaching this state
position{x, y}NoVisual editor position

WorkflowActionDto

FieldTypeRequiredDescription
actionTypestringYesMust be a valid EWorkflowActionType value
argsWorkflowArgumentsDtoNoAction-specific arguments

EWorkflowActionType Values

Action TypePurpose
NOTIFICATIONSend notification (email/SMS) to applicant
INTERNAL_NOTIFICATIONSend notification to internal staff
FORM_FIELD_NOTIFICATIONSend notification to address from a form field
OFFICE_ASSIGNMENT_NOTIFICATIONNotify assigned office
INTEGRATIONCall external integration endpoint
INTEGRATION_UPDATEUpdate via integration
GENERATE_CERTIFICATEGenerate output document/certificate
BILL_ID_GENERATIONGenerate payment bill ID
MASTER_BILL_ID_GENERATIONGenerate master bill ID
SERVICE_CENTER_MASTER_BILL_ID_GENERATIONService center master bill
EXECUTE_PRICINGExecute pricing calculation
OFFICE_ASSIGNMENTAssign application to office
FETCH_ID_PHOTOFetch ID photo from registry
SLOT_BOOKINGBook appointment slot
REDEEM_SLOTRedeem a booked slot
SLOT_REBOOKINGRebook an appointment slot
APPLY_SERVICEApply for a related service
APPLY_NORMAL_SERVICEApply for a normal service
TRIGGER_PARENTTrigger parent service event
TRIGGER_PARENT_SERVICE_EVENTTrigger specific parent event
TRIGGER_CHILD_SERVICE_EVENTTrigger child service event
CREATE_CHILD_APPLICATIONCreate a child application
APPLY_OR_RESUBMIT_CHILD_APPLICATIONApply or resubmit child
UPDATE_DATASETUpdate a dataset
SYSTEM_REQUEST_FOR_ACTIONSystem-generated RFA
URL_CALLCall an external URL
VALIDATE_UNIQUE_APPLICATION_PROPERTYValidate unique property

WorkflowArgumentsDto (Key Fields)

For NOTIFICATION / INTERNAL_NOTIFICATION

  • notificationType: DYNAMIC | STATIC
  • dynamicTemplate: { "en": { "templateCode": "CODE" } }
  • staticTemplate: { "en": { "templateCode": "CODE" } }
  • attachment: array of attachment configs
  • internalEmailNotificationRecipients: string[]
  • internalSmsNotificationRecipients: string[]
  • formFieldsSmsNotificationRecipients: string[]
  • formFieldsEmailNotificationRecipients: string[]

For INTEGRATION

  • endpointCode: string
  • async: boolean

For GENERATE_CERTIFICATE

  • certificateName: string
  • certificateNames: { "en": "Name" }
  • certificateTemplateCode: { "en": "TEMPLATE_CODE" }
  • certificateExpirationDays: number
  • certificateWithList: boolean
  • mergeDocuments: string[]

For BILL_ID_GENERATION / EXECUTE_PRICING

  • invoiceDescription: string
  • currency: string

For OFFICE_ASSIGNMENT

  • officeAssignmentType: string
  • officeLevel: string
  • formFieldKey: string
  • formFieldKeys: string[]
  • fixedOfficeCode: string
  • officeAssignmentExpression: string
  • officeId: string

For SLOT_BOOKING / REDEEM_SLOT

  • groupIdField: string
  • timeRangeIdField: string
  • seatsField: string

For SYSTEM_REQUEST_FOR_ACTION

  • fieldNames: string[]
  • feedbackSection: string
  • feedbackReason: string
  • comment: string

For APPLY_SERVICE / CREATE_CHILD_APPLICATION

  • serviceCode: string
  • applyPayload: { "sourceField": "targetField" }
  • event: string
  • parametersToRetain: { "key": "value" }

For UPDATE_DATASET

  • datasetCode: string
  • datasetUpdateType: string
  • datasetFieldsMapping: { "formField": "datasetField" }

For VALIDATE_UNIQUE_APPLICATION_PROPERTY

  • propertyKey: string
  • propertyValuePath: string
  • applicationStates: string[]
  • errorMessageCode: string
  • excludeCurrentApplication: boolean (default true)

For URL_CALL

  • source: string
  • sourceDocumentType: string
  • sourceDocumentCode: string

WorkflowAuthorisationDto

FieldTypeDescription
authorisedRolesstring[]Role codes (e.g., REVIEWER, APPROVER)
authorisedUsersUUID[]Specific user IDs
systemAuthorisedbooleanSystem-triggered (no human actor)

At least one of authorisedRoles, authorisedUsers, or systemAuthorised must be set.

WorkflowEndStateConditionDto

FieldTypeDescription
endStateTwoWorkflowSingleEndStateConditionDto[]Conditions for routing to endStateTwo
validationStrategystringStrategy identifier
validationStrategyIdentifierFieldstringField for strategy lookup
childReadyStatesstring[]Child states to wait for
duplicateCheckApplicationStatesstring[]States to check for duplicates

WorkflowSingleEndStateConditionDto

FieldTypeRequiredDescription
parameterstringYesForm field key to evaluate
valuestringYesExpected value
comparatorEFieldComparatorYesGT, LT, EQ, GTE, LTE, NEQ, CONTAINS

WorkflowEventConfigsDto

FieldTypeDescription
eventDueDatestringDue date expression

State Machine Rules

  1. Exactly one initial state (typically SUBMITTED)
  2. Every state must be reachable from the initial state
  3. Terminal states have no outgoing transitions
  4. State names: UPPER_SNAKE_CASE nouns (SUBMITTED, APPROVED, REJECTED)
  5. Event names: UPPER_SNAKE_CASE verbs (APPROVE, REJECT, FORWARD)
  6. Breaking actions = failure path (rejection, cancellation)
  7. Non-breaking actions = success path (certificates, integrations, notifications)

Complete Example -- Simple Approval

[
  {
    "startState": "SUBMITTED",
    "event": "APPROVE",
    "endStateOne": {
      "stateCode": "APPROVED",
      "stateName": "Approved",
      "stateNames": { "en": "Approved", "rw": "Byemejwe" },
      "breakingAction": null,
      "breakingActions": [],
      "nonBreakingActions": [
        {
          "actionType": "NOTIFICATION",
          "args": {
            "notificationType": "DYNAMIC",
            "dynamicTemplate": {
              "en": { "templateCode": "TODO: approval_template_en" }
            }
          }
        },
        {
          "actionType": "GENERATE_CERTIFICATE",
          "args": {
            "certificateName": "Certificate",
            "certificateTemplateCode": { "en": "TODO: cert_template_code" }
          }
        }
      ],
      "nextEvent": null,
      "position": { "x": 400, "y": 100 }
    },
    "endStateTwo": null,
    "endStateCondition": null,
    "authorisation": {
      "authorisedRoles": ["REVIEWER"],
      "authorisedUsers": null,
      "systemAuthorised": null
    },
    "position": { "x": 200, "y": 100 },
    "eventNames": { "en": "Approve", "rw": "Emeza" },
    "eventConfigs": null
  },
  {
    "startState": "SUBMITTED",
    "event": "REJECT",
    "endStateOne": {
      "stateCode": "REJECTED",
      "stateName": "Rejected",
      "stateNames": { "en": "Rejected", "rw": "Byanzwe" },
      "breakingAction": null,
      "breakingActions": [
        {
          "actionType": "NOTIFICATION",
          "args": {
            "notificationType": "DYNAMIC",
            "dynamicTemplate": {
              "en": { "templateCode": "TODO: rejection_template_en" }
            }
          }
        }
      ],
      "nonBreakingActions": [],
      "nextEvent": null,
      "position": { "x": 400, "y": 300 }
    },
    "endStateTwo": null,
    "endStateCondition": null,
    "authorisation": {
      "authorisedRoles": ["REVIEWER"],
      "authorisedUsers": null,
      "systemAuthorised": null
    },
    "position": { "x": 200, "y": 300 },
    "eventNames": { "en": "Reject", "rw": "Hagarika" },
    "eventConfigs": null
  }
]

On this page