Use Parallel Steps for Approvals

Often, a business process requires approvals from multiple people or departments simultaneously. SignStack's Blueprint model handles this easily using PARALLEL container steps. This guide shows how to design a workflow where, for example, both a Manager and a Legal Reviewer must approve a document before it proceeds.

1. The Scenario: Dual Approval

Imagine a contract needs approval from both the responsible Manager and the Legal department. They can perform their reviews at the same time, but the workflow should only continue once both have signed off.

2. Define the Blueprint Manifest

First, set up the Blueprint requirements. We'll need roles for the Initiator, Manager, and Legal Reviewer, and the document they are reviewing.

{
  "key": "parallelApprovalDemo",
  "displayName": "Parallel Approval Demo Blueprint",
  "documents": [
    {
      "key": "contractDoc",
      "displayName": "Contract for Approval",
      "templateKey": "standardContractTemplateV1", // Assumes this template exists
      "roleMapping": {
        "submitter": "initiatorRole",
        "managerApprover": "managerRole",
        "legalApprover": "legalRole"
      },
      "entityMapping": {
        "contractData": "contractInfoEntity"
      }
    }
  ],
  "roles": [
    { "key": "initiatorRole", "displayName": "Initiator", "isMandatory": true },
    { "key": "managerRole", "displayName": "Manager", "isMandatory": true },
    { "key": "legalRole", "displayName": "Legal Reviewer", "isMandatory": true }
  ],
  "entitySlots": [
    { "key": "contractInfoEntity", "displayName": "Contract Info", "schemaKey": "contractSchemaV1", "compatibleSchemaVersion": "^1.0.0", "isMandatory": true }
  ],
  "rootEntitySlotKeys": ["contractInfoEntity"],
  "steps": [
     // We'll define the steps next...
  ]
}

3. Define the Steps (Parallel Logic)

We'll use a SEQUENTIAL root step. Inside it, we'll have the initiator's step, followed by a PARALLEL container step for the approvals.

// Add this 'steps' array inside the main Blueprint object

"steps": [
  // --- The Root Container (Sequential) ---
  {
    "key": "root",
    "stepType": "CONTAINER",
    "executionMode": "SEQUENTIAL",
    "completionRule": "ALL",
    "children": ["initiatorSubmitStep", "approvalPhase", "finalStep"] // Steps run in this order
  },

  // --- Step 1: Initiator Submits ---
  {
    "key": "initiatorSubmitStep",
    "stepType": "PARTICIPANT_TASK",
    "name": "Submit Contract",
    "roleKey": "initiatorRole",
    "taskInterface": "DOCUMENT_SIGNING", // Or FORM_FILLING
    "links": [ /* Links for initiator fields */ ]
    // Optional mappers to update entities
  },

  // --- Step 2: Approval Phase (Parallel Container) ---
  {
    "key": "approvalPhase",
    "stepType": "CONTAINER",
    "name": "Manager and Legal Approval",
    "executionMode": "PARALLEL", // Children start simultaneously
    "completionRule": "ALL",     // This container waits for ALL children to complete
    "children": ["managerApprovalStep", "legalApprovalStep"] // Keys of the parallel tasks
  },

  // --- Step 2a: Manager Approval Task (Inside Parallel) ---
  {
    "key": "managerApprovalStep",
    "stepType": "PARTICIPANT_TASK",
    "name": "Manager Approval",
    "roleKey": "managerRole",
    "taskInterface": "DOCUMENT_SIGNING", // Or SIMPLE_APPROVAL
    "links": [ /* Links for manager's signature/approval fields */ ]
    // Optional mappers
  },

  // --- Step 2b: Legal Approval Task (Inside Parallel) ---
  {
    "key": "legalApprovalStep",
    "stepType": "PARTICIPANT_TASK",
    "name": "Legal Review and Approval",
    "roleKey": "legalRole",
    "taskInterface": "DOCUMENT_SIGNING", // Or SIMPLE_APPROVAL
    "links": [ /* Links for legal's signature/approval fields */ ]
    // Optional mappers
  },

  // --- Step 3: Final Step (After Approvals) ---
  {
    "key": "finalStep",
    "stepType": "PARTICIPANT_TASK", // Or TRIGGER_EVENT etc.
    "name": "Process Approved Contract",
    "roleKey": "initiatorRole", // Example: Notify initiator
    // ... configuration for the final step ...
  }
]
  • The approvalPhase container has executionMode: "PARALLEL". This means managerApprovalStep and legalApprovalStep will start at the same time.

  • Its completionRule: "ALL" ensures that the approvalPhase step only completes (allowing the workflow to move to finalStep) after both the manager and legal reviewer have finished their tasks.

  • If you wanted the workflow to proceed as soon as either person approved, you would set completionRule: "ANY".

  • You can also use completionRule: "QUORUM" along with a quorumCount (e.g., quorumCount: 3) if you need a specific number of participants (e.g., 3 out of 5) to complete their tasks before the step finishes.

4. Creating the Blueprint via API

Save this JSON structure and create it using the POST /blueprints API:

curl -X POST \
  [https://api.signstack.com/v1/organizations/me/blueprints](https://api.signstack.com/v1/organizations/me/blueprints) \
  -H "Authorization: Bearer <YOUR_ACCESS_TOKEN>" \
  -H "Content-Type: application/json" \
  --data @parallel_blueprint.json

You have now designed a Blueprint with parallel steps! This pattern is essential for modeling real-world approval processes efficiently.

➡️ Next: Guides: Implement Conditional Logic (inclusionCondition)