**Source URL:** https://limited.veevavault.dev/medical/vault-sdk/services/workflow-services

# Workflow Services

The services in the `workflow` package provide methods that allow custom code to interact with object and document workflows. Document workflows are object workflows on the `envelope__sys` object.

<Aside type="note" title="Note">
Vault Java SDK does not support [legacy workflows](https://platform.veevavault.help/en/lr/5205).
</Aside>

## Key Functionality

With workflow services, you can:

*   , such as , cancelling an in-progress workflow, or executing a [record workflow action](/medical/vault-sdk/entry-points/actions/record-workflow-actions/)
*   , such as assigning or unassigning a workflow task
*   
*   Update entities within workflow processing

### Key Interfaces

*   `WorkflowInstanceService`: Provides methods to retrieve information for and update active workflow instances. For example, setting participants within a [custom record workflow action](/medical/vault-sdk/entry-points/actions/record-workflow-actions/) or [executing active workflow actions](/vault-sdk/services/workflow-services/#Workflow_Action_Services).
*   `WorkflowMetadataService`: Provides methods to interact with workflow metadata.
*   `WorkflowTaskService`: Provides methods to retrieve active workflow task instances and execute workflow task actions, such as cancelling a workflow task.

## Workflow Action Services

The Vault Java SDK supports initiating workflow actions and workflow task actions. These actions run on active workflow instances and are available in all Vaults. If you are unfamiliar with workflow actions, you can learn more in Vault Help:

*   [Vault Help: Using Object Workflows](https://platform.veevavault.help/en/lr/33553)
*   [Vault Help: Using Document Workflows](https://platform.veevavault.help/en/lr/50506)

### Active Workflow Actions

You can find the supported workflow actions in the `WorkflowActions` Enum:

*   `ADD_PARTICIPANTS`: Adds participants to an active workflow.
*   `CANCEL_WORKFLOW`: Cancels an active workflow.
*   `REMOVE_ITEMS`: Removes documents or records from an active workflow.
*   `REPLACE_WORKFLOW_OWNER`: Replaces the workflow owner of an active workflow.
*   `UPDATE_WORKFLOW_DUE_DATE`: Updates the due date of an active workflow.

### Active Workflow Task Actions

You can find the supported workflow actions in the `WorkflowTaskAction` Enum:

*   `ASSIGN`: Assigns an available workflow task. Available workflow tasks are unassigned tasks which are valid for the requesting user to accept. For example, your organization's workflow configuration may only allow QA tasks to be assigned to users who are configured in the QA role.
*   `CANCEL`: Cancels an assigned workflow task.
*   `REASSIGN`: Reassigns a workflow task. The workflow task must be a valid task for the new task assignee to accept, for example, the new assignee cannot be configured in a restricted role. Completed or cancelled tasks cannot be reassigned.
*   `UNASSIGN`: Unassigns a workflow task. Once unassigned, the task becomes available. Tasks cannot be unassigned if they are completed, cancelled, or not configured as available tasks.
*   `UPDATE_DUE_DATE`: Updates the due date of an assigned workflow task. Vault notifies the task owner of the updated due date. If the workflow is configured to set all task due dates to the workflow due date, updates to individual task due dates will not affect the overall workflow due date. Cannot update the task due date if the due date is configured to sync with an object or document field.

<Aside type="tip" title="Tip">
Vault Java SDK also supports completing workflow tasks.
</Aside>

## How to Start a Workflow

The following is an example of a starting a workflow with the Vault Java SDK:

```java
// Records to start Workflow with
String objectName = "object__c";
String record1 = "V5K000000001001";
String record2 = "V5K000000001002";
List<String> records = VaultCollections.asList(record1, record2);  // can also be list of documents if it's a document workflow

WorkflowMetadataService workflowMetadataService = ServiceLocator.locate(WorkflowMetadataService.class);

// 1) Get available workflows for given records
AvailableWorkflowMetadataCollectionRequest availableWorkflowsRequest = workflowMetadataService.newAvailableWorkflowMetadataCollectionRequestBuilder()
                                                                .withRecords(objectName, records)
                                                                .build();

AvailableWorkflowMetadataCollectionResponse response = workflowMetadataService.getAvailableWorkflows(availableWorkflowsRequest);

// Get list of available workflow for the given content listing
List<AvailableWorkflowMetadata> availableWorkflows = response.getWorkflows();

// Can loop over list of AvailableWorkflowMetadata to find/show all available workflows

// 2) Get Start step details to begin workflow
WorkflowStartMetadataRequest startMetadataRequest = workflowMetadataService.newWorkflowStartMetadataRequestBuilder()
                                                                    .withWorkflowName(workflowName)
                                                                    .withRecords(objectName, records)
                                                                    .build();

WorkflowStartMetadataResponse startMetadataResponse = workflowMetadataService.getWorkflowStartMetadata(startMetadataRequest);

// List of control sections in the start step
List<WorkflowStartStepMetadata> startStepMetadata = startMetadataResponse.getStartStepMetadataList();

for (WorkflowStartStepMetadata metadata : startStepMetadata){
    WorkflowStartStepType metaDataType = metadata.getType();  // Type of Start control (Participant, date, etc.)

    List<WorkflowParameterMetadata> parameters = metadata.getParameters(); // Parameters needed to start the workflow

    for (WorkflowParameterMetadata param : parameters) {
      String paramName = param.getName();                           // used in input parameter key
            WorkflowInputValueType valueType = param.getDataType();       // used to set the value of the control
        }
    }
}

// 3) Start workflow with these start inputs

String participantName = "viewer__c";
Long userId = 100l;
Long groupId = 500l;
List<String> userIds = VaultCollections.asList(userId.toString());
List<String> groupIds = VaultCollections.asList(groupId.toString());

String numberInput = "number__c";
int number = 123;

WorkflowInstanceService workflowInstanceService = ServiceLocator.locate(WorkflowInstanceService.class);

// Set workflow participants input
WorkflowParticipantInputParameter workflowParticipantInputParameter = workflowInstanceService.newWorkflowParticipantInputParameterBuilder()
            .withUserIds(userIds)
            .withGroupIds(groupIds)
            .build();

// Create Start instance request with the builder
WorkflowStartInstanceRequest startRequest = workflowInstanceService.newWorkflowStartRequestBuilder()
            .withWorkflowName(workflowName)
            .withRecords(objectName, records)
            .withInputParameters(numberInput, number)
            .withInputParameters(participantName, workflowParticipantInputParameter)
            .build();

// Start workflow with start request and success and error handlers
workflowInstanceService.startWorkflow(startRequest)
            .onSuccess(startResponse -> {
                String workflowId = startResponse.getWorkflowId();
                // Developer provided success handling logic here
            })
            .onError(startResponse -> {
                // Developer provided failure handling logic here
                if (startResponse.getErrorType() == ActionErrorType.INVALID_REQUEST) {
                    throw new RuntimeException(startResponse.getMessage());
                } else {
                    // ...
                }
            })
            .execute();  // needed to execute the action
```

## How to Complete a Workflow Task

Complete a workflow task with Vault Java SDK in the following steps:

1.  **Retrieve Metadata**: Query the task instance to understand the input required to complete the task. In Vault, these requirements are called prompts. For example, a workflow task may prompt the user for a verdict. Verdicts may also include a *Capacity* field, which lets the user provide additional context for their task verdict. Include capacities in `WorkflowTaskInput`. Learn more about [prompts and verdicts in Vault Help](https://platform.veevavault.help/en/lr/33550/#wftaskstep).
2.  **Construct the Completion Request**: Construct the completion request. This request must have the same structure as the metadata, including all supporting task inputs and task verdict inputs.
3.  **Execute**: Execute the completion request. As a best practice, include success and failure cases to handle input errors.

<Aside type="warning" title="Warning">
Vault Java SDK does not support workflow tasks that require an eSignature.
</Aside>

The following is an example of a completing a workflow task with Vault Java SDK:

```Java
// 1) Get the task metadata to understand requirements
WorkflowTaskMetadataRequest metadataRequest = workflowMetadataService.newWorkflowTaskMetadataRequestBuilder()
                 .withTaskId(taskId)
                 .build();
WorkflowTaskMetadataResponse metadataResponse = workflowMetadataService.getWorkflowTaskMetadata(metadataRequest);

// 2) Inspect metadata. This example assumes we want to approve (verdict_approve__c)
String verdictToUse = "verdict_approve__c"; // The API name of the verdict
WorkflowTaskVerdictMetadata verdictMetadata = null;
for (WorkflowTaskVerdictMetadata v : metadataResponse.getVerdicts()) {
             if (v.getName().equals(verdictToUse)) {
                 verdictMetadata = v;
                 break;
             }
         }

// 3) Build WorkflowTaskInput for task-level prompts (such as verdicts, verdict capacities, comments, or reasons)
WorkflowTaskInput.Builder inputBuilder = workflowTaskService.newWorkflowTaskInputBuilder();

// 4) If a verdict is a required parameter for the task, add that here
inputBuilder.withInputParameters("verdict_public_key__c", verdictToUse);

// 5) Iterate over verdictMetadata.getPrompts() to find parameter names
for (WorkflowTaskPromptMetadata prompt : verdictMetadata.getPrompts()) {
             for (WorkflowParameterMetadata param : prompt.getParameters()) {
                 // Example: Set a comment if required
                 if (prompt.getType() == WorkflowTaskPromptType.COMMENT) {
                     inputBuilder.withInputParameters(param.getName(), "Approved via SDK");
                 }
             }
         }

WorkflowTaskInput taskInput = inputBuilder.build();

WorkflowTaskCompleteRequest completeRequest = workflowTaskService.newTaskCompleteRequestBuilder()
                 .withTaskId(taskId)
                 .withTaskInput(taskInput)
                 .build();

// 6) Execute the completion request
workflowTaskService.completeTask(completeRequest)
                 .onSuccess(response -> {
                     // Handle success
                 })
                 .onTaskInputError(response -> {
                     // Handle general input errors
                 })
                 .execute();
```

---

**Previous:** [Lifecycle Services](/medical/vault-sdk/services/lifecycle-services)  
**Next:** [Annotation Services](/medical/vault-sdk/services/annotation-services)