Introduction to the Processes API#

The Processes API enables you to programmatically create, configure, validate, and run workflow processes in Workiva. Use it to automate recurring workflows like financial close checklists, data collection assignments, and certification campaigns — distributing tasks to assignees, tracking completion status, and managing the entire lifecycle without manual intervention.

Before getting started, make sure you have credentials set up.

This guide covers the following scenarios:

Prerequisites & Authentication#

All requests to the Processes API require:

  • A valid OAuth 2.0 Bearer token

  • The X-Version: 2026-04-01.processes.preview header on every request

  • The appropriate OAuth scopes for each operation (noted per endpoint below)

  • Acceptance of the Preview Features Agreement (contact your CSM or Partner Success Manager)

Shell variables#
export TOKEN="your_access_token_here"
export PROCESS_ID="your-process-id"
export PROCESS_RUN_ID="your-process-run-id"

Important

This API is in preview status. Always include X-Version: 2026-04-01.processes.preview on all requests. The API may change before general availability. Do not rely on it for business-critical production workflows until GA.

Note

The Processes API uses a different version header than the main Workiva Platform API (2026-01-01). The preview version is 2026-04-01.processes.preview.


Key Concepts#

Concept

Description

Process

A build-time definition of a workflow. Contains a tree structure of Jobs organized into Groups that define execution order. Think of it as the blueprint.

ProcessRun

A runtime instance created when you start a Process. There is a 1:N relationship — one Process can be run many times. Each run tracks its own status independently.

Job

A single unit of work within a Process. Each Job has an action type (e.g., sendTask, contentRequest, certification) and arguments that define what work to perform.

JobRun

A runtime instance of a Job created when its parent Process is started. Tracks execution status (waiting, running, complete, cancelled, error).

Group

A container that organizes Jobs (and nested Groups) into either parallel or serial execution order. Every Process has a root Group.

GroupRun

A runtime instance of a Group. Tracks aggregated status of its child JobRuns.

Action

The type of work a Job performs. Determines the argument schema. Available actions: sendTask, contentRequest, and certification.

Trigger Type

Controls when a Job/Group starts: whenEligible (auto-start when predecessors complete) or manual (requires explicit start).

Build-Time vs. Run-Time#

The API cleanly separates design from execution:

Phase

Resources

What You Do

Build-time

Process, ProcessJob, ProcessGroup

Create and configure the workflow structure

Run-time

ProcessRun, JobRun, ProcessGroupRun

Start, monitor, and modify running workflows

Action Types#

Action

Purpose

Key Arguments

sendTask

Send a task assignment to a user with optional approval

assignee, title, dueDate, approver, document

contentRequest

Request content from a user for a specific document/section

assignee, document, section, title, approver

certification

Run a certification workflow with signers and approvers

sourceLetter, steps, title


Creating a Process#

Use the create a process endpoint to create a new Process with its full job hierarchy in a single request. The request body defines the process configuration and its root group containing jobs.

Required scope: file:write

POST /processes

Request body#
{
  "name": "Q4 2024 Financial Close",
  "autoClose": true,
  "certAutoApprove": false,
  "relativeDates": true,
  "businessStartDate": "2024-10-01",
  "businessEndDate": "2024-12-31",
  "dueDate": "2024-12-31",
  "businessDaysOfWeek": [
    "monday",
    "tuesday",
    "wednesday",
    "thursday",
    "friday"
  ],
  "businessDateExclusions": [
    "2024-11-28",
    "2024-12-25"
  ],
  "root": {
    "name": "Close Workflow",
    "parallel": false,
    "readOnly": false,
    "triggerType": "whenEligible",
    "children": [
      {
        "type": "job",
        "job": {
          "arguments": {
            "type": "sendTask",
            "sendTaskArgs": {
              "title": "Reconcile accounts receivable",
              "assignee": { "id": "user-analyst-001", "type": "user" },
              "approver": { "id": "user-manager-001", "type": "user" },
              "dueDate": "2024-12-15",
              "approverDueDate": "2024-12-20",
              "instructions": "Complete the AR reconciliation for all accounts over $10,000."
            }
          },
          "triggerType": "whenEligible"
        }
      },
      {
        "type": "job",
        "job": {
          "arguments": {
            "type": "contentRequest",
            "contentRequestArgs": {
              "title": "Provide Q4 revenue commentary",
              "assignee": { "id": "user-analyst-002", "type": "user" },
              "approver": { "id": "user-manager-001", "type": "user" },
              "document": "doc-revenue-report-id",
              "section": "section-commentary-id",
              "dueDate": "2024-12-18",
              "instructions": "Add variance explanations for all line items exceeding 5% threshold."
            }
          },
          "triggerType": "whenEligible"
        }
      }
    ]
  }
}
Request#
curl -X POST "https://api.app.wdesk.com/processes" \
    -H "Authorization: Bearer ${TOKEN}" \
    -H "Content-Type: application/json" \
    -H "X-Version: 2026-04-01.processes.preview" \
    -d @request.json
Response#
{
  "id": "e7b9920095e342889190b4d7eaeca6fa",
  "name": "Q4 2024 Financial Close",
  "autoClose": true,
  "certAutoApprove": false,
  "relativeDates": true,
  "businessStartDate": "2024-10-01",
  "businessDaysOfWeek": ["monday", "tuesday", "wednesday", "thursday", "friday"],
  "dueDate": "2024-12-31",
  "revision": 1,
  "created": {
    "dateTime": "2024-10-01T14:30:00Z",
    "user": { "id": "V1ZVd2VyFzU3NiQ1NDA4NjIzNzk2MjD" }
  },
  "modified": {
    "dateTime": "2024-10-01T14:30:00Z",
    "user": { "id": "V1ZVd2VyFzU3NiQ1NDA4NjIzNzk2MjD" }
  },
  "root": {
    "id": "root-group-abc123",
    "name": "Close Workflow",
    "parallel": false,
    "readOnly": false,
    "triggerType": "whenEligible",
    "children": [
      {
        "type": "job",
        "job": {
          "id": "job-001",
          "arguments": { "type": "sendTask" }
        }
      },
      {
        "type": "job",
        "job": {
          "id": "job-002",
          "arguments": { "type": "contentRequest" }
        }
      }
    ]
  }
}

Save the id field — you’ll need it to validate, update, or run the process.

Tip

Set parallel: false on the root group when jobs must execute in sequence (e.g., reconciliation before commentary). Set parallel: true when jobs can run concurrently.

Note

Jobs can be built incrementally. You can create a process with minimal job arguments and fill in details later via the Patch or Batch Update endpoints before running it.

Note

The assignee and approver fields in sendTaskArgs and contentRequestArgs accept a Participant object with id and type properties (e.g., { "id": "userId", "type": "user" }). This matches the SendTaskArguments and ContentRequestArguments schemas. Some API reference examples may show a flat-string shorthand (assigneeUser, approverUser) — always use the object form shown in this guide.


Retrieving a Process#

Use the get a process endpoint to retrieve a process definition by its ID to inspect its current configuration and job hierarchy.

Required scope: file:read

GET /processes/{processId}

Request#
curl -X GET "https://api.app.wdesk.com/processes/${PROCESS_ID}" \
    -H "Authorization: Bearer ${TOKEN}" \
    -H "Accept: application/json" \
    -H "X-Version: 2026-04-01.processes.preview"
Response#
{
  "id": "e7b9920095e342889190b4d7eaeca6fa",
  "name": "Q4 2024 Financial Close",
  "autoClose": true,
  "certAutoApprove": false,
  "relativeDates": true,
  "dueDate": "2024-12-31",
  "revision": 3,
  "root": {
    "id": "root-group-abc123",
    "name": "Close Workflow",
    "parallel": false,
    "readOnly": false,
    "triggerType": "whenEligible",
    "children": [
      {
        "type": "job",
        "job": {
          "id": "job-001",
          "arguments": {
            "type": "sendTask",
            "sendTaskArgs": {
              "title": "Reconcile accounts receivable",
              "assignee": { "id": "user-analyst-001", "type": "user" },
              "dueDate": "2024-12-15"
            }
          }
        }
      }
    ]
  }
}

Excluding Generated Jobs#

For certification processes, the system generates child jobs (signer actions, approver actions) automatically. To retrieve only the jobs you explicitly defined, use the excludeGeneratedJobs parameter:

GET /processes/{processId}?excludeGeneratedJobs=true

Request#
curl -X GET "https://api.app.wdesk.com/processes/${PROCESS_ID}?excludeGeneratedJobs=true" \
    -H "Authorization: Bearer ${TOKEN}" \
    -H "Accept: application/json" \
    -H "X-Version: 2026-04-01.processes.preview"

Tip

Use excludeGeneratedJobs=true when you only need to inspect the structure you defined. Omit it when you need the full runtime picture including system-generated certification steps.


Updating a Process#

There are two ways to update a process before running it: JSON Patch for configuration changes, and Batch Update for renaming jobs and groups.

Patching Process Configuration#

Use the update a process endpoint with JSON Patch (RFC 6902) to update process-level properties like name, due date, business calendar, and execution settings.

Required scope: file:write

PATCH /processes/{processId}

Request body#
[
  {
    "op": "replace",
    "path": "/name",
    "value": "Q4 2024 Financial Close — Updated"
  },
  {
    "op": "replace",
    "path": "/dueDate",
    "value": "2025-01-15"
  },
  {
    "op": "replace",
    "path": "/autoClose",
    "value": false
  },
  {
    "op": "remove",
    "path": "/businessDateExclusions"
  }
]
Request#
curl -X PATCH "https://api.app.wdesk.com/processes/${PROCESS_ID}" \
    -H "Authorization: Bearer ${TOKEN}" \
    -H "Content-Type: application/json-patch+json" \
    -H "X-Version: 2026-04-01.processes.preview" \
    -d @request.json

Response (200 OK): Returns the updated Process object.

Patchable paths:

Path

Operations

Description

/name

replace

Process name

/dueDate

replace, remove

Process due date

/businessStartDate

replace, remove

Anchor date for relative dates

/businessEndDate

replace, remove

End date for the process

/businessDaysOfWeek

replace, remove

Working days array

/businessDateExclusions

replace, remove

Holiday dates to exclude

/businessDateInclusions

replace, remove

Override dates to include

/autoClose

replace

Auto-close on completion

/relativeDates

replace

Enable relative date shifting

/root/parallel

replace

Root group execution mode

/root/triggerType

replace

Root group trigger type

/certAutoApprove

replace

Auto-approve certifications

/calendarIds

replace, remove

Calendar IDs associated with the process

/ipmBetaEnabled

replace

IPM beta feature flag

/iwmOptOut

replace

IWM opt-out flag

/defaultCertSignerReminders

replace, remove

Default signer reminders

/defaultCertApproverReminders

replace, remove

Default approver reminders

Batch Renaming Jobs and Groups#

Use the bulk update group and job names endpoint to rename multiple jobs and groups in a single request.

Required scope: file:write

POST /processes/{processId}/batchUpdates

Request body#
{
  "data": [
    {
      "type": "jobName",
      "id": "job-001",
      "newName": "Reconcile AR — All Entities"
    },
    {
      "type": "groupName",
      "id": "root-group-abc123",
      "newName": "Q4 Close Workflow — Final"
    }
  ]
}
Request#
curl -X POST "https://api.app.wdesk.com/processes/${PROCESS_ID}/batchUpdates" \
    -H "Authorization: Bearer ${TOKEN}" \
    -H "Content-Type: application/json" \
    -H "X-Version: 2026-04-01.processes.preview" \
    -d @request.json

Response (200 OK): Returns the updated Process object.

Note

The batch update endpoint only supports renaming. To update job arguments, due dates, or other structural changes, use the process-level Patch endpoint or recreate the process.


Validating a Process#

Use the validate a process endpoint before running a process to catch configuration errors like missing assignees, invalid dates, or incomplete job arguments. Validation is a read-only operation that does not modify the process.

Required scope: file:read

POST /processes/{processId}/validation

Request#
curl -X POST "https://api.app.wdesk.com/processes/${PROCESS_ID}/validation" \
    -H "Authorization: Bearer ${TOKEN}" \
    -H "Accept: application/json" \
    -H "X-Version: 2026-04-01.processes.preview"
Response — Process is valid#
{
  "errors": []
}
Response — Process has errors#
{
  "errors": [
    {
      "code": "MISSING_REQUIRED_FIELD",
      "message": "Job is missing required field: assigneeUser",
      "target": "/root/children/0/job"
    },
    {
      "code": "INVALID_DUE_DATE",
      "message": "Due date must be in the future",
      "target": "/dueDate"
    }
  ]
}

Important

Always validate before running. A process with validation errors will fail to start, returning a 400 Bad Request. Validating first gives you clear, actionable error messages.

Tip

Integrate validation into your automation pipeline as a pre-flight check. If errors is an empty array, the process is ready to run.


Running a Process#

Use the run a process endpoint to start execution of a validated process. This creates a ProcessRun — a runtime instance that tracks status and sends tasks to assignees.

Required scope: file:write

POST /processes/{processId}/run

Request body (optional)#
{
  "sendProcessCompleteEmail": true
}
Request#
curl -X POST "https://api.app.wdesk.com/processes/${PROCESS_ID}/run" \
    -H "Authorization: Bearer ${TOKEN}" \
    -H "Content-Type: application/json" \
    -H "X-Version: 2026-04-01.processes.preview" \
    -d @request.json
Response#
{
  "id": "processrun-xyz789",
  "name": "Q4 2024 Financial Close",
  "process": "e7b9920095e342889190b4d7eaeca6fa",
  "status": "running",
  "autoClose": true,
  "certAutoApprove": false,
  "relativeDates": true,
  "dueDate": "2024-12-31",
  "revision": 0,
  "created": {
    "dateTime": "2024-10-01T15:00:00Z",
    "user": { "id": "V1ZVd2VyFzU3NiQ1NDA4NjIzNzk2MjD" }
  },
  "statusCounts": {
    "waiting": 2
  },
  "modified": {
    "dateTime": "2024-10-01T15:00:00Z",
    "user": { "id": "V1ZVd2VyFzU3NiQ1NDA4NjIzNzk2MjD" }
  },
  "root": {
    "id": "grouprun-root123",
    "name": "Close Workflow",
    "parallel": false,
    "readOnly": false,
    "status": "waiting",
    "children": [
      {
        "type": "job",
        "job": {
          "id": "jobrun-001",
          "status": "waiting",
          "actionStatus": "waiting",
          "ordinal": 0,
          "readOnly": false,
          "revision": 0,
          "metadata": {
            "type": "sendTask"
          },
          "arguments": {
            "type": "sendTask",
            "sendTaskArgs": {
              "title": "Reconcile accounts receivable",
              "assignee": { "id": "user-analyst-001", "type": "user" },
              "dueDate": "2024-12-15"
            }
          }
        }
      }
    ]
  }
}

Save the ProcessRun id — you’ll need it to monitor status and add jobs.

Note

The POST .../run response wraps each child in a job key (the build-time resource name). When you later retrieve the run via GET /processRuns/{id}, the same children use the jobRun key instead, reflecting the runtime resource name. Your code should handle both keys depending on which endpoint it calls.

Note

Setting sendProcessCompleteEmail to true (the default) sends an email notification to the user who started the process when all actions are completed or cancelled. Set to false to suppress this notification.

Tip

You can run the same Process multiple times. Each run creates an independent ProcessRun with its own status tracking.


Monitoring a Process Run#

Use the get a ProcessRun endpoint to retrieve the current state of a running (or completed) process to check overall status and individual job progress.

Required scope: file:read

GET /processRuns/{processRunId}

Request#
curl -X GET "https://api.app.wdesk.com/processRuns/${PROCESS_RUN_ID}" \
    -H "Authorization: Bearer ${TOKEN}" \
    -H "Accept: application/json" \
    -H "X-Version: 2026-04-01.processes.preview"
Response#
{
  "id": "processrun-xyz789",
  "name": "Q4 2024 Financial Close",
  "process": "e7b9920095e342889190b4d7eaeca6fa",
  "status": "running",
  "statusCounts": {
    "Completed": 1,
    "Running": 1,
    "Waiting": 1
  },
  "root": {
    "id": "grouprun-root123",
    "name": "Close Workflow",
    "parallel": false,
    "readOnly": false,
    "status": "running",
    "children": [
      {
        "type": "job",
        "jobRun": {
          "id": "jobrun-001",
          "action": "sendTask",
          "status": "complete",
          "actionStatus": "Completed",
          "ordinal": 0,
          "readOnly": false,
          "job": "job-001",
          "arguments": {
            "type": "sendTask",
            "sendTaskArgs": {
              "title": "Reconcile accounts receivable",
              "assignee": { "id": "user-analyst-001", "type": "user" },
              "dueDate": "2024-12-15"
            }
          },
          "metadata": {
            "type": "sendTask",
            "sendTaskMetadata": {
              "status": "Completed",
              "task": "task-abc123",
              "permalink": "https://app.wdesk.com/a/workspace123/tasks/task-abc123",
              "taskCancelled": false,
              "cancelCleanupComplete": false,
              "taskCancelledNotificationSent": false
            }
          }
        }
      },
      {
        "type": "job",
        "jobRun": {
          "id": "jobrun-002",
          "action": "contentRequest",
          "status": "waiting",
          "actionStatus": "Waiting",
          "ordinal": 1,
          "readOnly": false,
          "job": "job-002",
          "arguments": {
            "type": "contentRequest",
            "contentRequestArgs": {
              "title": "Provide Q4 revenue commentary",
              "assignee": { "id": "user-analyst-002", "type": "user" },
              "document": "doc-revenue-report-id"
            }
          },
          "metadata": {
            "type": "contentRequest",
            "contentRequestMetadata": {
              "status": "Created",
              "task": "task-def456",
              "permalink": "https://app.wdesk.com/a/workspace123/tasks/task-def456",
              "taskCancelled": false,
              "cancelCleanupComplete": false,
              "taskCancelledNotificationSent": false
            }
          }
        }
      },
      {
        "type": "job",
        "jobRun": {
          "id": "jobrun-003",
          "action": "sendTask",
          "status": "running",
          "actionStatus": "Running",
          "ordinal": 2,
          "readOnly": false,
          "job": "job-003"
        }
      }
    ]
  }
}

Understanding Status Fields#

Each ProcessRun and JobRun has two status-related fields:

  • status — the general execution status of the JobRun (lowercase values):

Status

Meaning

waiting

Not yet started; waiting for predecessors to complete

running

Currently active; tasks have been sent to assignees

complete

All work finished successfully

cancelled

Explicitly cancelled

cancelling

Cancel in progress

error

Failed due to an error

errorHold

Paused due to an error; may be retried

  • actionStatus — an action-specific status (capitalized values, e.g., "Waiting", "Running", "Completed").

The statusCounts object provides a quick summary of how many JobRuns are in each action status. Note that these keys use capitalized values (e.g., "Completed": 1, "Running": 1, "Waiting": 1), matching actionStatus casing — not the lowercase status field.

Tip

Poll the ProcessRun endpoint periodically to track progress. Use statusCounts for a high-level overview, or traverse root.children for per-job detail. When writing code that checks statuses, be aware that status is lowercase while actionStatus and statusCounts keys are capitalized.

Note

The metadata field on each JobRun contains action-specific runtime information. For sendTask actions, it includes the created task ID, a permalink URL that links directly to the task in the Workiva UI, and boolean tracking fields like taskCancelled and cancelCleanupComplete. For contentRequest actions, a similar contentRequestMetadata object is returned.


Adding Jobs to a Running Process#

Use the create job runs endpoint to add new jobs to a process that is already running. This is useful when additional work emerges mid-workflow that wasn’t part of the original process definition.

Required scope: file:write

POST /processRuns/{processRunId}/jobRuns

You can control placement of new jobs using query parameters:

Parameter

Description

parentGroupId

Place the new jobs in this group (defaults to root group)

relativeSiblingId

Insert relative to this existing job or group

before

String. If "true" (default), insert before the sibling; if "false", insert after

Request body#
[
  {
    "action": "sendTask",
    "arguments": {
      "type": "sendTask",
      "sendTaskArgs": {
        "title": "Review intercompany eliminations",
        "assignee": { "id": "user-analyst-003", "type": "user" },
        "approver": { "id": "user-manager-001", "type": "user" },
        "dueDate": "2024-12-22",
        "instructions": "Verify all intercompany balances net to zero."
      }
    },
    "triggerType": "whenEligible"
  }
]
Request#
curl -X POST "https://api.app.wdesk.com/processRuns/${PROCESS_RUN_ID}/jobRuns?parentGroupId=grouprun-root123" \
    -H "Authorization: Bearer ${TOKEN}" \
    -H "Content-Type: application/json" \
    -H "X-Version: 2026-04-01.processes.preview" \
    -d @request.json
Response#
[
  {
    "id": "jobrun-new-001",
    "action": "sendTask",
    "status": "waiting",
    "ordinal": 2,
    "parent": "grouprun-root123",
    "triggerType": "whenEligible",
    "arguments": {
      "type": "sendTask",
      "sendTaskArgs": {
        "title": "Review intercompany eliminations",
        "assignee": { "id": "user-analyst-003", "type": "user" },
        "approver": { "id": "user-manager-001", "type": "user" },
        "dueDate": "2024-12-22"
      }
    }
  }
]

Important

New jobs added to a running process will start executing according to their triggerType. If set to whenEligible and the process is already past the insertion point in serial execution, the job may start immediately.

Tip

You can add multiple jobs in a single request by including multiple objects in the array. They will be inserted in order at the specified position.


Trashing and Restoring a Process#

Trashing a Process#

Use the delete a process endpoint to soft-delete a process by moving it to trash. This does not permanently destroy the process.

Required scope: file:write

DELETE /processes/{processId}

Request#
curl -X DELETE "https://api.app.wdesk.com/processes/${PROCESS_ID}" \
    -H "Authorization: Bearer ${TOKEN}" \
    -H "Accept: application/json" \
    -H "X-Version: 2026-04-01.processes.preview"

Response (204 No Content)

Restoring a Process#

Use the restore a process endpoint to restore a previously trashed process.

Required scope: file:write

POST /processes/{processId}/restore

Request#
curl -X POST "https://api.app.wdesk.com/processes/${PROCESS_ID}/restore" \
    -H "Authorization: Bearer ${TOKEN}" \
    -H "X-Version: 2026-04-01.processes.preview"

Response (200 OK): Returns the restored Process object.

Note

Only trashed processes can be restored. Attempting to restore an active process will return a 409 Conflict.


Common Issues#

Issue

Solution

400 when running a process

Run validation first (POST /processes/{id}/validation). Fix all reported errors before attempting to run.

Jobs not starting in expected order

Check the parallel setting on the parent group. Serial groups (parallel: false) execute children top-to-bottom. Parallel groups start all children simultaneously.

409 Conflict on run

The process may already have an active run or be in a state that doesn’t support starting. Check existing ProcessRuns.

Missing X-Version header

Every request requires X-Version: 2026-04-01.processes.preview. Omitting it or using the wrong version will result in errors.

403 Forbidden

Ensure your OAuth 2.0 token has the file:write scope (for mutations) or file:read scope (for reads). Also verify you have appropriate permissions on the process.

Jobs created with incomplete arguments

Jobs can be created incrementally with partial arguments. Validation will catch missing required fields before you attempt to run.

Certification jobs generate unexpected children

Certification actions automatically generate signer and approver JobRuns. Use excludeGeneratedJobs=true on GET to see only your explicit jobs.

Relative dates not shifting

Ensure relativeDates is true and businessStartDate is set. Dates shift relative to the business start date using the configured business days calendar.

Rate limiting (429)

The API enforces rate limits. If you receive a 429, respect the Retry-After header before making additional requests.


Summary of API Endpoints#

Operation

Method

Endpoint

Required Scope

Create a Process

POST

/processes

file:write

Get a Process

GET

/processes/{processId}

file:read

Patch a Process

PATCH

/processes/{processId}

file:write

Batch Update a Process

POST

/processes/{processId}/batchUpdates

file:write

Validate a Process

POST

/processes/{processId}/validation

file:read

Run a Process

POST

/processes/{processId}/run

file:write

Get a Process Run

GET

/processRuns/{processRunId}

file:read

Create Job Runs

POST

/processRuns/{processRunId}/jobRuns

file:write

Trash a Process

DELETE

/processes/{processId}

file:write

Restore a Process

POST

/processes/{processId}/restore

file:write