Skip to main content

Return Callback

Overviewโ€‹

The ReturnCallbackCommand resumes a paused process by returning results from a callback. This command handles two types of callbacks:

  1. Subprocess Callbacks (CallActivity) - Parent process waits for child subprocess to complete
  2. External Callbacks (ReceiveTask) - Process waits for webhook, payment gateway, or third-party API response

API Endpointโ€‹

POST /api/core/cmd

Headersโ€‹

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

Request Structureโ€‹

Two Request Types

The command accepts either childInstanceId or correlationKey, but not both. Choose based on your scenario:

  • childInstanceId: For subprocess (CallActivity) completions
  • correlationKey: For external callbacks (ReceiveTask, webhooks, API responses)

Request Type 1: Subprocess Callback (Using childInstanceId)โ€‹

When to Use: Parent process pauses for a child subprocess (CallActivity) to complete

{
"cmd": "ReturnCallbackCommand",
"data": {
"childInstanceId": "child-process-abc-123",
"results": {
"creditScore": 750,
"riskLevel": "Low",
"approved": true
},
"isFailed": false
}
}

Key Points:

  • childInstanceId is the process instance ID of the child subprocess
  • Parent process will resume at the CallActivity that spawned the child
  • results object is merged into parent process variables

Request Type 2: External Callback (Using correlationKey)โ€‹

When to Use: Process waits for external system (webhook, email approval, payment gateway, third-party API)

{
"cmd": "ReturnCallbackCommand",
"data": {
"correlationKey": "APPROVAL-LOAN123-1736544000",
"results": {
"approved": true,
"decidedBy": "manager@bank.com",
"decidedAt": "2026-01-10T14:30:00Z",
"comments": "Application approved"
},
"isFailed": false
}
}

Key Points:

  • correlationKey is defined in the BPMN ReceiveTask's correlationKey property
  • Can be auto-generated (${instanceId}_${taskId}) or custom (${approvalId})
  • Process resumes at the ReceiveTask that registered the callback
  • results object is stored in the variable specified by ReceiveTask's resultVariable

Failed Callback (Works with Both Types)โ€‹

Scenario: Callback indicates a failure (payment declined, approval rejected, subprocess error)

With childInstanceId:

{
"cmd": "ReturnCallbackCommand",
"data": {
"childInstanceId": "child-process-abc-123",
"isFailed": true,
"errorMessage": "Credit check service unavailable"
}
}

With correlationKey:

{
"cmd": "ReturnCallbackCommand",
"data": {
"correlationKey": "PAYMENT-TXN-987654",
"isFailed": true,
"errorMessage": "Payment declined - insufficient funds"
}
}

What Happens:

  • Process resumes but takes error/rejection path
  • Error boundary event can catch the failure
  • Alternative flow can be triggered (e.g., retry logic, notification)

Request Fieldsโ€‹

FieldTypeRequiredDescription
childInstanceIdstringEither this or correlationKeyID of child subprocess (for CallActivity)
correlationKeystringEither this or childInstanceIdCorrelation key (for external callbacks/ReceiveTask)
resultsobjectYesData to return to parent process. Will be stored in process variables
isFailedbooleanNoWhether the callback failed (default: false)
errorMessagestringNoError message if callback failed
Key Difference
  • childInstanceId: Used when a subprocess completes (CallActivity)
  • correlationKey: Used when an external system sends a webhook (ReceiveTask)

Use Casesโ€‹

1. Email Approval Callbackโ€‹

Scenario: User clicks "Approve" link in email, webhook calls this command

{
"cmd": "ReturnCallbackCommand",
"data": {
"correlationKey": "APPROVAL-LOAN123-1736544000",
"results": {
"approved": true,
"decision": "approved",
"decidedBy": "manager@bank.com",
"decidedAt": "2026-01-10T14:30:00Z",
"comments": "Loan approved after review"
}
}
}

What Happens:

  1. Command finds CallbackRegistry record by correlationKey
  2. Deserializes parent process state from database
  3. Stores results in process variables (e.g., approvalResult)
  4. Resumes process from ReceiveTask
  5. Process continues to next task

2. Payment Gateway Callbackโ€‹

Scenario: Paystack sends payment confirmation webhook

{
"cmd": "ReturnCallbackCommand",
"data": {
"correlationKey": "TXN-987654",
"results": {
"status": "success",
"transactionId": "TXN-987654",
"reference": "PSK-ABC123",
"amount": 50000,
"currency": "NGN",
"paidAt": "2026-01-10T15:00:00Z",
"gateway": "paystack",
"metadata": {
"accountNumber": "0123456789",
"customerName": "John Doe"
}
}
}
}

3. Credit Check Subprocess Callbackโ€‹

Scenario: Child subprocess completes credit check

{
"cmd": "ReturnCallbackCommand",
"data": {
"childInstanceId": "credit-check-subprocess-456",
"results": {
"creditScore": 750,
"riskLevel": "Low",
"creditHistory": "Good",
"recommendations": ["Approve up to รขโ€šยฆ100,000", "Standard interest rate"],
"checkedBy": "CreditBureau-API",
"checkedAt": "2026-01-10T16:00:00Z"
}
}
}

4. Failed Callbackโ€‹

Scenario: External system failed to process request

{
"cmd": "ReturnCallbackCommand",
"data": {
"correlationKey": "TXN-123456",
"isFailed": true,
"errorMessage": "Payment gateway timeout after 30 seconds",
"results": {
"status": "failed",
"errorCode": "GATEWAY_TIMEOUT",
"attemptedAt": "2026-01-10T17:00:00Z"
}
}
}

How It Worksโ€‹

Step-by-Step Flowโ€‹

Internal Processingโ€‹

  1. Find Callback Registration:

    Code Removed

Implementation details removed for security.

Contact support for implementation guidance. :::

  1. Check Expiry (if timeout configured):

    Code Removed

Implementation details removed for security.

Contact support for implementation guidance. :::

  1. Deserialize Parent State:

    Code Removed

Implementation details removed for security.

Contact support for implementation guidance. :::

  1. Store Results in Variables:

    Code Removed

Implementation details removed for security.

Contact support for implementation guidance. :::

  1. Resume Process:

    Code Removed

Implementation details removed for security.

Contact support for implementation guidance. :::

  1. Mark Callback Complete:

    Code Removed

Implementation details removed for security.

Contact support for implementation guidance. :::

CallbackRegistry Database Structureโ€‹

The command queries the CallbackRegistry table to find the paused process:

CREATE TABLE CallbackRegistry (
Id BIGINT PRIMARY KEY IDENTITY,

-- Callback identification
CallbackType INT NOT NULL, -- 1=Subprocess, 2=External
ChildInstanceId NVARCHAR(100), -- For subprocess callbacks
CorrelationKey NVARCHAR(200), -- For external callbacks

-- Parent process info
ParentInstanceId NVARCHAR(100) NOT NULL,
CallbackTaskId NVARCHAR(100) NOT NULL,
ParentProcessState NVARCHAR(MAX) NOT NULL, -- Serialized process state

-- Message configuration
MessageRef NVARCHAR(100),
ResultVariable NVARCHAR(100), -- Where to store results

-- Timeout
TimeoutMinutes INT,
RegisteredAt DATETIME2 NOT NULL,

-- Status
Status INT NOT NULL, -- 1=Pending, 2=Completed, 3=Expired
CompletedAt DATETIME2,
CallbackResults NVARCHAR(MAX), -- Stored results
ErrorMessage NVARCHAR(500),

-- Webhook info
WebhookUrl NVARCHAR(500),

INDEX IX_CorrelationKey (CorrelationKey, Status),
INDEX IX_ChildInstanceId (ChildInstanceId, Status)
);

Response Structureโ€‹

Success Responseโ€‹

{
"isSuccessful": true,
"message": "Callback processed successfully. Process resumed.",
"data": {
"parentInstanceId": "loan-approval-123",
"callbackId": 456,
"resumedAt": "2026-01-10T14:30:00Z"
}
}

Error Responsesโ€‹

Callback Not Foundโ€‹

{
"isSuccessful": false,
"message": "No pending callback registration found",
"errorCode": "CALLBACK_NOT_FOUND"
}

Callback Expiredโ€‹

{
"isSuccessful": false,
"message": "Callback has expired",
"errorCode": "CALLBACK_EXPIRED",
"data": {
"expiredAt": "2026-01-08T14:30:00Z",
"timeoutMinutes": 2880
}
}

Deserialization Failedโ€‹

{
"isSuccessful": false,
"message": "Failed to deserialize parent process state",
"errorCode": "DESERIALIZATION_ERROR"
}

Integration Examplesโ€‹

1. Webhook Controller (Email Approval)โ€‹

Code Removed

Implementation details removed for security.

Contact support for implementation guidance.

2. Payment Gateway Webhookโ€‹

Code Removed

Implementation details removed for security.

Contact support for implementation guidance.

3. Subprocess Completion (Automatic)โ€‹

When a subprocess completes, the BPMN engine automatically calls ReturnCallbackCommand:

Code Removed

Implementation details removed for security.

Contact support for implementation guidance.

Best Practicesโ€‹

1. Always Set Correlation Keysโ€‹

<!-- รขยล’ BAD: Auto-generated correlation key -->
<bpmn:receiveTask id="Wait" name="Wait for Payment"/>

<!-- รขล“โ€ฆ GOOD: Explicit correlation key -->
<bpmn:receiveTask id="WaitForPayment" name="Wait for Payment">
<bpmn:extensionElements>
<custom:correlationKey>${transactionId}</custom:correlationKey>
</bpmn:extensionElements>
</bpmn:receiveTask>

2. Set Timeoutsโ€‹

<bpmn:receiveTask id="WaitForApproval">
<bpmn:extensionElements>
<custom:correlationKey>${approvalId}</custom:correlationKey>
<custom:timeoutMinutes>2880</custom:timeoutMinutes> <!-- 48 hours -->
</bpmn:extensionElements>
</bpmn:receiveTask>

3. Store Results in Named Variablesโ€‹

<bpmn:receiveTask id="WaitForPayment">
<bpmn:extensionElements>
<custom:resultVariable>paymentResult</custom:resultVariable>
</bpmn:extensionElements>
</bpmn:receiveTask>

<!-- Later, access in gateway -->
<bpmn:sequenceFlow condition="${paymentResult.status == 'success'}"/>

4. Validate Webhooksโ€‹

Code Removed

Implementation details removed for security.

Contact support for implementation guidance.

5. Handle Failed Callbacksโ€‹

Code Removed

Implementation details removed for security.

Contact support for implementation guidance.

Then in BPMN, handle the error:

<bpmn:receiveTask id="WaitForPayment" name="Wait for Payment">
<bpmn:outgoing>ToCheckPayment</bpmn:outgoing>
</bpmn:receiveTask>

<bpmn:exclusiveGateway id="CheckPayment" name="Payment Success?">
<bpmn:incoming>ToCheckPayment</bpmn:incoming>
<bpmn:outgoing sequenceFlow="${paymentResult.status == 'success'}">ToSuccess</bpmn:outgoing>
<bpmn:outgoing sequenceFlow="${paymentResult.status == 'failed'}">ToRetry</bpmn:outgoing>
</bpmn:exclusiveGateway>

Summaryโ€‹

ReturnCallbackCommand is the key command for resuming processes that are waiting at:

  • รขล“โ€ฆ ReceiveTask - External webhooks, payment gateways, third-party APIs
  • รขล“โ€ฆ CallActivity - Subprocess completions

Key Features:

  • Correlation key matching (for external callbacks)
  • Child instance ID matching (for subprocesses)
  • Automatic timeout handling
  • Result variable storage
  • Automatic process resumption

Common Use Cases:

  • Email approval links
  • Payment gateway webhooks
  • Third-party API callbacks
  • Subprocess completions
  • Mobile app confirmations

Next Steps: