- Applies to: Sprinklr Search API V3 (
/api/v3/search) - V2 API reference: Search | Sprinklr Developer Portal
Search helps you quickly find and access Sprinklr entities — assets, campaigns, dashboards, cases, macros, rules, and tasks — saving time locating the data you want to view. The Search API exposes that capability programmatically: you post a filter expression against an entity type and receive a page of matching records plus a cursor for the next page.
Search V3 is one path parameterized by entity type, with three operations:
| Operation | Method | Path | operationId |
|---|---|---|---|
| Search entities by entity type | POST | /api/v3/search/{apiEntityName} | SearchApiV3_searchEntities |
| Fetch the next page using a cursor | GET | /api/v3/search/{apiEntityName}?cursor={cursorId} | SearchApiV3_searchEntitiesByCursor |
| Search entities using query parameters | GET | /api/v3/search/{apiEntityName}/query | SearchApiV3_searchEntitiesByQuery |
POSTthe filter to/api/v3/search/{apiEntityName}. The body carriesfilter, and optionallytimeFilter,sorts,page, and field projection.- Sprinklr returns
data.results(the page of records) anddata.cursor(an opaque token, for exampleid=6a062c9faffcb59a7b0a9e30). GET/api/v3/search/{apiEntityName}?cursor={cursorId}to fetch the next page. Repeat until results are exhausted.
The cursor is only valid for five minutes. If it expires, regenerate one with a fresh
POSTsearch. Do not persist cursors across jobs or store them in a queue that may be drained slowly.
Every search is driven by a single root filter object, which is recursive:
filter
├── type → the operator (AND, OR, NOT, IN, EQUALS, GT, LT, EXISTS, …)
├── filters[] → nested Filter objects (used by the boolean operators)
├── key → the field being filtered (used by the leaf operators)
└── values[] → the values to match against keyBoolean operators (AND, OR, NOT) carry filters[]. Leaf operators (IN, EQUALS, GT, and so on) carry key and values.
timeFilter is a separate, sibling object to filter, not a filter type. It bounds the result set by a single time field with since and until.
All API calls are sent to the production endpoint:
https://api3.sprinklr.com/{env}/api/v3So the search resource is:
https://api3.sprinklr.com/{env}/api/v3/search/{apiEntityName}Replace {env} with your assigned environment identifier (prod0, prod2, prod11, and so on — see APIs | Sprinklr Developer Portal for the environment list).
All Search API calls are authenticated with OAuth 2.0. See Developer Tools in Sprinklr for API key and secret generation, and the Authorize flow.
| Header | Value | Description | Required on |
|---|---|---|---|
Authorization | ****** | Credential used by the API to authenticate a user with the server | All requests |
Key | {{apiKey}} | API key that authenticates the application with the server | All requests |
Content-Type | application/json | Representation header that determines the type of data present in the request body | POST |
Accept | application/json | Determines the acceptable response type from the server | All requests |
POST /api/v3/search/{apiEntityName}
Fetches data for an entity type using filters. The response carries a cursor you can pass to Search by cursor to fetch the next set of data.
| Parameter | Required | Type | Description |
|---|---|---|---|
apiEntityName | Required | String | The type of entity you are searching for. See §4.6. |
| Parameter | Sub-parameter | Required | Type | Description |
|---|---|---|---|---|
filter | Required | Object | Filter to apply on the entity type | |
type | Required | String | The filter type. Supported types: AND, OR, NOT, IN, GT, GTE, LT, LTE, NIN, EQUALS, NOT_EQUALS, CONTAINS. See §4.3. | |
filters | Required | List[Filter] | The list of nested filters. The type of filter must match the provided key and values. | |
key | Required | String | The key on which you want to apply the filter | |
values | Required | List[String] | The value of the key. It must match the key. | |
timeFilter | Optional — required for the MESSAGE entity type | Object | The time range filter for the entities | |
key | Required | String | The key on which the time filter is applied, for example channelCreatedTime or createdTime | |
since | Required | Long (epoch ms) | Time since when you want to fetch the results | |
until | Required | Long (epoch ms) | Time until when you want to fetch the results | |
sorts | Required | List[Object] | Sorting information | |
key | Required | String | Key on the basis of which you want to sort the query | |
order | Optional | String | Sort in ascending or descending order — ASC or DESC | |
page | Required | Object | Pagination information | |
start | Optional | Integer | Specifies the starting index for pagination when retrieving records. Use this parameter to define the position from which the API should begin returning results. | |
size | Required | Integer | Size of the page to fetch in the response | |
cursor | Optional | String | Cursor token, as an alternative to the id query parameter on the cursor GET | |
q | Optional | String | Keyword to search in the asset | |
includeCount | Optional | Boolean | When set to true, the response includes the total number of records available for the specified entity type. This helps determine the overall dataset size when implementing pagination. Supported only for the Case entity type. | |
includeFields | Optional | List[String] | Fields to include in the search results | |
excludeFields | Optional | List[String] | Fields to exclude from the search results | |
userId | Optional | Long | Sprinklr user ID | |
impersonator | Optional | String | Impersonation identifier |
| Filter type | Description |
|---|---|
AND | Similar to boolean AND. Added where more than one filter exists; returns values that meet all filter conditions. |
OR | Similar to boolean OR. Added where more than one filter exists; returns values that meet at least one filter condition. |
NOT | Similar to boolean NOT — returns values that do not match the applied filter conditions. |
IN | Returns resources where the key matches any of the values mentioned in the list of values |
NIN (not in) | Returns resources where the key does not match the values mentioned in the list of values |
EQUALS | Returns resources where the given key is equal to the value(s) mentioned in the list of values |
NOT_EQUALS | Returns resources where the given key is not equal to the value(s) mentioned in the list of values |
GT (greater than) | Returns resources where the key is greater than the value(s) mentioned in the list of values |
GTE (greater than or equal to) | Returns resources where the key is greater than or equal to the value(s) mentioned in the list of values |
LT (less than) | Returns resources where the key is less than the value(s) mentioned in the list of values |
LTE (less than or equal to) | Returns resources where the key is less than or equal to the value(s) mentioned in the list of values |
CONTAINS | Returns resources where the given key contains the values mentioned in the list of values |
EXISTS | Tests for presence of the key. Used by the COMMENT entity for includeReplyOnComments with a value of true or false. |
SEARCH | Free-text search on the key. Supported on MESSAGE.content.text and SOCIAL_ASSET.name. |
BETWEEN | Range match. Supported on the OUTBOUND_MESSAGE date and time keys. |
curl --location 'https://api3.sprinklr.com/{env}/api/v3/search/USER' \
--header 'Authorization: ******' \
--header 'Key: {{apiKey}}' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--data '{
"filter": {
"type": "AND",
"filters": [
{
"type": "IN",
"key": "clientAttributes.clientId",
"values": [
"66000002"
]
}
]
},
"page": {
"size": 1
}
}'Response — 200 OK
{
"data": {
"results": [
{
"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": "66016438",
"externalId": "",
"userName": "nitish.kumar@example.com",
"name": {
"familyName": "Kumar",
"givenName": "Nitish"
},
"active": true,
"locale": "en_US",
"userPermissions": [
{
"entityType": "FOLDER",
"permissions": [
"LOCK_UNLOCK",
"CREATE",
"VIEW"
]
}
],
"accessibleClientIds": [],
"globalAttributes": {},
"clientAttributes": [],
"meta": {
"resourceType": "User",
"createdTime": "2025-01-21 11:58:00",
"lastModified": "2026-05-14 19:50:08"
}
}
],
"cursor": "id=6a062c9faffcb59a7b0a9e30"
},
"errors": []
}USER results are SCIM-shaped: they declare schemas, and attributes are split across globalAttributes (partner level), clientAttributes (workspace level), and meta. Note that meta.createdTime and meta.lastModified are formatted date strings ("2025-01-21 11:58:00"), not epoch milliseconds — unlike every other entity in this guide.
This request combines an EQUALS on caseNumber with a GT on modifiedTime under a single AND.
curl --location 'https://api3.sprinklr.com/{env}/api/v3/search/CASE' \
--header 'Authorization: ******' \
--header 'Key: {{apiKey}}' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--data '{
"filter": {
"type": "AND",
"filters": [
{
"type": "EQUALS",
"key": "caseNumber",
"values": [
"6771665"
]
},
{
"type": "GT",
"key": "modifiedTime",
"values": "1708873480000"
}
]
},
"page": {
"size": 10
}
}'Response — 200 OK (custom properties abridged)
{
"data": {
"results": [
{
"id": "67bdcfb28d6fd17e6994284d",
"caseNumber": 6771665,
"subject": "#6771665 Facebook Avinash Sprinklr",
"description": "asd",
"version": 74,
"status": "New",
"priority": "Medium",
"caseType": "Complaint",
"externalCase": {
"id": "500Ig000008xfSOIAY",
"caseNumber": "00005264",
"channelType": "SALESFORCE",
"permalink": "https://sprinklr-2a-dev-ed.develop.my.salesforce.com/500Ig000008xfSOIAY",
"createdTime": 1740493057000,
"modifiedTime": 1740494158000
},
"externalCaseInfo": {
"externalCases": []
},
"workflow": {
"customProperties": {
"_c_674db30dd6266d683949a697": ["50"],
"_c_65252be5825bb637b9857139": ["147258"],
"spr_uc_priority": ["Medium"]
},
"queues": []
},
"channelCustomProperties": [],
"contact": {
"id": "FACEBOOK_110103441967171",
"name": "Addy Wayne Enterprise",
"channelType": "FACEBOOK",
"channelId": "110103441967171",
"fromSnUserId": "110103441967171"
},
"createdTime": 1740492722458,
"modifiedTime": 1740838601419,
"firstMessageId": "ACCOUNT_66005064_1740397109000_FACEBOOK_97_122199892268193678_930538535817351",
"sentiment": -1,
"latestProfileMessageAssociatedTime": 1740397109000,
"conversationId": "240539989134747_122199892268193678",
"firstMessageAssociatedTime": 1740397109000,
"latestMessageAssociatedTime": 1740397109000,
"totalProcessingClockTime": 19442359,
"allEngagedUsersList": [
"66008592"
],
"associatedFanMessageCount": 1,
"associatedBrandMessageCount": 0,
"associatedUserBrandMessageCount": 0,
"deleted": false,
"latestMessageId": "ACCOUNT_66005064_1740397109000_FACEBOOK_97_122199892268193678_930538535817351",
"conversationIntentIds": []
}
]
},
"errors": []
}data.cursor is absent from this response. The result set (1 record) was smaller than the requested page size (10), so there is no next page. Always check for the presence of cursor rather than assuming it exists — see §8.
Search results for CASE use the same Case schema returned by the Case API. See the Case API V3 Developer Guide for the full field reference.
The following entity types are supported: MESSAGE, CASE, USER, OUTBOUND_MESSAGE, CAMPAIGN, SUB_CAMPAIGN, COMMENT, SOCIAL_ASSET, TASK, AUDIENCE_ACTIVITY, PROFILE, CUSTOM_FIELD, TRANSACTION, assignmentSkill.
| Key | Supported types |
|---|---|
sourceType | IN, NIN, EQUALS, NOT_EQUALS |
content.title | IN, NIN, EQUALS, NOT_EQUALS, CONTAINS |
content.text | IN, SEARCH |
channelType | IN, NIN, EQUALS, NOT_EQUALS |
deleted | IN, NIN, EQUALS, NOT_EQUALS |
enrichments.sentiment | IN, NIN, EQUALS, NOT_EQUALS, GT, GTE, LT, LTE |
workflow.customProperties / workflow.spaceWorkflows.customProperties | IN, NIN, EQUALS, NOT_EQUALS |
workflow.campaignId | IN, NIN, EQUALS, NOT_EQUALS |
postId | IN, NIN, EQUALS, NOT_EQUALS |
brandPost | EQUALS, NOT_EQUALS |
sourceId | IN, NIN, EQUALS, NOT_EQUALS |
caseNumber | IN, EQUALS |
MESSAGE timeFilter keys: channelCreatedTime and createdTime, each supporting LT, LTE, GT, GTE, EQUALS. A timeFilter is required for MESSAGE.
| Key | Supported types |
|---|---|
id | IN, NIN, EQUALS, NOT_EQUALS, LT, LTE, GT, GTE |
caseNumber | IN, NIN, EQUALS, NOT_EQUALS, LT, LTE, GT, GTE |
externalCase.caseNumber | IN, NIN, EQUALS, NOT_EQUALS, LT, LTE, GT, GTE |
externalCase.channelType | EQUALS, NOT_EQUALS, IN, NIN |
modifiedTime | IN, NIN, EQUALS, NOT_EQUALS, LT, LTE, GT, GTE |
createdTime | LT, LTE, GT, GTE, EQUALS |
contact.channelId | IN, NIN, EQUALS, NOT_EQUALS |
workflow.customProperties.{customPropertyId} | IN, NIN, EQUALS, NOT_EQUALS |
workflow.queues.queueId | EQUALS, NOT_EQUALS, IN, NIN |
deleted | EQUALS, NOT_EQUALS |
latestProfileAUMSnCreatedTime | LT, LTE, GT, GTE, EQUALS |
| Key | Supported types |
|---|---|
id | IN, NIN, EQUALS, NOT_EQUALS, LT, LTE, GT, GTE |
userName | IN, NIN, EQUALS, NOT_EQUALS |
active | IN, NIN, EQUALS, NOT_EQUALS |
clientAttributes.userType | IN, NIN, EQUALS, NOT_EQUALS |
clientAttributes.clientId | IN, NIN, EQUALS, NOT_EQUALS |
clientAttributes.clientCustomProperties | IN, NIN, EQUALS, NOT_EQUALS |
globalAttributes.partnerCustomProperties | IN, NIN, EQUALS, NOT_EQUALS |
globalAttributes.federationId | IN, NIN, EQUALS, NOT_EQUALS |
globalAttributes.passwordLoginDisabled | IN, NIN, EQUALS, NOT_EQUALS |
meta.lastModified | LT, LTE, GT, GTE, EQUALS |
meta.createdTime | LT, LTE, GT, GTE, EQUALS |
| Key | Supported types |
|---|---|
id | IN, NIN, EQUALS, NOT_EQUALS, LT, LTE, GT, GTE |
channelType | IN, NIN, CONTAINS |
channelId | IN, NIN, CONTAINS |
contact.email | IN, NIN, EQUALS, NOT_EQUALS |
contact.phoneNo | IN, NIN, EQUALS, NOT_EQUALS |
profileWorkflow.customProperties | IN, NIN, EQUALS, NOT_EQUALS |
profileWorkflow.profileSpaceWorkflows.customProperties | IN, NIN, EQUALS, NOT_EQUALS |
profileWorkflow.profileLists | IN, NIN, EQUALS, NOT_EQUALS |
profileWorkflow.profileSpaceWorkflows.profileLists | IN, NIN, EQUALS, NOT_EQUALS |
createdTime | LT, LTE, GT, GTE, EQUALS |
modifiedTime | LT, LTE, GT, GTE, EQUALS |
| Key | Supported types |
|---|---|
entityType (UNIVERSAL_CASE / MESSAGE_WORKFLOW / PROFILE_WORKFLOW) | IN, NIN, EQUALS, NOT_EQUALS |
entityId (case number, message ID, or profile ID) | IN, NIN, EQUALS, NOT_EQUALS |
includeReplyOnComments | EXISTS → true / false |
createdTime | LT, LTE, GT, GTE, EQUALS |
entityIdandentityTypeare required filters when searching for a comment.
| Key | Supported types |
|---|---|
id | IN, NIN, EQUALS, NOT_EQUALS |
assetType | IN, NIN, EQUALS, NOT_EQUALS |
assetSource | IN, NIN, EQUALS, NOT_EQUALS |
status | IN, NIN, EQUALS, NOT_EQUALS |
taxonomy.clientCustomProperties | IN, NIN, EQUALS, NOT_EQUALS |
taxonomy.partnerCustomProperties | IN, NIN, EQUALS, NOT_EQUALS |
restricted | IN, NIN, EQUALS, NOT_EQUALS |
validity.availableFrom | IN, NIN, EQUALS, NOT_EQUALS, LT, LTE, GT, GTE |
validity.expiryTime | IN, NIN, EQUALS, NOT_EQUALS, LT, LTE, GT, GTE |
shareConfigs.type | IN, NIN, EQUALS, NOT_EQUALS |
templateType | IN, NIN, EQUALS, NOT_EQUALS |
channels | IN, NIN, EQUALS, NOT_EQUALS |
name | SEARCH |
| Key | Supported types |
|---|---|
id | IN, NIN, EQUALS, NOT_EQUALS |
name | IN, NIN, CONTAINS |
description | IN, NIN, CONTAINS |
startDate | LT, LTE, GT, GTE, EQUALS |
endDate | LT, LTE, GT, GTE, EQUALS |
tags | IN, NIN, EQUALS, NOT_EQUALS |
owner | IN, NIN, EQUALS, NOT_EQUALS |
status | IN, NIN, EQUALS, NOT_EQUALS |
archived | EQUALS, NOT_EQUALS |
partnerCustomProperties | IN, NIN, EQUALS, NOT_EQUALS |
clientCustomProperties | IN, NIN, EQUALS, NOT_EQUALS |
createdTime | LT, LTE, GT, GTE, EQUALS |
modifiedTime | LT, LTE, GT, GTE, EQUALS |
| Key | Supported types |
|---|---|
id | IN, NIN, EQUALS, NOT_EQUALS |
taskStatus | IN, NIN, EQUALS, NOT_EQUALS |
taskType | IN, NIN, EQUALS, NOT_EQUALS |
title | IN, NIN |
assetId | IN, NIN, EQUALS, NOT_EQUALS |
assetType | IN, NIN, EQUALS, NOT_EQUALS |
customProperties | IN, NIN, EQUALS, NOT_EQUALS |
dueDate | LT, LTE, GT, GTE, EQUALS |
createdTime | LT, LTE, GT, GTE, EQUALS |
modifiedTime | LT, LTE, GT, GTE, EQUALS |
| Key | Supported types |
|---|---|
id | IN, NIN, CONTAINS |
activityTime | IN, NIN, EQUALS, NOT_EQUALS, LT, LTE, GT, GTE |
accountId | IN, NIN, CONTAINS |
messageId | IN, NIN, CONTAINS |
activityType | IN, NIN, CONTAINS |
channelType | IN, NIN, CONTAINS |
| Key | Supported types |
|---|---|
templateId | IN, NIN |
status | IN, NIN |
searchDetails.customProperties | IN, NIN |
createdDate / createdTime | GTE, LTE, BETWEEN |
scheduleDate / scheduleTime | GTE, LTE, BETWEEN |
modifiedDate / modifiedTime | LTE, GTE, BETWEEN |
publishedDate / publishedTime | GTE, LTE, BETWEEN |
| Key | Supported Filter Types |
|---|---|
skill | SEARCH, CONTAINS, TEXT_CONTAINS, EQUALS, IN |
skillCategory | IN, NIN, EQUALS, NOT_EQUALS |
id | IN, NIN, EQUALS, NOT_EQUALS |
createdTime | LT, LTE, GT, GTE, EQUALS, BETWEEN |
modifiedTime | LT, LTE, GT, GTE, EQUALS, BETWEEN |
Custom properties are addressed by appending the custom field ID to the property path:
"filters": [
{
"type": "IN",
"key": "workflow.customProperties.5e4e5f3954e68b2a475c05b6",
"values": [
"Andhra Pradesh"
]
}
]Resolve custom field IDs by searching the customField entity — see §4.9.
Use this to discover the custom field IDs you need for the custom-property filters above.
curl --location 'https://api3.sprinklr.com/{env}/api/v3/search/customField' \
--header 'Authorization: ******' \
--header 'Key: {{apiKey}}' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--data '{
"filter": {
"type": "AND",
"filters": [
{
"type": "LT",
"key": "createdTime",
"values": "1708873480000"
}
]
},
"page": {
"size": 10
}
}'Response — 200 OK (one result shown)
{
"data": {
"results": [
{
"id": "65da2e3013e1fe4109b8c77d",
"fieldName": "_c_65da2e3013e1fe4109b8c779",
"label": "s12",
"assetTypes": [
"USER"
],
"type": "PICKLIST",
"values": [
{ "key": "a", "label": "a" },
{ "key": "b", "label": "b" },
{ "key": "c", "label": "c" }
],
"enabled": true,
"visibility": {
"globallyVisible": true,
"visibilityConfig": []
},
"permissions": [],
"optionType": "GENERAL",
"accessibleClientIds": [
66000004,
66000010,
66000050
],
"createdTime": 1708797488387,
"modifiedTime": 1779195803742
}
],
"cursor": "id=6a0cca9fa62597c1d8643b11"
},
"errors": []
}curl --location 'https://api3.sprinklr.com/{env}/api/v3/search/COMMENT' \
--header 'Authorization: ******' \
--header 'Key: {{apiKey}}' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--data '{
"filter": {
"type": "AND",
"filters": [
{
"type": "IN",
"key": "entityType",
"values": [
"UNIVERSAL_CASE"
]
},
{
"type": "IN",
"key": "entityId",
"values": [
"829"
]
},
{
"type": "EXISTS",
"key": "includeReplyOnComments",
"values": [
"false"
]
}
]
},
"page": {
"size": 2
},
"sorts": [
{
"key": "createdTime",
"order": "ASC"
}
]
}'Response — 200 OK
{
"data": {
"results": [
{
"id": "64e5febee06bd348943340bc",
"text": "<p class=\"export-block__parent\">note1</p>",
"commentingUser": 66000101,
"createdTime": 1692794558032,
"modifiedTime": 1692794558032,
"entityType": "CASE",
"entityId": "829",
"conversationId": "19:6d1c3966-4da1-4eb6-9ee7-b07d72756abf_b1fc70a6-3878-4635-9462-29564f60fa6d@unq.gbl.spaces",
"externalComment": {
"channelType": "MICROSOFT_TEAMS"
}
},
{
"id": "64e5fec2e06bd3489433420f",
"text": "<p class=\"export-block__parent\">note 100</p>",
"commentingUser": 66000101,
"createdTime": 1692794562227,
"modifiedTime": 1692794562227,
"entityType": "CASE",
"entityId": "829",
"conversationId": "19:6d1c3966-4da1-4eb6-9ee7-b07d72756abf_b1fc70a6-3878-4635-9462-29564f60fa6d@unq.gbl.spaces",
"externalComment": {
"channelType": "MICROSOFT_TEAMS"
}
}
],
"cursor": "id=6a06339daffcb59a7b0aa53f"
},
"errors": []
}Two behaviors worth planning for:
- The request filters on
entityType: "UNIVERSAL_CASE", but the response returnsentityType: "CASE". The filter value and the response value are not the same vocabulary. Do not round-trip the response value back into a filter. textis HTML, not plain text. Sanitize it before rendering.
curl --location 'https://api3.sprinklr.com/{env}/api/v3/search/PROFILE' \
--header 'Authorization: ******' \
--header 'Key: {{apiKey}}' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--data '{
"filter": {
"type": "AND",
"filters": [
{
"type": "IN",
"key": "channelType",
"values": [
"WHATSAPP_BUSINESS"
]
}
]
},
"sorts": [
{
"key": "modifiedTime",
"order": "DESC"
}
],
"page": {
"size": 10
}
}'Response — 200 OK (one result, abridged)
{
"data": {
"results": [
{
"restricted": false,
"id": "652425977e759fa6379f4085",
"contact": {
"firstName": "Savy",
"lastName": "Sharma",
"fullName": "Savy Sharma",
"email": "savy.sharma@example.com",
"phoneNo": "+919876543210",
"website": [
"https://www.example.com/"
],
"phoneDetails": [
{ "phoneNo": "+919876543210" }
],
"emailDetails": []
},
"profileWorkflow": {
"profileLists": [
332,
333,
331188,
1
],
"customProperties": {
"_c_64cbf526fd8b0e259d72470a": ["20"],
"_c_64e8a89a9deb2c0c668e7a57": [],
"last_updated_by_user": ["66000015"]
},
"profileSpaceWorkflows": [
{
"profileLists": [1, 5],
"tags": [],
"spaceId": "66000002"
}
]
},
"createdTime": 1696867735563,
"modifiedTime": 1778789065730
}
],
"cursor": "id=6a0631b9affcb59a7b0aa4d1"
},
"errors": []
}Note that customProperties can contain empty arrays for fields that exist but have no value set. Handle that case rather than assuming a non-empty list.
Profile records also carry the résumé-style arrays works, profiles, demographics, organizations, certificates, recommendations, educations, languages, skills, courses, honors, patents, projects, publications, testScores, and voluntaryExp. Use includeFields or excludeFields to keep responses small if you do not need them.
curl --location --request POST 'https://api3.sprinklr.com/{env}/api/v3/search/assignmentSkill' \
--header 'Authorization: Bearer <token>' \
--header 'Key: {{apiKey}}' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--data '{
"filter": {
"type": "AND",
"filters": [
{
"type": "SEARCH",
"key": "skill",
"values": [
"Rahul"
]
}
]
},
"page": {
"size": 10
}
}'Response — 200 OK
{
"data": {
"results": [
{
"id": "69bbfbbca50a41755e093bff",
"skill": "Rahul",
"skillCategory": "64d2943548ed5b75fb38d34b",
"createdTime": 1773927356834,
"modifiedTime": 1773927356834
}
]
},
"errors": []
}GET /api/v3/search/{apiEntityName}?cursor={cursorId}
Fetches the next set of available data. Before using this call, run a Search by entity POST to receive the cursor in the response.
| Parameter | In | Required | Type | Description |
|---|---|---|---|---|
apiEntityName | Path | Required | String | The type of entity you are searching for. Must match the entity type used in the originating POST. |
cursor | Query | Required | String | Cursor ID for pagination. This is the value you received as cursor in the POST response. Example: cursor=5dd2699aaf47f50001d3299d |
The cursor ID is only valid for five minutes. If it expires, regenerate a new one with a fresh Search by entity call.
The Search by Entity API response returns the cursor as a bare query fragment with id= prefix:
"cursor": "id=6a062c9faffcb59a7b0a9e30"Extract the token, not the prefix. Strip any leading id=.
curl --location 'https://api3.sprinklr.com/{env}/api/v3/search/USER?cursor=6a062b7daffcb59a7b0a9ccb' \
--header 'Authorization: ******' \
--header 'Key: {{apiKey}}' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json'Response — 200 OK
The response has the identical envelope and record shape as the originating POST, with a new cursor for the following page:
{
"data": {
"results": [
{
"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"
],
"id": "66070390",
"userName": "user@example.com",
"active": true,
"locale": "en_US",
"meta": {
"resourceType": "User"
}
}
],
"cursor": "id=6a062c41affcb59a7b0a9dc6"
},
"errors": []
}Each page returns a fresh cursor. Always use the cursor from the most recent response, never the original one.
const entity = 'USER';
let response = await post(`/api/v3/search/${entity}`, {
filter: {
type: 'AND',
filters: [
{ type: 'IN', key: 'clientAttributes.clientId', values: ['66000002'] }
]
},
sorts: [{ key: 'meta.createdTime', order: 'ASC' }],
page: { size: 100 }
});
const all = [];
// Accepts a bare token, "id=<token>", "cursor=<token>", or a full URL.
function extractCursorToken(cursor) {
const withoutUrl = cursor.includes('?') ? cursor.slice(cursor.indexOf('?') + 1) : cursor;
return withoutUrl.replace(/^(id|cursor)=/, '');
}
while (true) {
if (response.errors && response.errors.length) {
handleErrors(response.errors);
break;
}
const data = response.data;
if (!data || !data.results || data.results.length === 0) break;
all.push(...data.results);
// No cursor means there is no next page.
if (!data.cursor) break;
// The cursor expires after five minutes — do not queue it for later.
const token = encodeURIComponent(extractCursorToken(data.cursor));
// show `id`. Send `cursor`, fall back to `id` until the build is confirmed.
response = await get(`/api/v3/search/${entity}?cursor=${token}`);
if (response.errors && response.errors.length) {
response = await get(`/api/v3/search/${entity}?id=${token}`);
}
}{
"data": {
"results": [ ... ],
"cursor": "id=6a062c9faffcb59a7b0a9e30",
"count": 42
},
"errors": []
}| Field | Type | Description |
|---|---|---|
data.results | Array | List of assets returned as part of the search. The record shape is the entity's own schema — Case for CASE, the SCIM user for USER, and so on. |
data.cursor | String | Link to get the next set of results. Absent when there is no next page. Valid for five minutes. |
data.count | Long | Total number of records available for the entity type. Returned only when includeCount is true, and supported only for the Case entity type. |
errors | Array[Error] | Array of error objects. Empty when there were no errors. |
On an error, the response contains no data key at all — only errors:
{
"errors": [
{
"id": "6a0633f7affcb59a7b0aa552",
"code": 400,
"message": "Invalid entity: LISTENING_TOPIC_BACKFILL"
}
]
}| Field | Type | Description |
|---|---|---|
id | String | Request identifier. Quote this when raising a support ticket. |
code | Integer | Error code, mirroring the HTTP status |
message | String | Human-readable description of the failure |
| HTTP code | Scenario | Description |
|---|---|---|
200 OK | Success | Results returned, with a cursor when a next page exists |
400 Bad Request | Invalid request | Unknown entity type, malformed filter, or an unsupported key/type combination. Also observed for transient backend failures, for example "Please try again, cluster: test-inbound1-es". |
401 Unauthorized | Authentication failed | Invalid or missing Authorization token |
403 Forbidden | Insufficient permissions | The caller lacks read permission on the entity type |
404 Not Found | Not found | The requested resource does not exist |
400is overloaded. A400can mean either a permanent contract violation ("Invalid entity: …") or a transient backend condition ("Please try again, cluster: …"). Inspecterrors[].messagebefore deciding whether to retry. Retrying an"Invalid entity"failure will never succeed.
| V2 | V3 |
|---|---|
POST /api/v2/search/{entityType} (Search by Entity) | POST /api/v3/search/{apiEntityName} |
GET /api/v2/search/{entityType}?id={cursorId} (Search by Cursor) | GET /api/v3/search/{apiEntityName}?cursor={cursorId} — parameter renamed |
Filter CASE on modifiedTime with GT and the timestamp of your previous run, sort by modifiedTime ASC, and page with the cursor. Sorting ascending on the same key you filter on keeps the watermark monotonic, so a mid-run failure can resume from the last record processed rather than restarting.
Custom properties are keyed by generated IDs such as _c_65da2e3013e1fe4109b8c779, which you cannot guess. Search the customField entity (§4.9), map label → fieldName, and cache the result. Then filter with workflow.customProperties.{fieldName}.
Search COMMENT with entityType and entityId — both are required for comment searches — sorted by createdTime ASC to get the notes in chronological order (§4.10). Remember that text is HTML and that the response entityType (CASE) differs from the filter value (UNIVERSAL_CASE).
Filter USER on clientAttributes.clientId for the workspace, page through with the cursor, and compare userName and active against your IdP. Use excludeFields to drop userPermissions — it is by far the largest part of a user record and is rarely needed for a directory reconciliation.
Filter PROFILE on channelType with IN, sorted by modifiedTime DESC to surface the most recently active profiles first (§4.11). Add contact.email or contact.phoneNo filters to resolve a specific customer.
MESSAGE searches require a timeFilter. Set key to createdTime or channelCreatedTime and bound it with since and until:
{
"filter": {
"type": "AND",
"filters": [
{
"type": "NOT_EQUALS",
"key": "brandPost",
"values": ["true"]
}
]
},
"timeFilter": {
"key": "createdTime",
"since": 1775939449000,
"until": 1778790649000
},
"page": {
"size": 10
}
}This example filters to inbound (non-brand) messages only. Narrow the window rather than widening the page size when a message search is slow.
For CASE searches only, set includeCount: true to have the response report the total number of matching records. Use it to decide whether to run an export at all, to estimate runtime, and to validate that your page loop retrieved everything.
All JSON payloads in this guide are illustrative examples. Email addresses, user names, and phone numbers have been replaced with placeholder values. They are not real customer data and are not guaranteed production responses. All credentials are placeholders (******, {{apiKey}}) and must never be committed or logged.
SOCIAL_ASSET