# SCIM (User) API V3 — Developer Guide

- **Applies to:** Sprinklr SCIM User API V3 (`/api/v3/scim/Users`)
- **V2 API reference:** [SCIM (User) APIs | Sprinklr Developer Portal](https://dev.sprinklr.com/scim-user-apis)


## 1. Overview

**SCIM**, acronym for **System for Cross-domain Identity Management**, is an open standard for managing user identity information. The goal of the SCIM APIs is to help provision users access to the Sprinklr platform to enable them to access the application. You can perform the basic CRUD operations using these APIs, such as adding a user, fetching user details, updating a user, or deleting/disabling a user. The APIs adhere to the SCIM protocol and ensure consistency, security, and compliance towards the industry standards.

The **user email (`userName`) is the unique identifier** when creating a user.

SCIM V3 exposes the standard SCIM resource surface at `/api/v3/scim/Users`, differentiated by HTTP method:

| Operation | Method | Path |
|  --- | --- | --- |
| Create user | `POST` | `/api/v3/scim/Users` |
| List or search users | `GET` | `/api/v3/scim/Users?startIndex=&count=&filter=&sortBy=&sortOrder=` |
| Read user by id | `GET` | `/api/v3/scim/Users/{userId}` |
| Replace user | `PUT` | `/api/v3/scim/Users/{userId}` |
| Patch user | `PATCH` | `/api/v3/scim/Users/{userId}` |
| Delete user | `DELETE` | `/api/v3/scim/Users/{userId}` |


### Addressing a user

A user is addressed by **`userId`** — the unique identifier for the user on the Sprinklr platform, typed `integer/int64` — in the path: `/api/v3/scim/Users/66078077`.

To obtain a `userId`, use search by entity, the read-user-by-username API, or the bootstrap API.

**Steps to extract the user id from the UI:**

1. Click the hamburger menu in the top left corner of the Sprinklr platform's homepage.
2. Navigate to **All Settings** options.
3. Click the **Users** icon within the **Manage Workspace** module.
4. Search for the user you want the details for.
5. Click the **Details** icon placed beside the three dots.
6. The user id is part of the web URL — for example `https://space.sprinklr.com/social/governance/users/1000211373/overview`, so the user id is `1000211373`.


## 2. Base URLs and environments

**All API calls are sent to the production endpoint:**

```
https://api3.sprinklr.com/{env}/api/v3
```

So the SCIM user resource is:

```
https://api3.sprinklr.com/{env}/api/v3/scim/Users
```

Replace `{env}` with your assigned environment identifier (`prod0`, `prod2`, `prod11`, and so on — see [APIs | Sprinklr Developer Portal](https://dev.sprinklr.com/apis) for the environment list).

## 3. Authentication and common headers

All SCIM API calls are authenticated with OAuth 2.0. See [Developer Tools in Sprinklr](https://www.sprinklr.com/help/articles/developer-tools/developer-tools-in-sprinklr/692e8b39f0afa271d18a5929) for API key and secret generation, and the Authorize flow on the developer portal.

| Header | Value | Description | Required on |
|  --- | --- | --- | --- |
| `Authorization` | `******` | Credential used by the API to authenticate a user with the server. For generating the authorization token, refer to the Authorize section on the developer portal. | All requests |
| `key` | `api-key` | API key helps authenticate the application with the server. For generating an API key, refer to the Getting Started guide. | All requests |
| `Content-Type` | `application/scim+json` | Representation header that determines the type of data (media/resource) present in the request body | All requests |


> **`Content-Type` is `application/scim+json`, not `application/json`.** This is the SCIM media type and is used on every SCIM operation — including `GET` and `DELETE` in the supplied Postman collection.


**Permissions:** to create a user you must be an admin of the Customer or Workspace environment in which you want to create the user. You cannot create a user with a higher user level permission than yourself.

## 4. Write operations

### 4.1 Create a user

**`POST /api/v3/scim/Users`**

Creates/adds a user within the Sprinklr platform. The `userName` — the user email — is the unique identifier; it must be unique every time you call the create user API.

#### Request body — `User`

| Parameter | Sub-parameter | Required | Type | Description |
|  --- | --- | --- | --- | --- |
| `userName` |  | **Required** | String | The email id of the user. The email of the user needs to be unique every time you hit the create user API. |
| `name` |  | **Required** | Object | Object that specifies the `familyName` and `givenName` |
|  | `familyName` | Required | String | Last name of the user |
|  | `givenName` | Required | String | First name of the user |
| `photos` |  | Optional | Array | Array of photos, but Sprinklr will use the first one only |
|  | `value` | Optional | URL | URL for the photo |
| `active` |  | Optional | Boolean | If `true`, the user will be set to active state. Per the V3 schema, by default a user is created in an **inactive** state. |
| `isSpaceUser` |  | Optional | Boolean | If `true`, the user can access Space UI only |
| `locale` |  | Optional | String | Language code of the user. See [§8.2](#82-commonly-used-locale-codes). |
| `globalAttributes` |  | Optional | Object | Partner-level attributes of the user, which cannot be mapped to SCIM attributes. See [§4.1.1](#411-globalattributes). |
| `clientAttributes` |  | **Required** | Array | Client (workspace) level attributes of the user. See [§4.1.2](#412-clientattributes). |
| `emails` |  | Optional | Array | List of user emails, each `{"value": …, "primary": …}` |
| `phoneNumbers` |  | Optional | Array | Phone numbers at the user level |
| `supervisorTeamIds` |  | Optional | Array[String] | List of team IDs where the user acts as a supervisor |
| `recordingShareConfigs` |  | Optional | Array[Object] | Configuration for sharing recordings with other users |
|  | `type` | Required | String | Sharing type, for example `USER`, `TEAM` |
|  | `ids` | Required | Array[Integer] | IDs of the users or teams with whom recordings are shared |
| `userSeats` |  | Optional | Array | User seats |
| `schemas` |  | Optional | Array[String] | SCIM schema URIs. See [§8.3](#83-scim-schema-uris). |


#### 4.1.1 `globalAttributes`

| Parameter | Required | Type | Description |
|  --- | --- | --- | --- |
| `partnerCustomProperties` | Optional | Object | Global-level custom properties, keyed by custom field id, each holding a **list** of values |
| `productSeat` | Optional | String | Product seat you want to assign to the user. Supported: **Modern Engagement, Modern Marketing, Modern Care, Modern Marketing Lite, Distributed**. By default the user falls under the **Modern Engagement** product seat. |
| `federationId` | Optional | String | Assigning a Federation ID helps with unique identification. You cannot assign the same federation identity to more than one user. The federation ID is additionally used by Customer Environments for attaching extra SSO login information. |
| `passwordLoginDisabled` | Optional | Boolean | Default `false`. In the case of an SSO user this needs to be `true` along with `federationId`. |


#### 4.1.2 `clientAttributes`

| Parameter | Sub-parameter | Required | Type | Description |
|  --- | --- | --- | --- | --- |
| `clientId` |  | **Required** | Integer | Workspace id where you want to add the user |
| `userType` |  | **Required** | String | Type of user you want to create. Supported: `PARTNER_ADMIN`, `PARTNER_USER`, `CLIENT_ADMIN`, `CLIENT_USER`. See [§8.1](#81-supported-user-types). |
| `phoneNumbers` |  | Optional | Array | Array containing phone details |
|  | `value` | Optional | String | Phone number of the user |
|  | `type` | Optional | String | Type of phone number — whether it is for work or personal |
|  | `primary` | Optional | Boolean | If `true`, the phone number is primary to the user |
| `clientCustomProperties` |  | Optional | Object | Workspace-level custom properties |
| `businessCategory` |  | Optional | String | Category of business. Either `CORPORATE` or `DISTRIBUTED`. |
| `designation` |  | Optional | String | Designation of the user |
| `department` |  | Optional | String | Department of the user |
| `managerId` |  | Optional | Integer | User ID of the user's manager |
| `persona` |  | Optional | String | Persona assigned to the user, for example ML Annotator |
| `personaViewEnabled` |  | Optional | Boolean | Whether persona-based view is enabled for the user |
| `personaApp` |  | Optional | String | Name of the application linked to the user's persona |
| `userGroupIds` |  | Optional | List[String] | User group ids where you want to add the user |
| `primaryUserGroupId` |  | Optional | String | Primary user group id where you want to add the user |
| `sessionTimeout` |  | Optional | Integer | Session timeout value in minutes |
| `customProfileConfigs` |  | Optional | Array[Object] | Custom profile configurations for specific channels. See [§4.1.3](#413-customprofileconfigs). |


> **Dev note:** to create a Distributed User, use `"businessCategory": "DISTRIBUTED"` and `"isSpaceUser": false`.


#### 4.1.3 `customProfileConfigs`

| Parameter | Type | Required | Description |
|  --- | --- | --- | --- |
| `customProfileEnabled` | Boolean | Required | Whether a custom profile is enabled for the user |
| `userId` | Integer | Required | Unique identifier of the user this profile configuration applies to |
| `channelType` | String | Required | Channel for which the custom profile is configured, for example `SPRINKLR_LIVE_CHAT` |
| `sprCustomProfileConfigs` | Array[Object] | Optional | The actual profile settings to be applied for the specified channel |
| `shouldUseDefaultProfile` | Boolean | Optional | If `true`, the system uses the default profile settings in the absence of a matching custom profile |


`sprCustomProfileConfigs` object:

| Parameter | Type | Required | Description |
|  --- | --- | --- | --- |
| `url` | String | Required | URL to the image or avatar used in the custom profile |
| `name` | String | Required | Name associated with the custom profile |
| `enabled` | Boolean | Required | Whether this specific profile is active/enabled |
| `userId` | Integer | Required | User ID to which the profile is linked (typically the same as the parent `userId`) |
| `channelType` | String | Required | The channel for which this profile configuration is valid |
| `accountId` | Integer | Optional | Account ID related to the specific custom profile. Use `-1` for a default or global profile. |


#### Request

```bash
curl -X POST \
  'https://api3.sprinklr.com/{env}/api/v3/scim/Users' \
  -H 'Authorization: ******' \
  -H 'Content-Type: application/scim+json' \
  -H 'key: {apikey}' \
  -d '{
    "userName": "mannam.akhilasree+v32@sprinklr.com",
    "name": {
        "familyName": "Test",
        "givenName": "UserV3"
    },
    "locale": "EN_US",
    "globalAttributes": {
        "partnerCustomProperties": {
            "58f7681be4b027b9a722d5c5": [
                "pp"
            ],
            "5b1006f1e4b0a54914f86e45": [
                "Yes"
            ]
        },
        "federationId": "",
        "passwordLoginDisabled": false
    },
    "clientAttributes": [
        {
            "clientId": 66000002,
            "userType": "CLIENT_ADMIN",
            "phoneNumbers": [
                {
                    "value": "+919123456789"
                }
            ],
            "businessCategory": "CORPORATE",
            "clientCustomProperties": {
                "580745abe4b027d61cf738d8": [
                    "5"
                ]
            },
            "designation": "test",
            "department": "test"
        }
    ]
}'
```

Custom properties — both `partnerCustomProperties` and `clientCustomProperties` — are keyed by custom field id and always take a **list** of values, even for single-valued fields.

#### Response

`200 Success`, body `User`.

**Response** *(illustrative example, generated from the documented schema)*

```json
{
    "schemas": [
        "urn:ietf:params:scim:schemas:core:2.0:User",
        "urn:scim:schemas:extension:sprinklrGlobalAttributes:2.0:User",
        "urn:scim:schemas:extension:sprinklrClientAttributes:2.0:User",
        "urn:scim:schemas:extension:sprinklrUserAssignmentConfig:2.0:User",
        "urn:scim:schemas:extension:sprinklrUserVoiceConfig:2.0:User",
        "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User"
    ],
    "id": "66078077",
    "userName": "mannam.akhilasree+v32@sprinklr.com",
    "name": {
        "familyName": "Test",
        "givenName": "UserV3"
    },
    "photos": [],
    "active": true,
    "locale": "EN_US",
    "globalAttributes": {
        "partnerCustomProperties": {},
        "passwordLoginDisabled": false
    },
    "clientAttributes": [
        {
            "clientId": 66000002,
            "userType": "CLIENT_ADMIN",
            "phoneNumbers": [
                {
                    "value": "+919123456789"
                }
            ],
            "businessCategory": "CORPORATE",
            "clientCustomProperties": {},
            "designation": "test",
            "department": "test"
        }
    ],
    "meta": {
        "resourceType": "User",
        "location": "/api/v3/scim/Users66078077"
    },
    "emails": [
        {
            "value": "mannam.akhilasree+v32@sprinklr.com",
            "primary": true
        }
    ]
}
```

Capture the returned `id` — that is the `userId` for every later call.

### 4.2 Replace a user — full update

**`PUT /api/v3/scim/Users/{userId}`**

Replaces the user record with the supplied document.

#### Path parameters

| Parameter | Required | Type | Description |
|  --- | --- | --- | --- |
| `userId` | **Required** | Integer (`int64`) | Unique identifier for the user whose details need to be updated. Use search by entity, the read-user-by-username API, or the bootstrap API to fetch the user id. See [§1.2](#12-addressing-a-user). |


#### Request body — `User`

Same schema as [§4.1](#41-create-a-user). Send the complete document, including `id`, `schemas`, `meta`, and `emails`.

#### Request

```bash
curl -X PUT \
  'https://api3.sprinklr.com/{env}/api/v3/scim/Users/66078077' \
  -H 'Authorization: ******' \
  -H 'Content-Type: application/scim+json' \
  -H 'key: {apikey}' \
  -d '{
    "schemas": [
        "urn:ietf:params:scim:schemas:core:2.0:User",
        "urn:scim:schemas:extension:sprinklrGlobalAttributes:2.0:User",
        "urn:scim:schemas:extension:sprinklrClientAttributes:2.0:User",
        "urn:scim:schemas:extension:sprinklrUserAssignmentConfig:2.0:User",
        "urn:scim:schemas:extension:sprinklrUserVoiceConfig:2.0:User",
        "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User"
    ],
    "id": "66078077",
    "userName": "mannam.akhilasree+v32@sprinklr.com",
    "name": {
        "familyName": "Testt",
        "givenName": "UserV3"
    },
    "photos": [],
    "locale": "EN_US",
    "globalAttributes": {
        "partnerCustomProperties": {},
        "federationId": "",
        "passwordLoginDisabled": false
    },
    "clientAttributes": [
        {
            "clientId": 66000002,
            "userType": "CLIENT_ADMIN",
            "phoneNumbers": [
                {
                    "value": "+919123456789"
                }
            ],
            "businessCategory": "CORPORATE",
            "clientCustomProperties": {},
            "designation": "test",
            "department": "test",
            "customProfileConfigs": []
        }
    ],
    "meta": {
        "resourceType": "User",
        "location": "/api/v3/scim/Users66078077"
    },
    "emails": [
        {
            "value": "mannam.akhilasree+v32@sprinklr.com",
            "primary": true
        }
    ],
    "recordingShareConfigs": []
}'
```

#### Response

`200 Success`, body `User`.

#### ⚠️ `PUT` replaces — it does not merge

The sample above illustrates the risk directly. It sends `"partnerCustomProperties": {}`, `"clientCustomProperties": {}`, `"photos": []`, `"customProfileConfigs": []`, and `"recordingShareConfigs": []`. Under replace semantics that clears every global and workspace custom property, the profile photo, all custom profile configs, and all recording share configs on that user.

Before issuing a `PUT`:

1. `GET /api/v3/scim/Users/{userId}` to retrieve the current document.
2. Merge your changes into the retrieved document.
3. `PUT` the merged result back.


If you only intend to change a few attributes, use `PATCH` ([§4.3](#43-patch-a-user--partial-update)) instead. `PATCH` exists precisely so you do not have to do a read-modify-write cycle.

### 4.3 Patch a user — partial update

**`PATCH /api/v3/scim/Users/{userId}`**

Updates specific attributes of an existing user without replacing the entire user record. The API follows the **SCIM 2.0 PATCH standard** and supports operations such as `add` and `replace` for user attributes like name, active status, locale, emails, client attributes, and custom properties.

#### Path parameters

| Parameter | Required | Type | Description |
|  --- | --- | --- | --- |
| `userId` | **Required** | Integer (`int64`) | Unique identifier for the user whose details need to be updated |


#### Request body — `ScimPatchOp`

The request uses the SCIM `Operations` object. Each operation contains an `op` (operation type) and `value` (fields to update).

| Parameter | Sub-parameter | Required | Type | Description |
|  --- | --- | --- | --- | --- |
| `Operations` |  | **Required** | Object | Defines the modification to be performed on the user resource |
|  | `op` | Required | String | The type of operation to perform. Supported values: `add`, `replace`. |
|  | `path` | Required | String | The user attribute you want to update. You can use dot notation for nested attributes, for example `name.givenName`. |
|  | `value` | Required | Object | Fields to update |


The `value` object accepts the same attributes as the create body — `userName`, `name` (`familyName`, `givenName`), `photos`, `active`, `isSpaceUser`, `locale`, `globalAttributes`, `clientAttributes`, `supervisorTeamIds`, `recordingShareConfigs` — as described in [§4.1](#41-create-a-user).

> **Dev note — `add` versus `replace`:**
- **`add`** — inserts a new attribute or appends a value to an existing multi-valued attribute. If the attribute already exists and supports multiple values (for example, `emails`), the new value is added alongside the existing ones.
- **`replace`** — updates an attribute by overwriting the existing value. If the attribute already has a value, it will be replaced entirely with the new one.

Use `add` when you want to keep existing values and extend them, and `replace` when you want to fully overwrite the existing attribute value.


#### Request

```bash
curl -X PATCH \
  'https://api3.sprinklr.com/{env}/api/v3/scim/Users/66078077' \
  -H 'Authorization: ******' \
  -H 'Content-Type: application/scim+json' \
  -H 'key: {apikey}' \
  -d '{
   "Operations": {
       "op": "add",
       "value": {
           "locale": "EN_GB",
           "active": true,
           "name": {
               "familyName": "Deepak",
               "givenName": "Bala Scim 7"
           }
       }
   }
}'
```

#### Response

`200 Success`, body `User`.

### 4.4 Delete a user

**`DELETE /api/v3/scim/Users/{userId}`**

Deletes/disables the user.

#### Path parameters

| Parameter | Required | Type | Description |
|  --- | --- | --- | --- |
| `userId` | **Required** | Integer (`int64`) | Unique identifier for the user to delete |


#### Request

```bash
curl -X DELETE \
  'https://api3.sprinklr.com/{env}/api/v3/scim/Users/66078093' \
  -H 'Authorization: ******' \
  -H 'Content-Type: application/scim+json' \
  -H 'key: {apikey}'
```

#### Response

`200 Success`, body type `string` per the specification — not a `User` object.

### 4.5 Method comparison — when to use which

|  | `POST` | `PUT` | `PATCH` | `DELETE` |
|  --- | --- | --- | --- | --- |
| Purpose | Create a user | Replace the full user record | Change selected attributes | Delete/disable a user |
| Addressing | None — `userName` in the body | `/{userId}` | `/{userId}` | `/{userId}` |
| Body schema | `User` | `User` | `ScimPatchOp` | None |
| Unspecified fields | N/A | **Replaced/cleared** | **Preserved** | N/A |
| Response body | `User` | `User` | `User` | `string` |
| Safe for incremental sync | — | No, without read-modify-write | Yes | — |


`PUT` and `PATCH` take **different body schemas** — `User` versus `ScimPatchOp`. You cannot reuse one payload for both methods.

## 5. Read operations

### 5.1 `GET /api/v3/scim/Users/{userId}` — Read a user

Fetches a user for the given user id (unique identifier for the user existing on the Sprinklr platform).

#### Path parameters

| Parameter | Required | Type | Description |
|  --- | --- | --- | --- |
| `userId` | **Required** | Integer (`int64`) | Unique identifier for the user whose details need to be fetched. Use search by entity, the read-user-by-username API, or the bootstrap API to fetch the user id. |


#### Request

```bash
curl -X GET \
  'https://api3.sprinklr.com/{env}/api/v3/scim/Users/66016584' \
  -H 'Authorization: ******' \
  -H 'Content-Type: application/scim+json' \
  -H 'key: {apikey}'
```

#### Response

`200 Success`, body `User`.

**Response** *(illustrative example, generated from the documented schema)*

```json
{
    "schemas": [
        "urn:ietf:params:scim:schemas:core:2.0:User",
        "urn:scim:schemas:extension:sprinklrGlobalAttributes:2.0:User",
        "urn:scim:schemas:extension:sprinklrClientAttributes:2.0:User",
        "urn:scim:schemas:extension:sprinklrUserAssignmentConfig:2.0:User",
        "urn:scim:schemas:extension:sprinklrUserVoiceConfig:2.0:User"
    ],
    "id": "66016584",
    "userName": "testuser@sprinklr.com",
    "name": {
        "familyName": "Test",
        "givenName": "User"
    },
    "photos": [
        {
            "value": "https://sprcdn-assets.sprinklr.com/787/profile-15ea76bd-9f28-47a3-83e7-dff01011834e-176564324.png"
        }
    ],
    "active": true,
    "locale": "EN_US",
    "globalAttributes": {
        "partnerCustomProperties": {},
        "passwordLoginDisabled": false
    },
    "clientAttributes": [
        {
            "clientId": 66000002,
            "userType": "CLIENT_USER",
            "phoneNumbers": [
                {
                    "value": "+919123456789"
                }
            ],
            "businessCategory": "CORPORATE",
            "designation": "test",
            "department": "test"
        }
    ],
    "meta": {
        "resourceType": "User",
        "createdTime": "2024-05-28 08:03:01",
        "lastModified": "2024-05-28 08:03:05"
    },
    "emails": [
        {
            "value": "testuser@sprinklr.com",
            "primary": true
        }
    ]
}
```

> **Dev note:** when making a request to retrieve user information, if the specified user is not found in the database, the API returns a **`404`** error.


### 5.2 `GET /api/v3/scim/Users` — List or search users

Search users by passing filters and sorting details.

#### Query parameters

| Parameter | Required | Type | Description |
|  --- | --- | --- | --- |
| `startIndex` | Optional | Integer (`int32`) | 1-based index of the first result — the row from which you want to fetch the results. For example, if there are 10 results and you specify `startIndex` as 2, the API returns 9 users. **Default: 1.** A non-positive value of `startIndex` also defaults to 1. |
| `count` | Optional | Integer (`int32`) | Maximum results per page — the number of results you want to fetch in the response. **Default: 100.** A non-positive value of `count` results in an empty response. |
| `sortBy` | Optional | String | Field you want to sort the results with. Supported values: `id`, `name`, `meta.createdTime`, `meta.lastModified`. |
| `sortOrder` | Optional | String (`ScimSortDirection`) | Order in which you want the results. Supported values: `ascending`, `descending`. **Default: `ascending`.** |
| `filter` | Optional | String | SCIM filter expression. Filters can only be combined by the **`and`** operator — any other operator throws an error. Filters supporting `eq` can carry multiple `eq` statements, for example `id eq "a" and id eq "b" and id eq "c"`. See the supported filter table below. |


#### Supported filter types and operations

| Filter type | Description | Supported operations | Type |
|  --- | --- | --- | --- |
| `id` | The user id associated with the user | `eq` (equal to), `le`, `ge` | Integer |
| `userName` | The name of the user | `eq` (equal to) | String |
| `meta.lastModified` | The last time the user was modified. Format: `yyyy-MM-ddTHH:mm:ssZ` | `eq` (equal to), `le`, `ge` | String |


> The V2 reference glosses `le` as "larger than" and `ge` as "greater than" in its operations column. In SCIM (RFC 7644) `le` is *less than or equal* and `ge` is *greater than or equal*, which is what the documented example `meta.lastModified le "2023-07-05T06:16:48Z" and meta.lastModified ge "2023-05-05T06:16:48Z"` (a bounded date range) implies. Verify the direction before relying on it — see [§10](#10-questions-for-the-api-owner).


#### Filter syntax examples

| Intent | Filter |
|  --- | --- |
| With `id` and `meta.lastModified` | `id le "1000052905" and meta.lastModified le "2023-07-05T06:16:48Z"` |
| With multiple user ids | `id eq "1" and id eq "2" and id eq "3"` |
| With a modified-time range | `meta.lastModified le "2023-07-05T06:16:48Z" and meta.lastModified ge "2023-05-05T06:16:48Z"` |


#### Request

```bash
curl -X GET \
  'https://api3.sprinklr.com/{env}/api/v3/scim/Users?startIndex=1&count=2&sortBy=id&sortOrder=descending&filter=id eq "66016584" and meta.lastModified le "2026-07-05T06:16:48Z"' \
  -H 'Authorization: ******' \
  -H 'Content-Type: application/scim+json' \
  -H 'key: {apikey}'
```

URL-encode the `filter` value; it contains spaces and double quotes.

#### Response

`200 Success`, body `ScimListResult`. `sprinklr-v3.yaml` declares `ScimListResult` as an untyped object (`DTO (com.spr.rest.http.v301.beans.scim.ScimListResult)`) with no properties, so the field-level shape below is taken from the V2 SCIM search response.

| Field | Type | Description |
|  --- | --- | --- |
| `schemes` | Array[String] | SCIM list-response schema URI — `urn:ietf:params:scim:api:messages:2.0:ListResponse` |
| `Resources` | Array[User] | The matching user objects |
| `totalResults` | Integer | Total number of users matching the filter |
| `startIndex` | Integer | 1-based index of the first returned result |
| `itemsPerPage` | Integer | Number of results in this page |


**Response** *(illustrative example, generated from the documented schema)*

```json
{
    "schemes": [
        "urn:ietf:params:scim:api:messages:2.0:ListResponse"
    ],
    "Resources": [
        {
            "schemas": [
                "urn:ietf:params:scim:schemas:core:2.0:User",
                "urn:scim:schemas:extension:sprinklrGlobalAttributes:2.0:User",
                "urn:scim:schemas:extension:sprinklrClientAttributes:2.0:User",
                "urn:scim:schemas:extension:sprinklrUserAssignmentConfig:2.0:User",
                "urn:scim:schemas:extension:sprinklrUserVoiceConfig:2.0:User"
            ],
            "id": "66016584",
            "userName": "testuser@sprinklr.com",
            "name": {
                "familyName": "Test",
                "givenName": "User"
            },
            "active": true,
            "locale": "EN_US",
            "globalAttributes": {
                "federationId": "febId12",
                "passwordLoginDisabled": false
            },
            "clientAttributes": [
                {
                    "clientId": 66000002,
                    "userType": "PARTNER_USER",
                    "phoneNumbers": [
                        {
                            "value": "+919123456789"
                        }
                    ],
                    "businessCategory": "CORPORATE",
                    "primaryUserGroupId": "621883eb0ba544387d2d5b24",
                    "userGroupIds": [
                        "642185c6f63bee0f15b3333f"
                    ],
                    "designation": "Test update desg"
                }
            ],
            "meta": {
                "resourceType": "User",
                "createdTime": "2019-04-09 10:43:38.0",
                "lastModified": "2023-07-18 08:16:33"
            },
            "emails": [
                {
                    "value": "testuser@sprinklr.com",
                    "primary": true
                }
            ]
        }
    ],
    "totalResults": 4114,
    "startIndex": 1,
    "itemsPerPage": 2
}
```

> Note the response key is **`schemes`** (list level) while each resource carries **`schemas`**. That spelling asymmetry appears in the V2 responses; preserve it in your parser rather than normalizing.


## 6. Response format and status codes

### 6.1 Response bodies

SCIM operations return **SCIM-shaped documents**, not the standard V3 `data`/`errors`/`metadata` envelope used by most other V3 APIs.

| Operation | Declared `200` schema |
|  --- | --- |
| `POST /scim/Users` | `User` |
| `GET /scim/Users` | `ScimListResult` |
| `GET /scim/Users/{userId}` | `User` |
| `PUT /scim/Users/{userId}` | `User` |
| `PATCH /scim/Users/{userId}` | `User` |
| `DELETE /scim/Users/{userId}` | `string` |


### 6.2 Response codes

Declared on every SCIM user operation:

| HTTP Code | Scenario | Description |
|  --- | --- | --- |
| `200 OK` | Success | Operation completed successfully |
| `400 Bad Request` | Invalid parameters | Malformed filter, invalid operator, or missing required attributes |
| `401 Unauthorized` | Authentication failed | Invalid or missing `Authorization` token |
| `403 Forbidden` | Insufficient permissions | Caller is not an admin of the target environment, or is attempting to create a user with higher permissions than their own |
| `404 Not Found` | User not found | The specified user does not exist in the database |


`500 Internal Server Error` is not declared on these operations; handle it defensively regardless.

## 7. V2 → V3 migration

**Endpoint mapping**

| V2 | V3 |
|  --- | --- |
| [Create User (SCIM)](https://dev.sprinklr.com/create-user-scim) — `POST /api/v2/scim/Users` | `POST /api/v3/scim/Users` |
| [Read User (SCIM)](https://dev.sprinklr.com/read-user-scim) — `GET /api/v2/scim/Users/{userId}` | `GET /api/v3/scim/Users/{userId}` |
| [Update User (SCIM)](https://dev.sprinklr.com/scim-user-apis) — `PUT /api/v2/scim/Users/{userId}` | `PUT /api/v3/scim/Users/{userId}` |
| [Partial Update User (SCIM)](https://dev.sprinklr.com/partial-update-user-scim) — `PATCH /api/v2/scim/Users/{userId}` | `PATCH /api/v3/scim/Users/{userId}` |
| [Delete User (SCIM)](https://dev.sprinklr.com/scim-user-apis) — `DELETE /api/v2/scim/Users/{userId}` | `DELETE /api/v3/scim/Users/{userId}` |


**This is a version-prefix migration, not a redesign.** Paths, methods, path parameters, query parameters, filter grammar, request bodies, and response shapes are unchanged between `/api/v2/scim/Users` and `/api/v3/scim/Users` across all six operations.

## 8. Supported enums and reference tables

### 8.1 Supported user types

| User type | Description |
|  --- | --- |
| `PARTNER_ADMIN` | Highest level of access; visibility across the entire brand, can manage users, accounts, workflow structures, and client (local division) accesses and structures |
| `PARTNER_USER` | Second highest level of access; visibility across the entire brand but cannot manage client (local division) accesses |
| `CLIENT_ADMIN` | Highest level of access within a Client environment; can manage users, accounts, and workflow structures within their local Client |
| `CLIENT_USER` | Lowest level of access/permissions; cannot manage users or accounts, and cannot manage workflow structures within any local Client environment |


Within a client environment, Client-level roles/permissions override Partner-level.

### 8.2 Commonly used `locale` codes

| Language | Code |
|  --- | --- |
| English (US) | `EN_US` |
| Deutsch (German) | `de_DE` |
| Español (Spanish) | `es_ES` |
| Français (France) | `fr_FR` |
| Italiano (Italian) | `it_IT` |
| Português (Brasil) | `pt_BR` |
| Русский (Russian) | `ru_RU` |
| Arabic | `ar_SA` |
| Chinese | `zh_CN` |


The supplied V3 `PATCH` sample also uses `EN_GB`.

### 8.3 SCIM schema URIs

| URI | Covers |
|  --- | --- |
| `urn:ietf:params:scim:schemas:core:2.0:User` | Core SCIM user attributes |
| `urn:scim:schemas:extension:sprinklrGlobalAttributes:2.0:User` | `globalAttributes` |
| `urn:scim:schemas:extension:sprinklrClientAttributes:2.0:User` | `clientAttributes` |
| `urn:scim:schemas:extension:sprinklrUserAssignmentConfig:2.0:User` | `userAssignmentConfig` |
| `urn:scim:schemas:extension:sprinklrUserVoiceConfig:2.0:User` | `userVoiceConfig` |
| `urn:ietf:params:scim:schemas:extension:enterprise:2.0:User` | `enterpriseUser` |
| `urn:ietf:params:scim:api:messages:2.0:ListResponse` | Search/list response envelope |


### 8.4 Other enums

| Field | Allowed values |
|  --- | --- |
| `businessCategory` | `CORPORATE`, `DISTRIBUTED` |
| `globalAttributes.productSeat` | Modern Engagement *(default)*, Modern Marketing, Modern Care, Modern Marketing Lite, Distributed |
| `Operations.op` | `add`, `replace` |
| `sortOrder` | `ascending`, `descending` |
| `sortBy` | `id`, `name`, `meta.createdTime`, `meta.lastModified` |
| `recordingShareConfigs[].type` | `USER`, `TEAM` |


## 9. Use cases

### 9.1 Provision a new workspace admin

**Scenario:** onboard a teammate into one workspace with a phone number and custom properties.

`POST /api/v3/scim/Users` with `userName` (their email), `name`, `locale`, and a single `clientAttributes` entry carrying `clientId`, `userType: "CLIENT_ADMIN"`, and `businessCategory: "CORPORATE"` — as in [§4.1](#41-create-a-user). Capture the returned `id`.

Remember: the V3 `User` schema states that by default a user is created in an **inactive** state. Send `"active": true` if the user should be able to log in immediately.

### 9.2 Provision a user into multiple workspaces

`clientAttributes` is an array. Send one entry per workspace in a single create call rather than creating the user twice:

```json
{
  "userName": "ben.turner+scimapi@sprinklr.com",
  "name": { "familyName": "Turner", "givenName": "Ben" },
  "clientAttributes": [
    { "clientId": 1000004509, "userType": "CLIENT_ADMIN", "businessCategory": "CORPORATE" },
    { "clientId": 1000004510, "userType": "CLIENT_ADMIN", "businessCategory": "CORPORATE" }
  ]
}
```

### 9.3 Create a Distributed user

Set `"businessCategory": "DISTRIBUTED"` inside `clientAttributes` and `"isSpaceUser": false` at the top level.

### 9.4 Configure an SSO user

Set `globalAttributes.federationId` to the user's federation identity **and** `globalAttributes.passwordLoginDisabled` to `true`. Neither works alone: `passwordLoginDisabled` defaults to `false`, and a federation identity cannot be assigned to more than one user.

### 9.5 Deactivate a user without deleting the record

`PATCH` with a `replace` operation rather than `DELETE`:

```json
{ "Operations": { "op": "replace", "value": { "active": false } } }
```

This preserves the record, its custom properties, and its group memberships — where `DELETE` returns a bare `string` and has undocumented cascade behavior ([§4.4](#44-delete-a-user)).

### 9.6 Append an email without dropping the existing one

Use `op: "add"` — it appends to multi-valued attributes. Using `op: "replace"` on `emails` overwrites the entire list.

### 9.7 Incremental identity-provider sync

**Scenario:** your IdP pushes only changed attributes each cycle.

Use `PATCH` per user with `op: "replace"` for single-valued attributes (`locale`, `active`, `name`) and `op: "add"` for multi-valued ones. Do not use `PUT` — a partial `PUT` body clears every attribute you omit ([§4.2](#42-replace-a-user--full-update)).

### 9.8 Reconcile users changed since the last run

Filter on `meta.lastModified` and page through the results:

```
GET /api/v3/scim/Users?startIndex=1&count=100&sortBy=meta.lastModified&sortOrder=ascending&filter=meta.lastModified ge "2026-07-05T06:16:48Z"
```

Read `totalResults` from the response and advance `startIndex` by `count` until `startIndex > totalResults`.

### 9.9 Fetch a specific set of users in one call

`filter` supports repeated `eq` clauses joined by `and`:

```
GET /api/v3/scim/Users?startIndex=1&count=3&sortBy=id&sortOrder=descending&filter=id eq "1" and id eq "2" and id eq "3"
```

This is the SCIM equivalent of a bulk fetch — cheaper than three `GET /scim/Users/{userId}` round trips.

### 9.10 Page through a large result set

```javascript
let startIndex = 1;
const count = 100;                    // default is also 100
let all = [];

while (true) {
  const res = await get(
    `/api/v3/scim/Users?startIndex=${startIndex}&count=${count}` +
    `&sortBy=id&sortOrder=ascending`
  );

  all = all.concat(res.Resources);

  if (startIndex + res.itemsPerPage > res.totalResults) break;
  startIndex += count;                // startIndex is 1-based, not 0-based
}
```

### 9.11 Bulk-provision at onboarding scale

For a one-time or high-volume import, do not loop `POST /api/v3/scim/Users`. Use `POST /api/v3/scim/bulk-upsert` with a `BatchUserImportDTO` body; it returns a `BulkAPIResponse`. Where you are keyed on email rather than user id, `POST /api/v3/scim/upsert` creates or updates in one call.