Generic Workflow to Auto-Approve/Reject an access request

@Bassem_Mohamed Below is the workflow to deny pending access request when it has crossed 30 days. However, it is not working in prod environment, but it is working in sandbox environment.

“name”: “Cancel Pending Access Requests”,
“description”: “Cancel Pending Access Requests which are older than 30 days.”,
“modified”: “2025-10-19T23:23:36.927240035Z”,
“modifiedBy”: {
“type”: “IDENTITY”,
“id”: “xxxxxxxxxxxxxxxx”,
“name”: “Kxxxxxx”
},
“definition”: {
“start”: “HTTP Request 1”,
“steps”: {
“End Step - Success 2”: {
“actionId”: “sp:operator-success”,
“displayName”: “”,
“type”: “success”
},
“HTTP Request 1”: {
“actionId”: “sp:http”,
“attributes”: {
“authenticationType”: “OAuth”,
“jsonRequestBody.$”: “”,
“method”: “get”,
“oAuthClientId”: “xxxxxxxxxxxxxxxxxxxxxxxx”,
“oAuthClientSecret”: “$.secrets.xxxxxxxxxxxxxx”,
“oAuthCredentialLocation”: “oAuthInHeader”,
“oAuthTokenUrl”: “https://xxxxxxx.api.identitynow.com/oauth/token”,
“requestContentType”: “json”,
“url”: “https://xxxxxx.api.identitynow.com/v3/access-request-approvals/pending”
},
“displayName”: “”,
“nextStep”: “Loop”,
“type”: “action”,
“versionNumber”: 2
},
“Loop”: {
“actionId”: “sp :loop:iterator”,
“attributes”: {
“context.$”: “”,
“input.$”: “$.hTTPRequest1.body”,
“start”: “Compare Timestamps”,
“steps”: {
“Compare Timestamps”: {
“actionId”: “sp:compare-timestamps”,
“choiceList”: [
{
“comparator”: “TimestampLessThanXDay”,
“nextStep”: “Deny Access Request”,
“variableA.$”: “$.loop.loopInput.requestCreated”,
“variableB”: “30”
}
],
“defaultStep”: “End Step - Success”,
“displayName”: “”,
“type”: “choice”
},
“Deny Access Request”: {
“actionId”: “sp:reject-request”,
“attributes”: {
“approvalId.$”: “$.loop.loopInput.id”,
“comment”: “This request was automatically declined as it is over 30 days old.”
},
“displayName”: “”,
“nextStep”: “End Step - Success 1”,
“type”: “action”,
“versionNumber”: 1
},
“End Step - Success”: {
“actionId”: “sp:operator-success”,
“displayName”: “”,
“type”: “success”
},
“End Step - Success 1”: {
“actionId”: “sp:operator-success”,
“displayName”: “”,
“type”: “success”
}
}
},
“displayName”: “”,
“nextStep”: “End Step - Success 2”,
“type”: “action”,
“versionNumber”: 1
}
}
},
“creator”: {
“type”: “IDENTITY”,
“id”: “xxxxxxxxxxx”,
“name”: “xxxxxxx”
},
“trigger”: {
“type”: “SCHEDULED”,
“attributes”: {
“cronString”: “0 1 * * *”,
“dailyTimes”: [
“1969-12-31T19:30:00.000Z”
],
“frequency”: “daily”,
“id”: “idn:cron-schedule”,
“timeZone”: “Asia/Calcutta”
}
}
}

Any thoughts?

Hi @karan_1984, what’s the error? did you try to reach out our support or Expert service team?

There is no error.

No Not yet.

Hey @karan_1984, if there is no error, maybe you need to revisit the workflow logic.

Hi @Bassem_Mohamed
I’ve built a similar workflow where access requests aged 10 days or older are automatically canceled via the API, and an email notification is sent to the requester with the approver’s details.

However, when the approver is part of a governance group, SailPoint appears to generate two approval items per approver. As a result, the requester ends up receiving two email notifications per approver.

Ideally, I’d like to prevent users from being spammed with multiple emails and instead send a single consolidated email listing all relevant approvers.

Is there a workaround for this?

Hi @salam1,

I think you need to add an node to check if the approval is assigned to a governance group, then you need to loop and get all the governance group members emails to send on consolidated to all the approvers.

Thanks!

The get pending requests approvals api does not specify whether the approver is part of a governance group. It simply states the approver’s name.

I was hoping to avoid adding more loops.