Skip to main content

FOI Integration — Complete Swimlane Diagram

End-to-end flow for a typical new FOI request, including Backend → Camunda and Camunda → Backend calls, reopen branches, and all RMA → Camunda message names from Phase 4 onward. Payload variable names appear in the diagram; field definitions are in the sections linked below.

See also (in this document):


Swimlane diagram

Legend: **[payloadVar]** = main JSON / Camunda variable name sent on that step.

Camunda → Backend pattern: Every HTTP call from BPMN (MGR, FEE, EM) is always three steps: (1) process ready → (2) POST Keycloak token → (3) Bearer API call to RMA. Same structure as steps 8→9→10 in Phase 1.

Form.io integration: Fee BPMN calls Form.io via ExternalSubmissionListener (Create Submission) and BPMFormDataPipelineListener (Update Form Submission) — not via RMA.


RMA to Camunda message catalog

Messages sent by request-management-api via POST {BPM_ENGINE_REST_URL}/message (unless noted). Enum source: bpmservice.MessageType · selection: workflowservice.__messagename().

Enum / code nameCamunda messageNameSent by RMA?Trigger (API / condition)Payload variable
intakeclaimfoi-intake-assignmentYesPOST /foirawrequest/{id} — Intake in Progress, not reopened**intakeClaimMessage**
intakereopenfoi-intake-reopenYesPOST /foirawrequest/{id} — Intake in Progress, reopened from Closed**intakeReopenMessage**
intakecompletefoi-intake-completeYesPOST /foirequests (Open + ministries); POST /foirawrequest/{id}Closed, Redirect, or other non–Intake-in-Progress statuses**intakeCompleteMessage**
iaoopenclaimfoi-iao-open-assignmentYesPOST .../ministryrequest/{id}save at Open**openedClaimMessage**
iaoopencompletefoi-iao-open-completeYesPOST .../ministryrequest/{id}complete Open (e.g. → Call For Records)**openedCompleteMessage**
iaoclaimfoi-iao-assignmentYesIAO save-in-place after Open**iaoClaimMessage**
iaocompletefoi-iao-completeYesIAO status transition**iaoCompleteMessage**
iaoreopenfoi-iao-reopenYesMinistry reopened from Closed, or complete after reopen**reopenMessage**
iaocorrenspodencefoi-iao-correnspodenceYesPOST /foiflow/applicantcorrespondence/{requestid}/{ministryrequestid}IAO boundary on user task; typically On Hold (fee estimate / pay online)**correspondenceMessage**
ministryclaimfoi-ministry-assignmentYesPOST .../ministrysave-in-place**ministryClaimMessage**
ministrycompletefoi-ministry-completeYesPOST .../ministrystatus transition**ministryCompleteMessage**
feepaymentfoi-fee-paymentNoMIN BPMN after foi-iao-correnspodence boundary or foi-iao-complete → On Hold— (BPMN internal)
managepaymentfoi-manage-paymentYesPUT .../payments/{id} PAID; sanction / correspondence CANCELLED**feeEventMessage**
foi-updateNoRAW/MIN task listeners — start api-managerrawReqPayload or reqPayload + category
foi-emailNoFEE Notify Payment / Notify Payment Confirmation.setVariables(execution.variables) + servicekey

Message selection (opened requests)

Previous / current contextUser typeActivitymessageName
Status = Open, not processingIAOsavefoi-iao-open-assignment
Status = Open, not processingIAOcompletefoi-iao-open-complete
Status = ReopenIAOeitherfoi-iao-reopen
After OpenIAOsavefoi-iao-assignment
After OpenIAOcompletefoi-iao-complete
Ministry statesministrysavefoi-ministry-assignment
Ministry statesministrycompletefoi-ministry-complete
Reopened from Closed (ministry)IAOcompletefoi-iao-reopen (overrides complete message)
Applicant correspondence (IAO)IAOboundary eventfoi-iao-correnspodencePOST /foiflow/applicantcorrespondence/..., often when moving to On Hold

Reopen detection

ScopeConditionMessage
Raw (intake)Last two states: new ≠ old, old = Closedfoi-intake-reopen instead of foi-intake-assignment
Raw (intake)Closed at intake → Pre-Closure SLA window; user returns to Intake in ProgressSame foi-intake-reopen — caught at Event_0wrm0sw (returns to Intake Analyst task)
Ministry (opened)Same state-history check on ministry requestfoi-iao-reopen on complete, or when previous status = Reopen

BPMN internal message correlations

These messages are not sent by RMA. They are raised inside BPMN via RuntimeService.createMessageCorrelation(...) from task listeners, boundary events, or intermediate throw events.

Source BPMN: foi-rawrequest-processing.bpmn, foi-request-processing.bpmn, foi-initial-payment-submission.bpmn (foi-fee-processing).

Internal message catalog

Camunda messageNameBPMN processProducer (element)Trigger / conditionVariables passed on correlateStarts / affects
foi-updatefoi-rawrequest-processingEvent_1nxaaj2 Send PIDProcess start.setVariables(execution.variables) · rawReqPayload {wfinstanceid, notes} · category=foi-rawrequest-updatefoi-rawrequest-api-manager → PUT addwfinstanceid
foi-updatefoi-rawrequest-processingIntake Analyst task · assignmentIntake task claimedSame pattern · rawReqPayload includes status=Intake in Progressapi-manager → PUT addwfinstanceid
foi-updatefoi-rawrequest-processingIntake Analyst task · completeIntake task completed via foi-intake-complete boundary (Open → Archived note; Closed/Redirect → gateway routing)Same pattern · rawReqPayload includes status=Archivedapi-manager → PUT addwfinstanceid
foi-updatefoi-request-processingStart scriptMIN subprocess started (per ministry).setVariables(execution.variables) · reqPayload {wfinstanceId: pid} · category=foi-request-updateapi-manager → PUT foirequests
foi-fee-paymentfoi-request-processingEvent_1tvpamu Complete boundary · IAO TeamRMA foi-iao-complete and status == On Hold · issync == false · isofflinepayment == false.setVariables(execution.variables) · sets applicantCorrespondenceId=0, templateName="" before correlate · feeflow=ONGOING afterfoi-fee-processing subprocess
foi-fee-paymentfoi-request-processingcorrenspodance Correspondence boundary · IAO TeamRMA foi-iao-correnspodence · status != Closed.setVariables(execution.variables) · servicekey=correspondence · feeflow=ONGOING afterfoi-fee-processing subprocess (Communication Log path)
foi-manage-paymentfoi-request-processingEvent_1tvpamu Complete boundary · IAO TeamLeave On Hold while feeflow==ONGOING and isPaymentActive · issync == false.processInstanceVariableEquals("axisRequestId", …) · paymentstatus=CANCELLED · status · foiRequestID · ministryRequestIDExisting fee workflow instance
foi-manage-paymentfoi-fee-processingEvent_05bv4ti Payment Update ReceivedRMA PUT .../payments/{id} (PAID) or RMA/ministry cancel paths (CANCELLED)correlationKeys.axisRequestId (from RMA) or variables set by MIN boundaryFee workflow continues → Update Form Submission
foi-emailfoi-fee-processingEvent_1y2hfyk Notify PaymentAfter payment link saved to RMA.setVariables(execution.variables) · servicekey: correspondence if correspondence path · payoutstanding if prevStatus==Response · else payonlinefoi-email-processing → applicant payment-link email
foi-emailfoi-fee-processingEvent_0q2irqu Notify Payment ConfirmationAfter PAID path · Sync FOI Status.setVariables(execution.variables) · servicekey: outstanding-payment-receipt if Response/outstanding · else fee-estimate-payment-receiptfoi-email-processing → payment receipt email
foi-iao-completefoi-fee-processing → MINActivity_1ka6mqq Sync FOI Statuspaymentstatus == PAIDfoistatuspayload: localCorrelationKeys.id=fileNumber · processVariables.foiRequestMetaData (status may = nextStateName)MIN IAO Team Complete boundary — updates ministry WF state (Camunda → Camunda)

All foi-update and most fee/email correlations use .setVariables(execution.variables) so inherited scope (foiApiUrl, foiRequestID, ministryRequestID, axisRequestId, etc.) is available to the target process.

Call activity — RAW → MIN (not a message)

DirectionBPMN elementVariables passed in
RAW → MINCall Activity foi-request-processingfoiRequestMetaData, pidrawRequestPID, idrawRequestID, foiApiUrl

Boundary events — side effects (before internal correlate)

These boundaries parse foiRequestMetaData and set execution variables; some also complete tasks without sending a new message.

BoundaryAttached toTriggered by (RMA message)Key variables setInternal message raised
ClaimOpen IAO task Activity_0cj09mlfoi-iao-open-assignmentReassigns assignedGroup / assignedTo
CompleteOpen IAO task Activity_0cj09mlfoi-iao-open-completestatus, minTaskName, iaoTaskName · completes Open task— (forks to CFR parallel or Closed)
ClaimIAO Team Activity_0jdrlczfoi-iao-assignmentReassigns group / assignee on IAO task
CompleteIAO Team Activity_0jdrlczfoi-iao-completestatus, ministryRequestID, axisRequestId, minTaskName · if Closed: completes ministry taskfoi-fee-payment (→ On Hold) or foi-manage-payment (leave On Hold)
CorrespondenceIAO Team Activity_0jdrlczfoi-iao-correnspodencestatus, ministryRequestID, axisRequestId, applicantCorrespondenceId, templateNamefoi-fee-payment + servicekey=correspondence
ClaimMinistry Coordinator Activity_085uygzfoi-ministry-assignmentReassigns group / assignee on ministry task
CompleteMinistry Coordinator Activity_085uygzfoi-ministry-completestatus, minTaskName · if Closed: completes IAO + ministry tasks— (joins Pre-Closure SLA)

Payment workflow — internal entry and outcomes

StageTypeDetail
Initial paymentEntryFee Estimate → On Hold via Complete boundary · form payfeeonline · email payonline or correspondence
Outstanding paymentEntryResponse → On Hold via Complete or Correspondence boundary · form payoutstandingform · email payoutstanding
Link generationFEE stepsGET payonline → Form.io Create Submission → POST /foipaymentfoi-email Notify Payment
PAIDOutcomeApplicant pays via Form.io · RMA foi-manage-payment → Update Form Submission → Sync FOI Status → receipt email
CANCELLEDOutcomeIAO leaves On Hold (MIN boundary) or RMA cancel · Update Form Submission → POST /foipayment/.../cancel
EXPIREDOutcomeDaily timer vs paymentExpiryDate (~20 days) · POST /foinotifications/.../payment/expiry

Parallel tasks and closure (no message — workflow structure)

EventBPMN elementProcessWhenEffect
Pre-Closure SLA (intake)Event_03aj013foi-rawrequest-processingAfter Closed at intakeDaily timer (22:00); intake_closure_sla_days increments (max 5)
End (intake closed)Event_043z2u1foi-rawrequest-processingintake_closure_sla_days > 5Raw workflow ends — Closed at Intake
Reopen (intake)Event_0wrm0swfoi-rawrequest-processingRMA foi-intake-reopenReturns to Intake Analyst task
Parallel forkGateway_0wfu2wzfoi-request-processingOpen → Call For RecordsIAO Team + Ministry Coordinator run in parallel
Parallel forkGateway_0ezgrjzfoi-request-processingReopen to non-Open statusRecreates IAO Team + Ministry Coordinator
Pre-Closure SLAEvent_14uk8xbfoi-request-processingAfter Closed (ministry)Daily timer; closure_sla_days increments (max 5)
EndEvent_0pwci99foi-request-processingclosure_sla_days > 5Ministry subprocess ends
ReopenEvent_0a37bnffoi-request-processingRMA foi-iao-reopenReturns to Open task or parallel CFR tasks

Variable reference tables

Auth tokens

VariableUsed inFields / valueSet by
access_tokenRMA → Camunda callsOAuth2 bearer tokenKeycloak response to BPM credentials
accessTokenCamunda → RMA callsOAuth2 bearer tokenKeycloak response to KEYCLOAK_CLIENTID credentials
Token request bodyBoth directionsgrant_type = client_credentialsHTTP connector / bpmservice

Camunda → Backend token request (every MGR / FEE / EM API call):

ItemValue
MethodPOST
URL{KEYCLOAK_URL}/auth/realms/{KEYCLOAK_URL_REALM}/protocol/openid-connect/token
HeadersContent-Type: application/x-www-form-urlencoded, Authorization: Basic base64(KEYCLOAK_CLIENTID:KEYCLOAK_CLIENTSECRET)
Bodygrant_type=client_credentials
ThenAuthorization: Bearer {accessToken} on the RMA API call

startProcessVariables

Camunda: POST /process-definition/key/foi-request/start Triggered by: POST /api/foirawrequests, sync recreate

FieldTypeSourceDescription
idIntegerRaw request DB idPrimary correlation key for raw workflow
assignedGroupStringForm / intake assignee groupCamunda candidate group hint
assignedToStringForm / intake assignee user idOptional direct assignee

rawReqPayload

Backend: PUT /api/foirawrequestbpm/addwfinstanceid/{id} Triggered by: foi-rawrequest-processing.bpmnfoi-update (category foi-rawrequest-update)

FieldTypeWhen sentBackend uses?
wfinstanceidString (UUID)Process start, task assign, task completeYes — saved to FOIRawRequests.wfinstanceid
notesStringAll variantsYes — audit note on raw request
statusStringTask assign / completeNo — sent by BPMN but API ignores; DB status unchanged

Example (process start):

{ "wfinstanceid": "<camunda-pid>", "notes": "Workflow ID update" }

reqPayload

Backend: PUT /api/foirequests/{foiRequestID} Triggered by: foi-request-processing.bpmnfoi-update (category foi-request-update)

FieldTypeSourceDescription
wfinstanceIdString (UUID)Ministry subprocess pidSaved to FOIRequests.wfinstanceid

Example:

{ "wfinstanceId": "<ministry-process-pid>" }

intakeClaimMessage / intakeReopenMessage

Camunda: POST /message Triggered by: POST /api/foirawrequest/{id} (Intake in Progress)

Payload aliasmessageNameWhen
**intakeClaimMessage**foi-intake-assignmentNormal intake claim
**intakeReopenMessage**foi-intake-reopenRaw request reopened from Closed
FieldLocation in messageSource
processInstanceIdTop-levelRaw request wfinstanceid from DB
messageNameTop-levelSee table above
assignedToprocessVariables.assignedTo.valueRequest body assignedTo

intakeCompleteMessage

Camunda: POST /messagefoi-intake-complete Triggered by: POST /api/foirequests (Open + ministries); POST /api/foirawrequest/{id} when status is Closed, Redirect, or other non–Intake-in-Progress outcomes

FieldLocationDescription
processInstanceIdTop-levelRaw workflow instance id
messageNameTop-levelfoi-intake-complete
foiRequestMetaDataprocessVariables — JSON stringSee **foiRequestMetaData (intake)** table

foiRequestMetaData (intake — inside intakeCompleteMessage)

FieldTypeDescription
idNumberRaw request id
statusString"Open" on open transition
ministriesArrayMinistry request objects created on open
assignedGroupStringIAO group
assignedToStringIAO assignee

Opened / ministry / reopen messages (RMA → Camunda)

Triggered by: POST /api/foirequests/.../ministryrequest/... (IAO or ministry routes)

Two payload shapes depending on activity (save vs complete):

Claim / save-in-place (*-assignment messages)

Payload aliases: **openedClaimMessage, **iaoClaimMessage, **ministryClaimMessage**

messageNameUserWhen
foi-iao-open-assignmentIAOSave at Open
foi-iao-assignmentIAOSave after Open
foi-ministry-assignmentministrySave-in-place
FieldLocation
processInstanceIdTop-level (ministry wf instance or file correlation id)
messageNameTop-level
assignedToprocessVariables.assignedTo.value

Complete / reopen / correspondence (*-complete, foi-iao-reopen, foi-iao-correnspodence)

Payload aliases: **openedCompleteMessage, **iaoCompleteMessage, **ministryCompleteMessage**, **reopenMessage**, **correspondenceMessage**

messageNameUserWhen
foi-iao-open-completeIAOComplete Open (e.g. → Call For Records)
foi-iao-completeIAOStatus transition (incl. → On Hold via Complete boundary)
foi-ministry-completeministryStatus transition
foi-iao-reopenIAOReopen from Closed, or complete after reopen
foi-iao-correnspodenceIAO**POST /foiflow/applicantcorrespondence/...** — boundary on IAO Team task; typically On Hold templates
FieldLocation
messageNameTop-level
processInstanceIdTop-level — ministry workflow instance id
localCorrelationKeys.idFile number
foiRequestMetaDataprocessVariables — JSON string

foiRequestMetaData (opened — inside complete / reopen messages)

FieldTypeDescription
idStringFile number
previousstatusStringPrior ministry status
statusStringCurrent ministry status
assignedGroupStringIAO or ministry group
assignedToStringAssignee user id
assignedministrygroupStringMinistry team group
ministryRequestIDNumberMinistry request primary key
isPaymentActiveBooleanActive CFR/application payment exists
paymentExpiryDateStringPayment link expiry
axisRequestIdStringAXIS correlation id
issyncBooleantrue when from sync API
isofflinepaymentBooleanOffline payment flag

feeEventMessage

Camunda: POST /messagefoi-manage-payment Triggered by: Payment PUT, CFR sanction, correspondence (cancel)

FieldLocationDescription
messageNameTop-levelfoi-manage-payment
correlationKeys.axisRequestIdCorrelationLinks to payment workflow instance
paymentstatusprocessVariables"PAID" or "CANCELLED"
foiRequestMetaDataprocessVariables — JSON stringSee **foiRequestMetaData (fee)** table

foiRequestMetaData (fee — inside feeEventMessage)

FieldTypeDescription
idStringFile / id number
statusStringCurrent request state
assignedGroupStringIAO group
assignedToStringIAO assignee
assignedministrygroupStringMinistry group
ministryRequestIDNumberMinistry request id
foiRequestIDNumberParent FOI request id
nextStateNameStringTarget state after payment (PAID flow)

correspondenceMessage

Camunda: POST /messagefoi-iao-correnspodence Triggered by: POST /api/foiflow/applicantcorrespondence/...

FieldLocationDescription
messageNameTop-levelfoi-iao-correnspodence
processInstanceIdTop-levelMinistry workflow instance id
localCorrelationKeys.idCorrelationFile number
foiRequestMetaDataprocessVariables — JSON stringSee table below

foiRequestMetaData (correspondence)

FieldTypeDescription
idStringFile number
statusStringCurrent state
ministryRequestIDNumberMinistry request id
paymentExpiryDateStringFrom correspondence template attributes
axisRequestIdStringAXIS id
applicantcorrespondenceidNumberSaved correspondence log id
templatenameStringTemplate name (spaces removed)

saveDataPayload (payment)

Backend: POST /api/foipayment/{foiRequestID}/ministryrequest/{ministryRequestID} (create) or .../cancel (cancel) Triggered by: foi-fee-processing.bpmn — create after Form.io submission; cancel when paymentstatus == CANCELLED

FieldTypeSourceDescription
paymenturlString{foiwebUrl}/public/form/{formId}/submission/{submissionId}/editApplicant payment link
paymentexpirydateDateCamunda variable paymentExpiryDateLink expiry date

Cancel path: same **saveDataPayload** variable and fields (paymenturl, paymentexpirydate), POST .../foipayment/.../cancel — after Update Form Submission when foi-manage-payment sets paymentstatus=CANCELLED.


saveDataPayload (email)

Backend: POST /api/foiemail/.../{servicekey} Triggered by: foi-email-processing.bpmn

FieldTypeWhen presentDescription
(empty object)Most service keys{} — no body fields required
templateNameStringcorrespondence, PAYOUTSTANDING, PAYONLINEEmail template
applicantCorrespondenceIdNumberSame as aboveLinks email to correspondence log

Common servicekey values: correspondence, payonline, payoutstanding, outstanding-payment-receipt, fee-estimate-payment-receipt

Acknowledge call: POST .../acknowledge — no payload body.


foistatuspayload

Camunda internal: POST {BPM_ENGINE_REST_URL}/message Triggered by: foi-fee-processing.bpmn after payment (sync ministry WF state)

FieldLocationDescription
messageNameTop-levelTypically foi-iao-complete
localCorrelationKeys.idCorrelationfileNumber
foiRequestMetaDataprocessVariablesUpdated metadata (status may reflect nextStateName)

This is Camunda → Camunda, not a backend API call. Included because it closes the payment loop before the UI sees the updated state.


Camunda process variables (passed between BPMN, not HTTP bodies)

VariableSet byUsed byDescription
pidEngine on startRAW, MIN subprocessesCamunda process instance UUID
idstartProcessVariablesRAW, api-manager URL pathRaw request id
foiRequestIDOpen / ministry flowFee, email, notification URLsParent FOI request id
ministryRequestIDOpen / ministry flowFee, email, notification URLsMinistry request id
foiApiUrlEnv FOI_REQ_MANAGEMENT_API_URLAll HTTP connector tasksBackend base URL
foiwebUrlEnv FORMSFLOW_WEB_URLFee BPMNBuilds paymenturl
axisRequestIdRequest metadataPayment correlationLinks fee workflow to request
fileNumberMinistry metadataOpened message correlationMinistry file number
categoryBPMN scriptapi-manager gatewayfoi-rawrequest-update
servicekeyFee / correspondence scriptsEmail URL path segmentEmail type routing
formIdCreate Submission (Form.io)Fee save API, Update Form SubmissionForm.io form id
submissionIdCreate Submission (Form.io)Fee save API, Update Form SubmissionForm.io submission id
paymentFormNameGET payonline listenerCreate Submissionpayfeeonline
formioURLFee BPMN startExternalSubmissionListenerForm.io API base URL

Form.io integration (fee BPMN only)

StepBPMN taskListenerDirectionDetails
Create SubmissionActivity_0k05bsnExternalSubmissionListenerFEE → Form.ioCreates payment form submission; outputs formId, submissionId
Update Form SubmissionActivity_1mkqp7nBPMFormDataPipelineListenerFEE → Form.ioAfter foi-manage-payment; updates status, paymentstatus on existing submission

Env vars on fee process start: FORMIO_URL, FORMIO_ROOT_EMAIL, FORMIO_ROOT_PASSWORD, FORMSFLOW_WEB_URL (foiwebUrl).


Scheduled jobs (not in main swimlane)

These Camunda processes also call the backend using the same Get Token → API pattern:

ProcessStepsBackend callPayload variable
foi-cache-refresh.bpmnKC token → RMAPOST /api/foiflow/cache/refreshOptional { "key": "..." } or empty
foi-duedate-reminder.bpmnKC token → RMAPOST /api/foinotifications/reminderNone