Change the workflow state

View as Markdown

An object's workflow and state are property values: Workflow (38) and State (39). Read which states and transitions the workflow has and which of them the user may take, then change the state with a property update.

Calls

A class can have a default workflow (default_workflow of the ObjectClass); see Read the vault structure.

Code

The recipe creates a test document that is already in a workflow: it sets Workflow (38) and State (39) when it creates the document. It then reads the workflow's states and transitions for that document and sets State to the target state. The defaults are workflow 107 ("Contract Approval Workflow" in the M-Files Sample Vault), initial state 137 ("Draft") and target state 141 ("Rejected"); pass others as arguments. At the end it deletes the document, unless you pass --keep.

Python

# The states and transitions of the workflow, with what this user may select for
# this object in its current state.
version = obj_ver(object_id.type, object_id.item_id.internal_id,
                  created.version_info.version.internal_version)
workflow = objects.GetWorkflowStatesAndTransitions(
    ops.GetWorkflowStatesAndTransitionsRequest(
        workflow_id=workflow_id,
        current_state=lookup(8, initial_state),
        obj_ver=version))
for state in workflow.states:
    print(f"  State {state.id} {state.name}: "
          f"selectable {state.can_current_user_select}")
for transition in workflow.transitions:
    print(f"  Transition {transition.id} {transition.name}: "
          f"{transition.from_state_id} -> {transition.to_state_id}, "
          f"selectable {transition.can_current_user_select}")

# Change the state by setting property 39 "Workflow State" on the version just read.
updated = objects.SetProperties(ops.SetPropertiesRequest(
    obj_ver=version,
    allow_modifying_checked_in_object=True,
    fail_if_newer_version_exists=True,
    properties=[property_value(39, lookup(8, target_state))]))

Source: python/recipes/workflow_state.py

C#

// The states and transitions of the workflow, with what this user may select for
// this object in its current state.
var objVer = ObjVer(objId.Type, objId.ItemId.InternalId, created.VersionInfo.Version.InternalVersion);
var workflow = await objects.GetWorkflowStatesAndTransitionsAsync(new GetWorkflowStatesAndTransitionsRequest
{
    WorkflowId = workflowId,
    CurrentState = Lookup(8, initialState),
    ObjVer = objVer,
});
foreach (var state in workflow.States)
    Console.WriteLine($"  State {state.Id} {state.Name}: selectable {state.CanCurrentUserSelect}");
foreach (var transition in workflow.Transitions)
{
    Console.WriteLine($"  Transition {transition.Id} {transition.Name}: {transition.FromStateId} -> " +
        $"{transition.ToStateId}, selectable {transition.CanCurrentUserSelect}");
}

// Change the state by setting property 39 "Workflow State" on the version just read.
var updated = await objects.SetPropertiesAsync(new SetPropertiesRequest
{
    ObjVer = objVer,
    AllowModifyingCheckedInObject = true,
    FailIfNewerVersionExists = true,
    Properties = { Property(39, Lookup(8, targetState)) },
});

Source: csharp/Recipes/WorkflowState.cs

Go

// The states and transitions of the workflow, with what this user may select for this
// object in its current state.
objVer := mfilesclient.ObjVer(objID.GetType(), objID.GetItemId().GetInternalId(),
	created.GetVersionInfo().GetVersion().GetInternalVersion())
workflow, err := objects.GetWorkflowStatesAndTransitions(ctx,
	&mfiles.GetWorkflowStatesAndTransitionsRequest{
		WorkflowId:   workflowID,
		CurrentState: mfilesclient.Lookup(8, initialState),
		ObjVer:       objVer,
	})
if err != nil {
	return err
}
for _, state := range workflow.GetStates() {
	fmt.Printf("  State %d %s: selectable %v\n", state.GetId(), state.GetName(),
		state.GetCanCurrentUserSelect())
}
for _, transition := range workflow.GetTransitions() {
	fmt.Printf("  Transition %d %s: %d -> %d, selectable %v\n", transition.GetId(),
		transition.GetName(), transition.GetFromStateId(), transition.GetToStateId(),
		transition.GetCanCurrentUserSelect())
}

// Change the state by setting property 39 "Workflow State" on the version just read.
updated, err := objects.SetProperties(ctx, &mfiles.SetPropertiesRequest{
	ObjVer:                        objVer,
	AllowModifyingCheckedInObject: true,
	FailIfNewerVersionExists:      true,
	Properties: []*mfiles.PropertyValue{
		mfilesclient.PropertyValue(39, mfilesclient.Lookup(8, targetState)),
	},
})
if err != nil {
	return err
}

Source: go/recipes/workflow_state/main.go

Output against the Sample Vault:

Created [docs-test] Python workflow-state (ID 613, version 1, modified 2026-10-31 14:55:59 UTC)
  State 137 Draft: selectable True
  State 138 Waiting for Approval: selectable True
  State 139 Approved: selectable False
  State 140 Expired: selectable False
  State 141 Rejected: selectable True
  Transition 5 Rejected: 137 -> 141, selectable True
  Transition 11 Waiting for Approval: 137 -> 138, selectable True
State is now Rejected (ID 141), version 2
Deleted object 0-613

Pitfalls

See also