# Web Services connector : Add entitlement with PATCH

**URL:** <https://developer.sailpoint.com/discuss/t/web-services-connector-add-entitlement-with-patch/180098>\
**Category:** SHF Discussion and Questions\
**Tags:** webservice-connector, identity-security-cloud\
**Created:** [September 16, 2025, 7:35am UTC](https://developer.sailpoint.com/discuss/t/web-services-connector-add-entitlement-with-patch/180098 "2025-09-16T07:35:33Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![davidtrn](https://sea1.discourse-cdn.com/sailpoint/discuss/user_avatar/developer.sailpoint.com/davidtrn/32/19752_2.png) [@davidtrn](https://developer.sailpoint.com/discuss/u/davidtrn)\
**Post date:** [September 16, 2025, 7:35am UTC](https://developer.sailpoint.com/discuss/t/web-services-connector-add-entitlement-with-patch/180098/1 "2025-09-16T07:35:33Z")

</div>

Hello,

**Context** :

I am trying to integrate an application to ISC using APIs. The accounts aggregation works fine, but the app does not have a dedicated endpoint to add or remove an entitlement.  
It does however have a PATCH operation that can be used, but it replaces all existing entitlements with the new value provided.

**What I tried** :

Following some [threads](https://developer.sailpoint.com/discuss/t/web-service-connector-understand-add-entitlement-operation-flow/151939/2) on the forum, I tried to used 2 chained HTTP operations :

1rst operation :  
Type : Add Entitlement-role  
Retrieve the current users, including the current roles.  
Through postman, the response body is the following :

```auto
{
    "id": "ID-12345",
    "name": {
        "firstName": "John",
        "gender": "UNKNOWN",
        "lastName": "Doe"
    },
    "email": "john.doe@company.com",
    "timeZoneCode": "Europe/Amsterdam",
    "username": "john.doe@company.com",
    "roles": [
        "role1",
        "role2"
    ]
}

```

And my response mapping is :

 ![image](https://global.discourse-cdn.com/sailpoint/original/3X/6/a/6a59a8412320644436c030d3aafb5b5e96d14065.png)

2nd operation :  
Type : Get Object  
Is the actual PATCH operation, set with the 1rst operation as the parent endpoint.

 ![image](https://global.discourse-cdn.com/sailpoint/original/3X/e/5/e5af57332d28fd520f9f9e254bc524fbdc5d6457.png)

To populate this operation with the proper body, I set the following beforeProvisioningRule to it :

```auto
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.List;
import java.util.Set;
import java.util.LinkedHashSet;

Map body = requestEndPoint.getBody();
if (body == null) body = new HashMap();
String jsonBody = (String) body.get("jsonBody");

log.info("App PATCH oldresponse: " + oldResponseMap);

// 1) Read existing roles from oldResponseMap (roles only), normalizing to a List<String>
List currentRoles = null;
if (oldResponseMap != null) {
  Object cur = oldResponseMap.get("roles");
  if (cur instanceof List) {
    currentRoles = (List) cur;
  } else if (cur != null) {
    currentRoles = new ArrayList();
    currentRoles.add(String.valueOf(cur));
  }
}

// 2) Merge existing first, then add the new role (de-duplicated, order-preserving)
Set merged = new LinkedHashSet();

// Add existing first
if (currentRoles != null) {
  for (Object o : currentRoles) {
    if (o != null) merged.add(String.valueOf(o));
  }
}

// 3) Parse new roles from jsonBody (roles only)
if (jsonBody != null) {
  String trimmed = jsonBody.trim();
  try {
    if (trimmed.startsWith("{")) {
      // jsonBody is a JSON object; use 'roles' field only
      Map jsonMap = JsonUtil.toMap(trimmed);
      Object rolesField = (jsonMap != null) ? jsonMap.get("roles") : null;
      if (rolesField instanceof List) {
        for (Object o : (List) rolesField) if (o != null) merged.add(String.valueOf(o));
      } else if (rolesField != null) {
        merged.add(String.valueOf(rolesField));
      } else {
        // No 'roles' in object; treat object string as a single value (optional behavior)
        merged.add(trimmed);
      }
    } else {
      // Single string value
      merged.add(trimmed);
    }
  } catch (Exception e) {
    log.warn(application.getName() + " Combine Roles: Failed to parse jsonBody; treating as single value. Err=" + e);
    merged.add(trimmed);
  }
}

// 4) Build final JSON body: {"roles":[...]}
Map payload = new HashMap();
payload.put("roles", new ArrayList(merged));
String finalBody = connector.common.JsonUtil.render(payload);

body.put("jsonBody", finalBody);
requestEndPoint.setBody(body);

```

Still, the body is always empty.

Anyone has a guess on what is wrong ?

Thank you !

---

<div class="post-metadata">

**Author:** ![Gopi2000](https://sea1.discourse-cdn.com/sailpoint/discuss/user_avatar/developer.sailpoint.com/gopi2000/32/21706_2.png) [@Gopi2000](https://developer.sailpoint.com/discuss/u/Gopi2000)\
**Post date:** [September 16, 2025, 7:55am UTC](https://developer.sailpoint.com/discuss/t/web-services-connector-add-entitlement-with-patch/180098/2 "2025-09-16T07:55:23Z")

</div>

Hi @davidtrn

I’ve worked on a similar scenario where I used the below web service before operation rule.

```auto
List teamIds = new ArrayList();

if (currentRoles != null) {
    for (Object role : currentRoles) {
        if (role instanceof String) {
            try {
                String[] rolesArray = ((String) role).split(",");
                for (String roleStr : rolesArray) {
                    String roleId = roleStr.trim();
                    if (!teamIds.contains(roleId)) {
                        teamIds.add(roleId);
                    }
                }
            } catch (Exception e) {
                throw new GeneralException("Error parsing team_ids String: " + role, e);
            }
        } else {
            throw new Exception("Unexpected type for team ID: " + role.getClass().getName());
        }
    }
} else {
    throw new Exception("currentRoles is null in one of the user objects");
}

} else {
    throw new Exception("Expected a Map in the list but got: " + obj.getClass().getName());
}

}
} else {
    throw new Exception("Expected a List for userObj but got: " + userObj.getClass().getName());
}

Map body = requestEndPoint.getBody();
String jsonBody = (String) body.get("jsonBody");
Map jsonMap = JsonUtil.toMap(jsonBody);
Map usersMap = (Map) jsonMap.get("user");

if (provisioningPlan != null) {
    for (AccountRequest accReq : provisioningPlan.getAccountRequests()) {
        for (ProvisioningPlan.AttributeRequest attReq : accReq.getAttributeRequests()) {
            if ("team_ids".equalsIgnoreCase(attReq.getName())) {
                Object ids = attReq.getValue();
                if (ids instanceof List) {
                    List idsList = (List) ids;
                    for (Object id : idsList) {
                        if (id instanceof String) {
                            String idStr = ((String) id).trim();
                            if (!teamIds.contains(idStr)) {
                                teamIds.add(idStr);
                            }
                        } else {
                            throw new Exception("Unexpected type in team_ids list: " + id.getClass().getName());
                        }
                    }
                } else if (ids instanceof String) {
                    String[] idsArray = ((String) ids).split(",");
                    for (String idStr : idsArray) {
                        String trimmedId = idStr.trim();
                        if (!teamIds.contains(trimmedId)) {
                            teamIds.add(trimmedId);
                        }
                    }
                } else {
                    throw new Exception("Unexpected type for team_ids attribute: " + ids.getClass().getName());
                }
            }
        }
    }
}

```

---

<div class="post-metadata">

**Author:** ![davidtrn](https://sea1.discourse-cdn.com/sailpoint/discuss/user_avatar/developer.sailpoint.com/davidtrn/32/19752_2.png) [@davidtrn](https://developer.sailpoint.com/discuss/u/davidtrn)\
**Post date:** [September 16, 2025, 9:01am UTC](https://developer.sailpoint.com/discuss/t/web-services-connector-add-entitlement-with-patch/180098/3 "2025-09-16T09:01:31Z")

</div>

Hi Gopi,

Thanks for your input. I have two questions :  
1 - Once you have the correct values to use, how do you map it to the body of the request to be sent ?  
2 - How do you set this rule to the HTTP operation ? Are you using “beforeRule” or something else ?

Kind regards

---

<div class="post-metadata">

**Author:** ![Gopi2000](https://sea1.discourse-cdn.com/sailpoint/discuss/user_avatar/developer.sailpoint.com/gopi2000/32/21706_2.png) [@Gopi2000](https://developer.sailpoint.com/discuss/u/Gopi2000)\
**Post date:** [September 16, 2025, 9:53am UTC](https://developer.sailpoint.com/discuss/t/web-services-connector-add-entitlement-with-patch/180098/4 "2025-09-16T09:53:52Z")

</div>

Hi @davidtrn

1. `Object existingTeamIds = usersMap.get("team_ids");` – This piece of code is used to retrieve the existing team IDs. If that is not possible, we can use an API call to retrieve the existing values. After processing, we update the body using the code:  
`usersMap.put("team_ids", teamIds);`
2. I have attached this Before Operation Rule in the **Add Entitlement** operation.

---

<div class="post-metadata">

**Author:** ![davidtrn](https://sea1.discourse-cdn.com/sailpoint/discuss/user_avatar/developer.sailpoint.com/davidtrn/32/19752_2.png) [@davidtrn](https://developer.sailpoint.com/discuss/u/davidtrn)\
**Post date:** [September 16, 2025, 9:55am UTC](https://developer.sailpoint.com/discuss/t/web-services-connector-add-entitlement-with-patch/180098/5 "2025-09-16T09:55:01Z")

</div>

After adding logs to my rule :

```auto
Map body = requestEndPoint.getBody();
if (body == null) body = new HashMap();
String jsonBody = (String) body.get("jsonBody");

log.info(application.getName() + " Combine Roles: body: " + body);

```

The ccg logs :

> “message”:“STG - APP VA [source-1757425274935] **Combine** Roles: body: {jsonBody=null, bodyFormat=raw}”

Map body = requestEndPoint.getBody(); is returning an empty body even if I configured it as this :

 ![image](https://global.discourse-cdn.com/sailpoint/original/3X/f/c/fc939c67c6890a4076b79aa4be075733cdf923b1.png)

---

<div class="post-metadata">

**Author:** ![system](https://global.discourse-cdn.com/sailpoint/original/2X/f/f2136700ed5e3703e0b85e02f6be799dacca7735.png) [@system](https://developer.sailpoint.com/discuss/u/system)\
**Post date:** [November 15, 2025, 9:55am UTC](https://developer.sailpoint.com/discuss/t/web-services-connector-add-entitlement-with-patch/180098/6 "2025-11-15T09:55:34Z")

</div>

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