# SCIM Patch Operations SCIM Patch Operations aggregate a collection of operations on a target resource. SCIM Patching is described in [RFC7644 Section 3.5.2.](https://datatracker.ietf.org/doc/html/rfc7644#section-3.5.2) This guide covers basics and common use cases related to our Firstup users and user groups. ## Overview In context of the Firstup API, a SCIM patch is a way of editing a Firstup platform user or a Firstup user group. These users and user groups are created using SCIM, therefore editing them requires certain operations. ### Operation An operation is a way of adding, changing, replacing or removing data in a user's record or a user group, e.g. change a user's last name. To perform an operation, you send it as an object in a `PATCH` endpoint request connected to the relevant user or user group ID. Patch endpoint examples: PATCH /SCIM/v2/users/{userid} PATCH /SCIM/v2/Groups/{groupId} An operation object has three properties: | Property | Description | | --- | --- | | `op` | The type of operation being performed: `add`, `replace`, `remove`. | | `path` | The data that needs changing from the operation (e.g. `title`) | | `value` | What you want the data to be changed to (e.g. `mrs`) | Based on our example of replacing an existing user's title from Miss to Mrs, your patch operation request looks like: ``` { "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"], "Operations": [ { "op": "replace", "path": "title", "value": "Mrs" } ] } ``` **Note**: This example shows how to replacing a simple string (root-level property). Continue to read for information on replacing or adding objects, lists and lists of objects. ### Targeting Properties Unlike the above example, not all properties are at the root level. ``` const examplePaths = [ { "path": "title" }, // Root-level property { "path": "name:familyName" }, // Nested property { "path": "urn:SocialChorus:1.0:User:managerName" }, // User extension property ] ``` ## Patching Strings To add, replace or remove a string attribute, you must need to include an `op`, a `path` and a `value`. ### Replacing Strings A user's nickname is a string attribute that does not belong to a list or object. To change this: ``` { "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"], "Operations": [ { "op": "replace", "path": "nickName", "value": "Barry" } ] } ``` ### Adding strings To add a nickname to an existing user, change the `op` to `add`: ``` { "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"], "Operations": [ { "op": "add", "path": "nickName", "value": "Barry" } ] } ``` ### Remove Strings To remove a nickname from an existing user, change the `op` to `remove` and don't send a `value`: ``` { "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"], "Operations": [ { "op": "remove", "path": "nickName", } ] } ``` ### Strings Use Case Change UserName ## Patching Lists Targeting an attribute within a list (array) requires a filter: * The list (array) attribute name comes first `"listExample"` * The list attributes are then shown inside square brackets `"ListExample": ["item1", "item2"]` * The SCIM filter expressed supported is equals to, which means you type in the exact value you need. Example, `eq \"valuehere\"` - the `eq` is equals to, `valuehere` is where you type in your required value. Complex lists will then have a list of objects, like the `addresses` array. Objects appear in curly brackets `{objectExample}` ### Replacing a List Attribute Adding the filter after the list property name targets the list attribute. For example, replacing a misspelled street address within a user's full address. The list is `addresses` but the `stretAddress` is a propery within this list. Address list example: ``` "addresses": [ { "streetAddress": "123 Kission St", "locality": "San Francisco", "region": "CA", "postalCode": "94105", "country": "US", "primary": false, "formatted": "123 Mission St, San Francisco, CA, 94105", "type": "work" } ] ``` To only replace the streetAddress property your patch looks like: ``` { "op": "replace", "path": "address[streetAddress eq \"123 Kission St\"].streetAddress", "value": "123 Mission St" } ``` The `OP` (operation) is to change the `path` (the current data) to the entered `value` by yourself (the new data - here 123 Mission St). SCIM does not support position-based operations, meaning we can't target the "first" address, or re-order addresses from within SCIM itself. Those types of operations would need to be handled on the client side followed by a value replacement. ### Removing List Attributes To remove a list attribute, change the `op` from `replace` to `remove` and don't include any `value`: ``` { "op": "remove", "path": "address[streetAddress eq \"123 Mission St\"].streetAddress" } ``` ### Adding List Attributes To add a list to an existing user or user group, your `op` is `add`, your `path` is the blank data field that exists in the user or user group schema (e.g. `members`), and your `value` is your list (e.g. a list of members you want adding). For example, you want to add users to an existing user group: ``` { "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"], "Operations": [ { "op": "add", "path": "members", "value": [ { "value": "user1" }, { "value": "user2" }, { "value": "user3" }, { "value": "user4" }, { "value": "user5" } ] } ] } ``` ### List Use Case Change email ## Patching Objects For properties within objects (nested property), SCIM Paths use a colon as a path separator. This means if you have an item in an object you wish to change, add in a colon between the object name and the attribute within. * The object (nested) attribute name comes first `"objectExample"` * The nested object attributes are then shown inside curly brackets `"objectExample": {"item1", "item2"}` ### Replacing an Object Attribute To change a user's last name, you need to change the `familyName` property within the `name` object: ``` "name": { "givenName": "Jane", "familyName": "Doe" }, ``` This example means your `path` needs to include both the `name` and `familyName` attributes. This looks like: ``` { "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"], "Operations": [ { "op": "replace", "path": "name:familyName", "value": "NewLastName" } ] } ``` ### Removing an Object Attribute To remove an object attribute, using the same example, change the `op` from `replace` to `remove` and don't send a `value`: ``` { "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"], "Operations": [ { "op": "remove", "path": "name:familyName" } ] } ``` ### Adding an Object Adding an object requires you to add in the object as the `path`, and then list out any attributes in the `value`. For example: ``` { "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"], "Operations": [ { "op": "add", "path": "emails", "value": [ { "value": "janedoe@email.com", "primary": true, "type": "work" } ] } ] } ``` ### Object Use Case Change role ## Pathless Targeting Including a `path` property is optional when replacing properties. If the optional path property is omitted it is assumed the target is the entire resource, e.g., a SCIM User or Group. In this case the value property's own property names will align with the resource. For example, replace a user's `userName` with a `path`: ``` { "op": "replace", "path": "displayName", "value": "User McUser" } ``` Or without a `path`: ``` { "op": "replace", "value": { "displayName": "User McUser" } } ``` **Note:** Pathless replace replaces the entire object. It is not a merge. Remove operations require a path. Removes are value-less operations. ## Use Cases Here a list of use cases where we're using a patch operation to change specific user details: * [Change user's name](/usermanagementapi/user-managing#change-user-names) * [Change user's email address ](/usermanagementapi/user-managing#change-users-email-address)