Webservice After Rule - Aggregation

Hi,

I need to write a webservice after rule for an aggregation operation, Now whatever I configured in pagination will remain same. Is that true.

can someone share any same code if you have worked on the same use case. Any guidance would be approeciated.

Hey Chandra,

Pagination config happens in the connector. If it’s setup correctly there, it will continue to work the same.

  • You do not need to implement pagination logic in the after operation rule
  • The After Rule will receive the aggregated data per page, and you can manipulate or transform it as needed.

If you’d like to confirm my response, you can review this discussion wherein they talk about the same: HTTP Aggregation operation - Paging - Identity Security Cloud (ISC) / ISC Discussion and Questions - SailPoint Developer Community

Can you be more specific about this and also explain what are you looking to achieve?

Pagination configuration in the UI is to iterate through multiple API calls when all records are not returned in on API call from endpoint of the application (which is the case with almost every API service) and you can modify the offset values under Pagination settings so that you can tell ISCloud how to make each call until all values are fetched and then to stop.

However, if you are planning to do something with the returned data, then you can do it in the AfterOp rule

1 Like

@iamology So if my response has 10 pages, then my After rule gets executed for 10 times?

that’s right. After Operation is called after each page. If you like to reuse any of the values in these executions, you can use transientValue approach explained in this page:

2 Likes

can you clarify what you need for pagination here?
Does it use Query params, ie https://site?limit=250&offset=250
or something in the body?
does it involve a response header? part of the previous response?

@StephenHolinaty My requirement here is.

The API call returns body something like below

```

{

"records": \[

    {

        "foldername": "testuser1",

        "id": "41"

    },

    {

        "foldername": "testuser2",

        "id": "42"

    },

    {

        "foldername": "testuser3",

        "id": "43"

    }

\]

}

Now I need to use the ID and make an other API call, passing ID as input which returns me userEmail. Now I need to insert the attribute userEmail to my responseObject..

```{

"records": \[

    {

        "foldername": "testuser1",

        "id": "41",

        "userEmail": "testuser1@gmail.com"

    },

    {

        "foldername": "testuser2",

        "id": "42",

        "userEmail": "testuser3@gmail.com"

    },

    {

        "foldername": "testuser3",

        "id": "43",

        "userEmail": "testuser3@gmail.com"

    }

\]

}

based on what you’ve written here, that doesnt sound like “Pagination”

that sounds like you need (pseudo-code…)

GET /Users

  • parse the user responses, and get things like email, foldername, id

CHILD OPERATION of the first agg (set a parent endpoint of the 1st call)
GET /users/$response.id$

  • do the next things, grab the email address
2 Likes

Expanding on the parent/child endpoint relationship slightly more,

the connector will perform (page 1) of the GET to /Users
then for each individual record, as specified by your root path ($, $.users, etc.), it will call the child operation to supplement the data.

1 Like

@StephenHolinaty

Actually the reason I thought of after rule is because there is an additional logic. my second API call returns multiple records, I need to check if it is equals to “Employee“ only then take the value “userEmail” and set it on response object.

you might even be able to do that with JSONPath in your mappings
root: $
email: $[?(@.type == “Employee”)].email
or similar

1 Like

this might also help: Using WebService connector rules to streamline and accommodate “interesting” sources

1 Like

@StephenHolinaty

In the Example script and video, the APIs to get Job Name.. those APIs can be made independent of user information to made transient. But in my use case, I need to get userID from my API 1 and then need to call API2 to get user details.

If there are 100 users, then API count is going to be 101.

From your explanation its a simple parent endpoint aggregation and doesn`t need a rule to read the accounts!

{

            "httpMethodType": "GET",

            "pagingInitialOffset": 0,

            "requestType": "API",

            "sequenceNumberForEndpoint": "3",

            "uniqueNameForEndPoint": "Read Accounts",

            "rootPath": "$\[\*\]",

            "body": {

                "bodyFormData": null,

                "jsonBody": null,

                "bodyFormat": null

            },

            "paginationSteps": null,

            "responseCode": \[

                "2\*\*"

            \],

            "resMappingObj": {

                "blocked": "blocked",

                "user_id": "user_id",

                "name": "name",

                "nickname": "nickname",

                "email": "email"

            },

            "contextUrl": "users",

            "pagingSize": 50,

            "header": {

                "Authorization": "Bearer $application.accessToken$",

                "Accept": "application/json"

            },

            "operationType": "Account Aggregation",

            "xpathNamespaces": null,

            "parentEndpointName": null

        },

        {

            "httpMethodType": "GET",

            "pagingInitialOffset": 0,

            "requestType": "API",

            "sequenceNumberForEndpoint": "4",

            "uniqueNameForEndPoint": "Get User Roles",

            "rootPath": "$\[\*\]",

            "body": {

                "bodyFormData": null,

                "jsonBody": null,

                "bodyFormat": null

            },

            "paginationSteps": null,

            "responseCode": \[

                "2\*\*"

            \],

            "resMappingObj": {

                "roles": "id"

            },

            "contextUrl": "users/$response.user_id$/roles",

            "pagingSize": 50,

            "header": {

                "Authorization": "Bearer $application.accessToken$",

                "Accept": "application/json"

            },

            "operationType": "Account Aggregation",

            "xpathNamespaces": null,

            "parentEndpointName": "Read Accounts"

        }

In this case a call the endpoint users and for each user i call **users/$response.user_id$/roles.
**
Best Regards!

1 Like

@YanCoelho Thanks for your reply,

actually this API **users/$response.user_id$/roles returns me an array of values.

{
“records”: [
{
“id”: 1878,
“folderId”: 524,
“groupId”: 42,
“groupName”: null,
“userId”: 36,
“userName”: “DelineaAppUserDEV”,
“folderAccessRoleId”: 10,
“folderAccessRoleName”: “Owner”,
“secretAccessRoleId”: 11,
“secretAccessRoleName”: “Owner”,
“knownAs”: “Delinea Application User - DEV”,
“domainName”: null
},
{
“id”: 1879,
“folderId”: 524,
“groupId”: 11,
“groupName”: “az_ss_dev_admin”,
“userId”: null,
“userName”: null,
“folderAccessRoleId”: 10,
“folderAccessRoleName”: “Owner”,
“secretAccessRoleId”: 9,
“secretAccessRoleName”: “List”,
“knownAs”: “testCorp.com \az_ss_dev_admin”,
“domainName”: "testCorp.com "
},
{
“id”: 1880,
“folderId”: 524,
“groupId”: 143,
“groupName”: null,
“userId”: 103,
“userName”: “Erica.Salazar.ctr@testCorp.com”,
“folderAccessRoleId”: 12,
“folderAccessRoleName”: “View”,
“secretAccessRoleId”: 11,
“secretAccessRoleName”: “Owner”,
“knownAs”: “rawo365testing.onmicrosoft.com (testCorp)\Erica Salazar CONTRACTOR”,
“domainName”: “rawo365testing.onmicrosoft.com (testCorp)”
}
]
}

I need to do a conditional check to see if groupName is null and userId != 36

The JSON I gave you is just an example. You need to change it to fit your own APIs and data.

Let’s start with your first API endpoint. Imagine it’s called “users” (which gets a list of user accounts). We’ll name this operation “Read Accounts” in our system.

The data it returns might look like this simple list:

"records": [
  { "foldername": "testuser1", "id": "41" },
  { "foldername": "testuser2", "id": "42" },
  { "foldername": "testuser3", "id": "43" }
]

For this, your settings (called “attribute mapping”) should probably be:

  • “rootPath”: “$.records[*]” (This tells the system to look at each item in the “records” list.)

  • “resMappingObj”: { “folderName”: “foldername”, “id”: “id” } (This matches the fields from the data to what our system expects.)

Now, for your second API endpoint. Imagine it’s something like “user/<user_id>/email” (where you replace <user_id> with a real ID to get that user’s email). It might return simple data like:

{
  "email": "yan.coelho@sailpoint.com"
}

To handle this, create a new operation in our system called “Get User Email” (or whatever name makes sense).

  • Set “Read Accounts” as its parent (because it builds on the list from the first one).

  • For the URL, use: “user/$response.id$/email” (The “$response.id$” part automatically pulls the “id” from the first operation’s results and plugs it in.)

Best regards!!

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