Build a Workflow from Scratch (Builder API)

While creating a Workflow from a Blueprint is ideal for repeatable processes, SignStack also provides a powerful "Builder API" giving you complete control to define and launch unique, one-off workflows entirely through code.

This approach is perfect when your application needs to dynamically generate the workflow structure itself, perhaps based on user input or complex internal logic. Think of it like building a custom house brick-by-brick instead of using a pre-designed floor plan.

💡 Using the UI: You can also build custom workflows visually using the SignStack dashboard.

The Workflow Object: Key Components

Creating a workflow programmatically involves defining a JSON object that describes the entire process. Before diving into the API calls, let's understand the key sections of this object:

  1. displayName (Optional string): A human-readable name for this specific workflow instance (e.g., "Custom Enterprise Deal - Q4").

  2. documents (Required array): Defines the specific documents involved. Each entry specifies:

    • key: A unique key for this document instance within the workflow (e.g., mainAgreement).

    • fileId (Optional): The ID of the base PDF file. Optional iftemplateKey is specified.

    • templateKey (Optional): The key of a Template to inherit field definitions and metadata from. If both fileId and a templateKey are provided, the fileId here overrides the template's default file.

    • entityMapping: An object mapping the template's required entitySlot keys to the entity keys defined in this workflow request (e.g., { "customer": "clientInfo", "deal": "dealInfo" }).

  3. participants (Required array): Defines the actual people (name, email) involved in this specific workflow instance, each identified by a unique key for referencing within this request (e.g., primarySigner).

  4. entities (Required array): Provides the initial data state for the workflow. Each entry specifies the key for this instance (e.g., clientInfo), the schemaKey defining its structure, and the actual data object.

  5. steps (Required array) & rootStepKey (Required string): This defines the core process logic using SignStack's recursive Step model. You'll define Container steps (with executionMode, completionRule, children) and Task steps (like participantTask which links a participantKey to specific roleLinks on documents). The rootStepId points to the entry point of this step tree.

  6. status (Optional string): Determines the initial state. Set to Draft if building incrementally, or InProgress if creating and sending in one go. Defaults to Draft.

While you can send the entire object in one POST request (see "Alternative" below), building it incrementally using PATCH is often easier during development as it allows for validation at each stage.

Start by creating an empty container.

  • Endpoint: POST /v1/organizations/{organizationId}/workflows

  • Request Body:

    { "displayName": "Custom Deal - Project Phoenix" }
  • Response: 201 Created with the new Workflow object (status: "Draft"). Store the returned id.

Use PATCH requests to add the core components to the draft. Send only the sections you want to add or update.

  • Endpoint: PATCH /v1/organizations/{organizationId}/workflows/{workflowId}

  • Request Body (Example):

    {
      "documents": [
        {
          "key": "mainAgreement",
          "fileId": "file_abc...",
          "templateKey": "standardContractV3",
          "entityMapping": { "customer": "clientInfo", "deal": "dealInfo" }
        }
      ],
      "participants": [
        { "key": "signerA", "firstName": "Jane", "lastName": "Doe", "email": "..." }
      ],
      "entities": [
        { "key": "clientInfo", "schemaKey": "customerSchemaV1", "data": { ... } }
      ]
    }
  • Response: 200 OK with the updated Workflow object (still in Draft).

Add the process logic by sending the steps array and rootStepId.

  • Endpoint: PATCH /v1/organizations/{organizationId}/workflows/{workflowId}

  • Request Body:

    {
      "rootStepKey": "root",
      "steps": [
        {
          "key": "root",
          "type": "CONTAINER",
          "executionMode": "SEQUENTIAL",
          "completionRule": "ALL",
          "children": ["buyerSignStep"]
        },
        {
          "key": "buyerSignStep",
          "type": "PARTICIPANT_TASK",
          "participantTask": {
            "participantKey": "signerA",
            "roleLinks": [
              { "documentKey": "mainAgreement", "templateRoleKey": "primaryBuyer" }
            ]
          }
        }
      ]
    }
  • Response: 200 OK with the fully defined Workflow object (still Draft).

Once fully defined and valid, trigger execution.

  • Endpoint: POST /v1/organizations/{organizationId}/workflows/{workflowId}/send

  • Request Body: (Can be empty)

  • Backend Logic: Validates, sets status to InProgress, generates signing tokens, starts the root step, and enqueues notifications.

  • Response: 200 OK with the updated Workflow object (status: "InProgress").

The POST /v1/organizations/{orgId}/workflows endpoint also supports creating and sending a workflow in a single call. To do this, provide the complete Workflow object (including documents, participants, entities, steps, rootStepId) and set the initial status to InProgress in the request body.

This single-cal method is often more efficient for production integrations but can be harder to debug if the initial payload is invalid.

The Builder API provides ultimate flexibility, allowing you to programmatically construct any workflow imaginable directly from your application code.

➡️ Next: Guides: Monitor Workflow Status