A transition moves the application to a new state; actions run on the way. Each action is {"actionType": …, "args": {…}} placed on an end state (endStateOne or endStateTwo):
Rule of thumb: anything the next step depends on (bill, office, certificate, photo, slot) is breaking; anything that only informs (notifications) is non-breaking.
↻ If the breaking action fails, nothing after it happens and the officer sees an error.
STATIC: you write the subject, email body and SMS text in the workflow, per language. NOTIFICATION_ENGINE_TEMPLATE: you reference templates maintained centrally in the notification engine (for example PAYMENT_PENDING, PENDING_RESUBMISSION, PAYMENT_EXPIRED, PENDING_ASSIGN_OFFICE_PAID, REJECTED, RESUBMITTED). The engine fills placeholders such as ${applicantName}, ${serviceName} and ${billReferenceNumber}.
Static
{
"actionType": "NOTIFICATION",
"args": {
"notificationType": "STATIC",
"staticTemplate": {
"en": {
"subject": "Application approved",
"emailBody": "<p>Dear ${applicantName}, your ${serviceName} is approved.</p>",
"smsBody": "Your ${serviceName} (${applicationNumber}) is approved."
}
}
}
}
Template
{
"actionType": "NOTIFICATION",
"args": {
"notificationType": "NOTIFICATION_ENGINE_TEMPLATE",
"dynamicTemplate": {
"en": {
"smsTemplateName": "PAYMENT_PENDING_SMS_EN",
"emailTemplateName": "PAYMENT_PENDING_EMAIL_EN"
}
}
}
}
With the certificate
{
"actionType": "NOTIFICATION",
"args": {
"notificationType": "STATIC",
"staticTemplate": { "en": { "subject": "Your clearance", "emailBody": "...", "smsBody": "..." } },
"attachment": [ { "sourceType": "DOCUMENT_GENERATION_ENGINE" } ]
}
}
Bill
{ "actionType": "BILL_ID_GENERATION", "args": null }
Certificate
{
"actionType": "GENERATE_CERTIFICATE",
"args": {
"certificateName": "TE4I3DV_CourseDemoTravelClearance",
"certificateTemplateCode": { "en-US": "TE4I3DV" },
"certificateExpirationDays": 7
}
}
Slot
{
"actionType": "SLOT_BOOKING",
"args": {
"groupIdField": "slotbooking.group.id",
"timeRangeIdField": "slotbooking.timeRange.id",
"seatsField": "slotbooking.seats"
}
}
ID photo
{
"actionType": "FETCH_ID_PHOTO",
"args": {
"fetchValueAttribute": ["applicantNID"],
"fetchValueTypeAttribute": "applicantDocumentType.id"
}
}
Integration
{
"actionType": "INTEGRATION",
"args": { "endpointCode": "TRAFFIC_POLICE_API", "async": false }
}
Every action type accepted by the application engine
| actionType | What it does | Main args | Usually |
|---|---|---|---|
BILL_ID_GENERATION |
Creates the bill the applicant pays; triggers the price calculation | none (or receiptMetadata) | Breaking |
NOTIFICATION |
SMS and email to the applicant | notificationType, staticTemplate or dynamicTemplate, attachment | Non-breaking |
RESEND_NOTIFICATION |
Sends a previous notification again | as NOTIFICATION | Non-breaking |
INTERNAL_NOTIFICATION |
Emails / SMS fixed staff recipients | internalEmailNotificationRecipients, internalSmsNotificationRecipients | Non-breaking |
FORM_FIELD_NOTIFICATION |
Notifies a phone or email typed in the form | formFieldsSmsNotificationRecipients, formFieldsEmailNotificationRecipients | Non-breaking |
OFFICE_ASSIGNMENT |
Chooses the office that will process | officeAssignmentType, officeId / formFieldKey(s), officeLevel | Breaking |
OFFICE_ASSIGNMENT_NOTIFICATION |
Notifies the officers of the assigned office | as OFFICE_ASSIGNMENT | Non-breaking |
GENERATE_CERTIFICATE |
Renders the certificate from a template | certificateName, certificateTemplateCode, certificateExpirationDays | Breaking |
REGISTER_EXTERNAL_CERTIFICATE |
Registers a document produced outside (e.g. by a partner) as the certificate | certificateName, certificateNames (title per language), attachmentKey, languageKey, certificateExpirationDays | Breaking |
FETCH_ID_PHOTO |
Fetches the official ID photo | fetchValueAttribute, fetchValueTypeAttribute | Breaking |
SLOT_BOOKING / SLOT_REBOOKING / REDEEM_SLOT |
Books, moves or consumes an appointment slot | groupIdField, timeRangeIdField, seatsField | Breaking |
INTEGRATION |
Calls a partner endpoint configured by the integration manager | endpointCode, async | Breaking or non-breaking |
INTEGRATION_UPDATE |
Calls an endpoint and stores its response on the application | endpointCode, parametersToRetain | Breaking |
UPDATE_DATASET |
Writes application values into a dataset | datasetCode, datasetUpdateType, datasetFieldsMapping | Breaking |
VALIDATE_UNIQUE_APPLICATION_PROPERTY |
Rejects a duplicate (same value already in an open application) | propertyKey, propertyValuePath, applicationStates, errorMessageCode | Breaking |
SYSTEM_REQUEST_FOR_ACTION |
Sends the application back to the applicant automatically | fieldNames, officerSummary | Breaking |
EXECUTE_PRICING |
Recalculates the price | none | Breaking |
APPLY_SERVICE / APPLY_NORMAL_SERVICE / CREATE_CHILD_APPLICATION / APPLY_OR_RESUBMIT_CHILD_APPLICATION |
Creates or resubmits a linked (child) application of another service | serviceCode, applyPayload, childResubmitConditions | Breaking |
TRIGGER_PARENT / TRIGGER_PARENT_SERVICE_EVENT / TRIGGER_CHILD_SERVICE_EVENT |
Fires an event on the parent or child application | TRIGGER_PARENT: event, additionalPayload; *_SERVICE_EVENT: serviceCode, event | Breaking |
MASTER_BILL_ID_GENERATION / SERVICE_CENTER_MASTER_BILL_ID_GENERATION |
One bill for a group of applications (bulk, service centres) | as BILL_ID_GENERATION | Breaking |
URL_CALL |
Not implemented: the engine builds the payload and calls nothing. Use INTEGRATION | (url, method, headers are ignored) | n/a |
Gotcha · URL_CALL does nothing
URL_CALL is still accepted in a workflow, but the engine only prepares the payload and never calls the URL. Anything that must reach an external system goes through an INTEGRATION action and an endpoint configured by the integration manager.
Gotcha · TRANSITION is an event, not an action
To move an application from one state to another without a person, use a transition whose event is system-authorised (for example with nextEvent). There is no action that "jumps" states.
| Item | Matches |
|---|---|
| An applicant must pay before processing | BILL_ID_GENERATION |
| The approved licence must be downloadable | GENERATE_CERTIFICATE |
| The applicant books a driving test time | SLOT_BOOKING |
| The applicant gets an SMS when rejected | NOTIFICATION |
Your payment-confirmation SMS fails because the SMS gateway is down. What should happen to the application, and how do you configure it?
A. A failed notification must never block a paid applicant. Non-breaking actions run after the state is saved.
Tip · reference
← B6 · Payment routing: account, code and merchant · B8 · Office assignment and routing →