When a user is terminated, their open work items should be reassigned to their manager

Hey Guys ,

i have a leaver requirement which says When a user is terminated, their open work items should be reassigned to their manager. Can we achive it throug UI or we have to write a workfloww for this ?? pls help

Detailed requirement :

2 Likes

@Rakesh_Singh_1234

You can achieve this using workflow .

step 1- trigger workflow on lcs change or attribute level change

step 2- cap user details

step 3- call API({{baseUrl}}/work-items/:id) to get the work items further filter with completed or not

step 4 you can assign retreive the value and reassign them using ({{baseUrl}}/work-items/:id/forward)

Thanks

shantanu

1 Like

hey @schattopadhy i made below workflow is it good ? if now can u kindly give me a workflow pls?

{
  "name": "Leaver Workflow - Reassign Work Items to Manager",
  "description": "Reassign all open work items of a terminated user to their manager and notify the manager.",
  "trigger": {
    "type": "EVENT",
    "attributes": {
      "id": "idn:identity-attributes-changed",
      "attributeToFilter": "cloudLifecycleState",
      "filter.$": "$.changes[?(@.attribute == \"cloudLifecycleState\" && @.newValue == \"terminated\")]"
    }
  },
  "definition": {
    "start": "Get User Details",
    "steps": {
      "Get User Details": {
        "type": "action",
        "actionId": "sp:get-identity",
        "attributes": {
          "id.$": "$.trigger.identity.id"
        },
        "nextStep": "Find Open Work Items"
      },
      "Find Open Work Items": {
        "type": "action",
        "actionId": "sp:search",
        "attributes": {
          "objectType": "workItem",
          "filter.$": "assignee.id == '{{$.getUserDetails.id}}' AND status == 'OPEN'"
        },
        "nextStep": "Loop Work Items"
      },
      "Loop Work Items": {
        "type": "action",
        "actionId": "sp:loop",
        "attributes": {
          "input.$": "$.FindOpenWorkItems.results",
          "loopVariableName": "workItem"
        },
        "nextStep": "Reassign Work Item"
      },
      "Reassign Work Item": {
        "type": "action",
        "actionId": "sp:update-object",
        "attributes": {
          "objectType": "workItem",
          "objectId.$": "$.loop.workItem.id",
          "changes": {
            "assignee": "{{$.getUserDetails.managerRef.id}}"
          }
        },
        "nextStep": "Send Notification"
      },
      "Send Notification": {
        "type": "action",
        "actionId": "sp:send-email",
        "attributes": {
          "to": "{{$.getUserDetails.managerRef.email}}",
          "subject": "Work Items Reassigned for {{$.getUserDetails.displayName}}",
          "body": "All open work items for {{$.getUserDetails.displayName}} (terminated) have been reassigned to you."
        },
        "nextStep": "Workflow Complete"
      },
      "Workflow Complete": {
        "type": "success",
        "actionId": "sp:operator-success",
        "description": "Reassignment workflow completed successfully"
      }
    }
  }
}

{
  "name": "Leaver Workflow - Reassign Work Items",
  "description": "This workflow reassigns all open work items from a terminated user to their manager.",
  "modified": "2025-09-08T12:30:00Z",
  "modifiedBy": {
    "type": "IDENTITY",
    "id": "9e1a8100c603c89a69c74911",
    "name": "aps"
  },
  "definition": {
    "start": "Get Leaver Details",
    "steps": {
      "Get Leaver Details": {
        "actionId": "sp:get-identity",
        "attributes": {
          "id.$": "$.trigger.identity.id"
        },
        "description": "Fetch full details of the terminated identity",
        "displayName": "Get Leaver Identity",
        "nextStep": "Get Work Items",
        "type": "action",
        "versionNumber": 1
      },
      "Get Work Items": {
        "actionId": "sp:http",
        "attributes": {
          "authenticationType": "OAuth",
          "method": "get",
          "oAuthClientId": "your-client-id",
          "oAuthClientSecret": "$.secrets.your-secret-id",
          "oAuthCredentialLocation": "oAuthInHeader",
          "oAuthTokenUrl": "https://sbc-sb.api.identitynow.com/oauth/token",
          "requestContentType": "json",
          "url": "https://sbc-sb.api.identitynow.com/v3/work-items?assigneeId={{$.getLeaverDetails.id}}&status=OPEN"
        },
        "description": "Fetch all open work items assigned to the terminated user",
        "displayName": "Fetch Work Items",
        "nextStep": "Loop Work Items",
        "type": "action",
        "versionNumber": 1
      },
      "Loop Work Items": {
        "actionId": "sp:loop",
        "attributes": {
          "input.$": "$.getWorkItems.body",
          "loopVariableName": "workItem"
        },
        "description": "Loop through each open work item",
        "displayName": "Loop Work Items",
        "nextStep": "Forward Work Item",
        "type": "action",
        "versionNumber": 1
      },
      "Forward Work Item": {
        "actionId": "sp:http",
        "attributes": {
          "authenticationType": "OAuth",
          "method": "post",
          "oAuthClientId": "your-client-id",
          "oAuthClientSecret": "$.secrets.your-secret-id",
          "oAuthCredentialLocation": "oAuthInHeader",
          "oAuthTokenUrl": "https://spc-sb.api.identitynow.com/oauth/token",
          "requestContentType": "json",
          "url": "https://spc-sb.api.identitynow.com/v3/work-items/{{$.loop.workItem.id}}/forward",
          "jsonRequestBody": {
            "assigneeId": "{{$.getLeaverDetails.managerRef.id}}"
          }
        },
        "description": "Forward the work item to the manager",
        "displayName": "Forward Work Item",
        "nextStep": "Workflow Complete",
        "type": "action",
        "versionNumber": 1
      },
      "Workflow Complete": {
        "actionId": "sp:operator-success",
        "description": "All work items reassigned successfully",
        "displayName": "Workflow Complete",
        "type": "success"
      }
    }
  },
  "creator": {
    "type": "IDENTITY",
    "id": "9e1a8100c60343c8911ca09c74911",
    "name": ""
  },
  "trigger": {
    "type": "EVENT",
    "attributes": {
      "id": "idn:identity-attributes-changed",
      "attributeToFilter": "cloudLifecycleState",
      "filter.$": "$.changes[?(@.attribute == \"cloudLifecycleState\" && @.newValue == \"terminated\")]"
    }
  }
}

@Rakesh_Singh_1234 let me have a look

i have modified a bit you can further verify by changing the data

{
	"name": "Leaver Workflow - Reassign Work Items",
	"description": "This workflow reassigns all open work items from a terminated user to their manager.",
	"modified": "2025-09-08T12:53:25.679130554Z",
	"modifiedBy": {
		 "type": "IDENTITY",
    "id": "9e1a8100c603c89a69c74911",
    "name": "aps"
	},
	"definition": {
		"start": "Compare Strings",
		"steps": {
			"Compare Strings": {
				"actionId": "sp:compare-strings",
				"choiceList": [
					{
						"comparator": "StringEquals",
						"nextStep": "Get Leaver Details",
						"variableA.$": "$.trigger.changes[?(@.attribute == 'cloudLifecycleState')].newValue",
						"variableB": "terminated"
					}
				],
				"defaultStep": "End Step - Success",
				"displayName": "",
				"type": "choice"
			},
			"End Step - Success": {
				"actionId": "sp:operator-success",
				"displayName": "",
				"type": "success"
			},
			"End Step - Success 2": {
				"actionId": "sp:operator-success",
				"displayName": "",
				"type": "success"
			},
			"Get Leaver Details": {
				"actionId": "sp:get-identity",
				"attributes": {
					"id.$": "$.trigger.identity.id"
				},
				"description": "Fetch full details of the terminated identity",
				"displayName": "Get Leaver Identity",
				"nextStep": "Get Work Items",
				"type": "action",
				"versionNumber": 1
			},
			"Get Work Items": {
				"actionId": "sp:http",
				"attributes": {
					"authenticationType": "OAuth",
					"method": "get",
					"oAuthClientId": "your-client-id",
					"oAuthClientSecret": "",
					"oAuthCredentialLocation": "oAuthInHeader",
					"oAuthTokenUrl": "https://sbc-sb.api.identitynow.com/oauth/token",
					"requestContentType": "json",
					"url": "https://sailpoint.api.identitynow.com/v3/work-items?ownerId=1211bcaa32112bcef6122adb21cef1ac&limit=100"
				},
				"description": "Fetch all open work items assigned to the terminated user",
				"displayName": "Fetch Work Items",
				"nextStep": "Loop",
				"type": "action",
				"versionNumber": 1
			},
			"Loop": {
				"actionId": "sp:loop:iterator",
				"attributes": {
					"start": "Forward Work Item",
					"steps": {
						"Forward Work Item": {
							"actionId": "sp:http",
							"attributes": {
								"authenticationType": "OAuth",
								"jsonRequestBody": {
									"assigneeId": "{{$.getLeaverDetails.managerRef.id}}"
								},
								"method": "post",
								"oAuthClientId": "your-client-id",
								"oAuthClientSecret": "",
								"oAuthCredentialLocation": "oAuthInHeader",
								"oAuthTokenUrl": "https://spc-sb.api.identitynow.com/oauth/token",
								"requestContentType": "json",
								"url": "https://spc-sb.api.identitynow.com/v3/work-items/{{$.loop.workItem.id}}/forward"
							},
							"description": "Forward the work item to the manager",
							"displayName": "Forward Work Item",
							"nextStep": "Workflow Complete",
							"type": "action",
							"versionNumber": 1
						},
						"Workflow Complete": {
							"actionId": "sp:operator-success",
							"description": "All work items reassigned successfully",
							"displayName": "Workflow Complete",
							"type": "success"
						}
					}
				},
				"displayName": "",
				"nextStep": "End Step - Success 2",
				"type": "action",
				"versionNumber": 1
			}
		}
	},
	"creator": {
		"type": "IDENTITY",
		"id": "3f946f3831234cba96f8623398ea5e2f",
		"name": "Shantanu Chattopadhyay"
	},
	"trigger": {
		"type": "EVENT",
		"attributes": {
			"attributeToFilter": "cloudLifecycleState",
			"filter.$": "$.changes[?(@.attribute == \"cloudLifecycleState\" && @.newValue == \"terminated\")]",
			"id": "idn:identity-attributes-changed"
		}
	}
}

Hi Fellow Developers,

I believe the above is a great workflow.

Wanted to share that there is a work reassignment API, which might be a better fit for the requirement. Unlike the API used in workflows that only handle existing open work items to be reassigned, work reassignment API ensures any future work assigned to the terminated user automatically goes to the manager.

Good luck!

hey @TheOneAMSheriff It worked but still have one doubt how to validate it ?? i mean in UI how we can validate that work item is frowarded to manager as we need to validate

1 Like

Hi Rakesh,

I am glad it worked for you. For testing/proof of concept I would recommend you choose identity to be terminated and identity’s manager both which you can login yourself, easy to see work items move from one identity to another along with work reassignment in Preferences of terminated identity. If you preference not to login as the test identities I would recommend below steps: -

  1. Identify a few identities with open work items of different types (access request approval, certification, and manual task from disconnected source as applicable) that you can terminate. Would be better if you can store the work item JSON using API: get-work-item | SailPoint Developer Community. The response from this API holds ownerName and ownerId. Can be used as before change evidence.
  2. Configure/Enable the workflow and terminate the identified identity/identities for validation.
  3. The same Get work item API above should have the updated owner details which could be your after change evidence. Also an additional record in the JSON response of API: list-reassignment-configurations | SailPoint Developer Community in case work reassignment was already being used in the tenant.

I hope this helps.

@TheOneAMSheriff Hey Amar just wanted to know will this api covers all type of requests like cert and all and fowwd to manager?

Hi Rakesh,

Yes, the work reassignment API: create-reassignment-configuration | SailPoint Developer Community should be able to forward all 3 types of work items: -

@TheOneAMSheriff hey amar we tried the below in body

{
“reassignedFromId”: “f108f2a7f344409982ad64cabd9d4af4”,
“reassignedToId”: “d6deda39d7294a69965dd1a778ee2d2a”,
“configDetails”: “ACCESS_REQUESTS”,
“startDate”: “2025-09-12T17:00:00.000Z”,
“endDate”: “2028-07-30T17:00:00.000Z”
}

and it is giving us bad request can u kindly tell me how we can do it?

Hi Rakesh,

The work reassignment API was introduced in API version v2024, also included in v2025. Both APIs are in experimental state, so if you didn’t select the experimental header you would get the expected 400 Bad Request error as below: -

Select the header X-SailPoint-Experimental and the API should run fine, provided the body of the API call has valid identity ids and dates: -

I hope this helps.

we have selected it @TheOneAMSheriff but can u pls send us what you are giving in the body …?and my post is successful but where in the UI i can confirm that the item is forwared to the manager i chked the event but it is not coming ?

Hi Rakesh, I confirm my payload for the POST API call was the same structure as yours above. In the UI for the terminated user the work reassignment should look like this:-

Let me know the error message if you are still facing issue with API :slight_smile:

Hey @TheOneAMSheriff Amar, in config details in the body can we give both ACCESS REQUESTS and CERTIFICATION in one go for all work item forward (like cert ,tasks ,acess req)

so with same config type : ACCESS_REQUESTS can all things happen like cert tasks and roles?

FOR EX ;

{
“configType”: [“ACCESS_REQUESTS”, “CERTIFICATIONS”],
“endDate”: “{{$.now()}}”,
“reassignedFromId”: “{{$.getIdentity.id}}”,
“reassignedToId”: “{{$.getIdentity.managerRef.id}}”,
“startDate”: “{{$.now()}}”
}

we have got one error in workflow below is error :

{
“authenticationType”: “OAuth”,
“basicAuthPassword”: null,
“basicAuthUserName”: null,
“csvRequestBody”: null,
“formRequestBody”: null,
“headerAuthName”: null,
“headerAuthValue”: null,
“jsonRequestBody”: {
“configDetails”: “ACCESS_REQUESTS”,
“endDate”: “2025-09-11T14:16:30.991Z”,
“reassignedFromId”: “31d1d59e1c78400da97bffef60c6”,
“reassignedToId”: “fc411d44f1ac4d95b225465ed707”,
“startDate”: “2025-09-11T14:16:30.992Z”
},
“method”: “post”,
“oAuthClientId”: “c70df491faea4048b563f00c465c”,
“oAuthClientSecret”: “$.secrets.e07c6367-4f59-427f-b019-f73ce9f4e57f”,
“oAuthCredentialLocation”: “oAuthInHeader”,
“oAuthScope”: null,
“oAuthTokenUrl”: “https://xyz-sb.api.identitynow.com/oauth/token”,
“requestContentType”: “json”,
“requestHeaders”: null,
“suppliedInlineExpression”: {
“jsonRequestBody”: “{“configDetails”:“ACCESS_REQUESTS”,“endDate”:“{{$.now()}}”,“reassignedFromId”:“{{$.getIdentity.id}}”,“reassignedToId”:“{{$.getIdentity.managerRef.id}}”,“startDate”:“{{$.now()}}”}”
},
“textRequestBody”: null,
“url”: “https://xyz-sb.api.identitynow.com/beta/reassignment-configurations”,
“urlParams”: null,
“xmlRequestBody”: null
}

Hi Rakesh,

Ahh bummer! Seems like not possible as configType is expected to be a string.

so what we can do as we can have certificate , work item and access request , task we have to forward all?

You would have to make one HTTP request/action per config type. In your case of access request and certification, 2 HTTP actions precisely.

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.