Skip to main content

Signal Process

Overview

The SignalProcessInstanceCommand sends data/signals to a waiting process instance. This unified command works for UserTask, ReceiveTask (form mode), and ReceiveTask (webhook mode via correlationKey), providing a single API for all process continuations.

Unified Signal API

SignalProcessInstanceCommand supports three lookup modes:

  1. instanceGuid — Look up by process instance ID (for UI/form submissions)
  2. correlationKey — Look up by correlation key (for external webhooks)
  3. Both — Use both for explicit targeting

The backend automatically detects the task type and handles CallbackRegistry updates internally.

API Endpoint

POST /api/core/cmd

Headers

Content-Type: application/json
Authorization: Bearer {access_token}
X-Tenant-ID: {tenant_id}

Request Structure

Format 1: By Instance GUID (UI/Form Mode)

Use when you know the process instance ID (e.g., frontend form submissions).

{
"cmd": "SignalProcessInstanceCommand",
"data": {
"instanceGuid": "PI-20260210-abc123",
"taskId": "Activity_Approval",
"callbackData": {
"approved": true,
"comments": "Application looks good"
}
}
}

Format 2: By Correlation Key (Webhook Mode)

Use when an external system only has the correlation key (e.g., payment gateway callback, Mono webhook).

{
"cmd": "SignalProcessInstanceCommand",
"data": {
"correlationKey": "REQ-20260210-3048",
"callbackData": {
"status": "active",
"accountNumber": "0123456789",
"balance": 50000
}
}
}

Format 3: Legacy Format (Still Supported)

{
"cmd": "SignalProcessInstanceCommand",
"data": {
"instanceGuid": "PI-20260210-abc123",
"signalPayload": {
"approved": true,
"comments": "Application looks good"
}
}
}

Request Fields

FieldTypeRequiredDescription
instanceGuidstringEither this or correlationKeyThe unique identifier of the process instance
correlationKeystringEither this or instanceGuidCorrelation key from the ReceiveTask's CallbackRegistry
callbackDataobjectEither this or signalPayloadData to send to the process (recommended)
signalPayloadobjectEither this or callbackDataLegacy parameter (fallback for callbackData)
taskIdstringNoSpecific task ID to signal. Auto-resolved from correlationKey if not provided. Uses first waiting task as fallback
currentUserstringNoUser performing the action (defaults to "system")
Correlation Key Resolution

When you provide correlationKey instead of instanceGuid:

  1. The command looks up the CallbackRegistry table for a pending entry matching the key
  2. Resolves the instanceGuid from CallbackRegistry.ParentInstanceId
  3. Resolves the taskId from CallbackRegistry.CallbackTaskId (if not explicitly provided)
  4. Proceeds with normal signal processing
  5. Marks the CallbackRegistry as Completed after successful signal

Result Storage

Important — No Top-Level Context Merge

Signal/callback data is stored only in named variables, never merged into the top-level process context. This prevents accidental overwrites of existing variables like userId, entityId, etc.

Results are stored in these locations:

LocationWhenHow to Access in Scripts
lastReceiveTaskResultAlways (for ReceiveTask)context.lastReceiveTaskResult.fieldName
lastUserTaskResultAlways (for UserTask)context.lastUserTaskResult.fieldName
Custom resultVariableWhen configured on the task in BPMN designercontext.myVariable.fieldName

Example: If a ReceiveTask has resultVariable = "paymentResult":

// In subsequent ScriptTask
var status = context.paymentResult.status; // "success"
var amount = context.paymentResult.amount; // 50000
var txnId = context.paymentResult.transactionId; // "TXN-987654"

When to Use Signal Process

1. Completing UserTasks (Form Submission)

When a process reaches a UserTask and waits for human action:

{
"cmd": "SignalProcessInstanceCommand",
"data": {
"instanceGuid": "loan-approval-123",
"taskId": "Task_OfficerReview",
"callbackData": {
"action": "approve",
"officerComments": "Credit score acceptable",
"approvedAmount": 50000
}
}
}

2. External Webhook via Correlation Key

When an external system (e.g., Mono, Paystack) sends a webhook callback:

{
"cmd": "SignalProcessInstanceCommand",
"data": {
"correlationKey": "REQ-20260210-3048",
"callbackData": {
"event": "account_updated",
"status": "active",
"accountNumber": "0123456789",
"bankName": "GTBank",
"balance": 150000
}
}
}

3. ReceiveTask Form Mode (UI)

When a ReceiveTask is displayed as a form in the frontend:

{
"cmd": "SignalProcessInstanceCommand",
"data": {
"instanceGuid": "kyc-verification-456",
"taskId": "Activity_WaitForDocument",
"callbackData": {
"documentType": "passport",
"documentUrl": "https://storage.example.com/doc123.pdf",
"uploadedBy": "customer@email.com"
}
}
}

Response Structure

Successful Signal (Process Continues)

{
"isSuccessful": true,
"message": "Signal processed successfully.",
"statusCode": "00",
"data": {
"instanceGuid": "loan-approval-123",
"status": "running",
"currentActivityId": "Task_DisburseLoan",
"waitingTasks": [],
"executionLogs": [...]
}
}

Successful Signal (Process Waiting Again)

{
"isSuccessful": true,
"message": "Signal processed successfully.",
"statusCode": "00",
"data": {
"instanceGuid": "loan-approval-123",
"status": "waiting",
"currentActivityId": "Task_ManagerApproval",
"waitingTasks": [
{
"taskId": "Task_ManagerApproval",
"taskName": "Manager Approval Required",
"taskType": "bpmn:UserTask"
}
]
}
}

Successful Signal (Process Completed)

{
"isSuccessful": true,
"message": "Signal processed successfully.",
"statusCode": "00",
"data": {
"instanceGuid": "loan-approval-123",
"status": "completed"
}
}

Error: Neither instanceGuid nor correlationKey

{
"isSuccessful": false,
"message": "Either 'instanceGuid' or 'correlationKey' must be provided.",
"statusCode": "99"
}

Error: Correlation Key Not Found

{
"isSuccessful": false,
"message": "No pending callback found for correlationKey 'INVALID-KEY'.",
"statusCode": "99"
}

Error: Instance Not Found

{
"isSuccessful": false,
"message": "Process instance 'invalid-guid' not found.",
"statusCode": "99"
}

Comparison: SignalProcessInstanceCommand vs ReturnCallbackCommand

Both commands can resume a ReceiveTask. Choose based on your use case:

AspectSignalProcessInstanceCommandReturnCallbackCommand
Lookup by instanceGuid✅ Yes❌ No
Lookup by correlationKey✅ Yes (new)✅ Yes
Lookup by childInstanceId❌ No✅ Yes (for subprocesses)
Handles UserTask✅ Yes❌ No
Handles ReceiveTask✅ Yes✅ Yes
Handles CallActivity❌ No✅ Yes
ServerScript execution✅ Yes (if configured)❌ No
State sourceProcessInstance.StateJson (live)CallbackRegistry.ParentProcessState (snapshot)
Typical callerFrontend / webhook controllersExternal webhooks / subprocesses
Recommendation
  • Use SignalProcessInstanceCommand as the default for all signals (UserTask, ReceiveTask form mode, and webhooks)
  • Use ReturnCallbackCommand only for subprocess (CallActivity) callbacks or legacy webhook integrations

Process Flow with Signals

Best Practices

1. Use Explicit Correlation Keys

Set meaningful correlation keys on ReceiveTask nodes in the BPMN designer:

correlationKey: context.requestId
resultVariable: webhookResult

This makes it easy for external systems to signal the correct process.

2. Access Results via Named Variables

// ✅ GOOD — Access via resultVariable
var result = context.webhookResult;
var status = result.status;

// ✅ ALSO GOOD — Access via default variable
var result = context.lastReceiveTaskResult;

// ❌ BAD — Don't expect results in top-level context
// var status = context.status; // This won't work!

3. Include taskId When Possible

When signaling by instanceGuid, include taskId to target the specific waiting task:

{
"data": {
"instanceGuid": "PI-123",
"taskId": "Activity_WaitForPayment",
"callbackData": { "status": "paid" }
}
}

4. Handle All Response States

const response = await signalProcess(data);

switch (response.data.status) {
case 'waiting':
showNextTaskForm(response.data.waitingTasks[0]);
break;
case 'running':
showProcessingMessage();
break;
case 'completed':
showCompletionMessage();
break;
case 'error':
showErrorMessage(response.message);
break;
}