Portal Community

Port Routing Logic

The resume API receives an action field that determines which port fires:

ActionPort FiredData Available
"submit"submitPort (default: "main")Full form field values
"cancel"cancelPort (default: "cancelled"){ _action: "cancel", _cancelledBy, _cancelledAt }
"timeout"timeoutPort (default: "timeout"){ _action: "timeout", _timedOutAt }

Canvas Layout for Three Paths


  ┌───────────────────┐
  │   expenseReview   │
  │  (UserFormNode)   │
  └──────┬────────────┘
         │              ┌─────────────────┐
         ├─ submitted ──▶ ProcessApproval  │
         │              └─────────────────┘
         │              ┌─────────────────┐
         ├─ cancelled ──▶ NotifyCancelled  │
         │              └─────────────────┘
         │              ┌─────────────────┐
         └─ timeout ────▶ EscalateToAdmin  │
                        └─────────────────┘
  

Custom Action Names

If the form has a custom submit button (e.g., "Request More Info" alongside "Approve"), you can define multiple submit actions:

{
  "submitActions": [
    { "action": "approve", "label": "Approve", "port": "approved" },
    { "action": "reject", "label": "Reject", "port": "rejected" },
    { "action": "requestInfo", "label": "Request More Info", "port": "infoRequested" }
  ]
}

Each action sends a different action value in the resume payload, routing to the corresponding port.

Always handle cancel: Connect the cancelPort to a meaningful handler. If the user cancels and there is no connected edge, the workflow branch silently terminates with no cleanup, no notification, and no audit entry. This is almost always undesirable.