Applies to: Sprinklr API v3 (Content Template V3 tag) — GET /contentTemplate, POST /contentTemplate/search
V2 API reference: Content Template on the Sprinklr Developer Portal [doc:turn1doc1]
Sprinklr Content Template Builder powers cross-channel content management: it lets users consolidate images, videos, and content for non-social channels such as websites, blogs, and email into reusable templates. The Content Template APIs let you fetch details for user-created and standard content templates, and search templates using sorts, filters, and pagination [doc:turn1doc1].
The v3 Content Template API replaces four separate v2 endpoints with a single resource path plus a search sub-resource.
| # | Operation | Method and path | operationId | Declared 200 schema |
|---|---|---|---|---|
| 1 | Fetch standard content template details | GET /contentTemplate | ContentTemplateApiV3_fetchContentTemplates | APIResponse |
| 2 | Fetch content template details using sorting and filters | POST /contentTemplate/search | ContentTemplateApiV3_searchContentTemplates | PaginatedSearchResponse |
Both operations are tagged Content Template V3 and declare the four shared error responses: 400 BadRequest, 401 Unauthorized, 403 Forbidden, 404 NotFound.
For more details refer to the Content Template V3 API Reference.
A content template is identified by a 24-character hexadecimal id. Beyond id and name, the returned object is template-type dependent.
Note (from the source operation document). "The response parameters vary from template to template. The details depend on the template details present on the backend." Treat every field other than
idandnameas optional and defensively parse the payload.
Fields observed in the reference GET response for an email content template:
| Field | Type | Observed value / meaning |
|---|---|---|
id | String | 6a2bfe33703a82b2e91dc02a — template identifier |
name | String | manual ctm template |
channelType | String | EMAIL |
accountTypes | Array[String] | ["BULK_EMAIL"] |
content | String | Stringified JSON describing the template component tree (Canvas → Subject, EmailTitle, PostGallery …), fonts, merge tags, and languages. Parse as JSON after unescaping. |
smartTemplate | Boolean | false |
isAdvocacyTemplate | Boolean | true |
templateType | String | CONTENT_TEMPLATE |
advocacyProjectId | String (UUID) | f5122f12-f3fb-4ef9-87f5-56b05b2ba4f9 |
height / width | Integer | 1457 / 600 (pixels) |
projectId | String (UUID) | d5b402ad-cb5f-4976-8a23-0ea316767890 |
locationUrl | String (URL) | Location of the rendered publisher bundle |
publisherStatus | String | completed |
contentType | String | PUBLISHING |
version | Integer | 0 |
templateVersionInfo | String | 0.0.1 |
editDisabled | Boolean | true |
archived | Boolean | false |
isPurelyAIGenerated | Boolean | false |
report | String | CONTENT_TEMPLATE |
governance.visibility.globallyVisible | Boolean | true — the v3 equivalent signal of the v2 fromGlobal flag |
clientId | Integer | 66000002 |
ownerUserId | Integer | 66009128 |
createdTime / modifiedTime | String | Jun 12, 2026, 12:40:19 PM / Jul 29, 2026, 09:29:56 AM — formatted date strings, not epoch milliseconds |
lastModifiedUserId | Integer | 66009128 |
deleted | Boolean | false |
canEdit | Boolean | false |
Typical workflow:
- Call
POST /contentTemplate/searchwith filters (for exampleTEMPLATE_TYPE IN [CONTENT_TEMPLATE]) and a page size to obtain a lightweight list of{id, name}pairs plushasMoreandtotalHits. - Call
GET /contentTemplate?id={templateId}for each identifier you need in order to retrieve the full template body.
https://api3.sprinklr.com/{env}/api/v3env is a required path variable. Default: prod. Allowed values declared in the specification:
prod, prod0, prod2, prod3, prod4, prod5, prod6, prod8, prod11, prod12, prod15, prod16, prod17, prod18, prod19, prod21, prod25
Full endpoint URLs:
GET https://api3.sprinklr.com/{env}/api/v3/contentTemplate
POST https://api3.sprinklr.com/{env}/api/v3/contentTemplate/searchImportant. Use your own partition's environment token.
| Key | Value | Description |
|---|---|---|
Authorization | Bearer {{accessToken}} | Credential used by the API to authenticate a user with the server. For generating an authorization token, refer to the Authorize section on the developer portal. |
Key | {{apiKey}} | API key helps authenticate the application with the server. For generating an API key, refer to the Getting Started guide. |
Content-Type | application/json | Representation header that determines the type of data (media/resource) present in the request body. Required for POST /contentTemplate/search. |
Accept | application/json | Determines the acceptable response type from the server. |
GET /api/v3/contentTemplate · operationId ContentTemplateApiV3_fetchContentTemplates
Fetches standard content template details using the template id.
Endpoint form given in the source operation document:
https://api3.sprinklr.com/{env}/api/v3/contentTemplate?{templateId}Endpoint form given in the Jira description:
GET /api/v3/contentTemplate?id=templateId1,templateId2| Parameter | Required / Optional | Description | Type |
|---|---|---|---|
id | Required | Unique identifier of the content template to retrieve. Example: 6a2bfe33703a82b2e91dc02a. Use a comma-separated list form (id=templateId1,templateId2) for bulk fetch | String |
Additional query parameters named in the Jira description as replacements for v2 URL variants, not present in the specification and not exercised in the operation document:
| Parameter | Source | Status |
|---|---|---|
fromGlobal | Jira description — "fromGlobal=true … moved into query params on the standard GET" | Undeclared in sprinklr-v3.yaml; unverified |
channelTypes | Jira description — "channelTypes filter moved into query params on the standard GET" | Undeclared in sprinklr-v3.yaml; unverified |
curl --location 'https://api3.sprinklr.com/{env}/api/v3/contentTemplate?id=6a2bfe33703a82b2e91dc02a' \
--header 'Authorization: Bearer {{accessToken}}' \
--header 'Key: {{apiKey}}' \
--header 'Accept: application/json'Illustrative example. Replace {env}, {{accessToken}}, {{apiKey}}, and the template id with your own values.
The content field in the real response is a very large escaped-JSON string containing the full component tree and embedded @font-face declarations. It is elided below as "…"; everything else is reproduced from the source document.
{
"data": {
"id": "6a2bfe33703a82b2e91dc02a",
"name": "manual ctm template",
"channelType": "EMAIL",
"accountTypes": [
"BULK_EMAIL"
],
"content": "…",
"smartTemplate": false,
"isAdvocacyTemplate": true,
"templateType": "CONTENT_TEMPLATE",
"advocacyProjectId": "f5122f12-f3fb-4ef9-87f5-56b05b2ba4f9",
"height": 1457,
"width": 600,
"projectId": "d5b402ad-cb5f-4976-8a23-0ea316767890",
"locationUrl": "https://storage.googleapis.com/…/spx-publisher/d5b402ad-cb5f-4976-8a23-0ea316767890/1785317396873",
"publisherStatus": "completed",
"contentType": "PUBLISHING",
"version": 0,
"templateVersionInfo": "0.0.1",
"editDisabled": true,
"archived": false,
"isPurelyAIGenerated": false,
"report": "CONTENT_TEMPLATE",
"governance": {
"visibility": {
"globallyVisible": true
}
},
"clientId": 66000002,
"ownerUserId": 66009128,
"createdTime": "Jun 12, 2026, 12:40:19 PM",
"modifiedTime": "Jul 29, 2026, 09:29:56 AM",
"lastModifiedUserId": 66009128,
"deleted": false,
"canEdit": false
},
"errors": []
}data carries the template object described in §1.2. errors is an array of Error objects; an empty array indicates that no errors occurred. See §6.
POST /api/v3/contentTemplate/search · operationId ContentTemplateApiV3_searchContentTemplates
Fetches content template id and name details using sorting and filter values. The request body is required and the declared body schema is Request; the declared 200 schema is PaginatedSearchResponse.
| Parameter | Sub-parameter | Required / Optional | Definition | Type |
|---|---|---|---|---|
sorts | Optional | Sorting filter that specifies the arrangement of data in the response. | Array | |
key | — | Field used for sorting the data. Example: MODIFIED_TIME sorts the response by each template's modified time. | String | |
order | — | Order of data in the response. Example: ASC for ascending, DESC for descending. | String | |
page | Optional | Limits the number of items returned when the response set is large. | Object | |
page | — | Page number to return. If the field has no value, the first page of results is returned. | Integer | |
size | — | Number of results to return. | Integer | |
filters | Required | Information used to filter the data in the response. | List[Object] | |
field | Optional | Field on which the data is filtered. Example: TEMPLATE_TYPE, PUBLISHER_STATUS. | String | |
filterType | Optional | Type of filter applied. Supported values per the operation document: IN, GT, GTE, LT, LTE, NIN, BETWEEN, STARTS_WITH, CONTAINS, EQUALS, FILTER, EXISTS. | String | |
values | Optional | Values against which the data is compared. Example: CONTENT_TEMPLATE. | List[String, Integer] |
Discrepancy —
filtersrequiredness. The operation document marksfiltersRequired while marking every one of its sub-fields Optional, and the same document's dev note says an empty body{}is valid (see §5.4). Those two statements cannot both hold. The specification marks the body required but declares norequiredarray insideRequest, sofiltersis optional at the schema level. Confirm the intended contract.
Discrepancy —
filterTypeenum. In the specification,filters[]resolves toFilter_request, whosefilterTypeis the enumFilterType_Filterwith valuesFILTER,LIMIT,SEARCH,MATCH_PHRASE_PREFIX,ADHOC_SEARCH,EXPRESSION,GEO_DISTANCE,ADVANCED_QUERY,MATCH_NONE,MATCH_ALL. OnlyFILTERappears in both lists. The value used in the working example —IN— is not in the specification enum, yet QA verified the call. Treat the operation document's list as the behavioural truth and the specification enum as stale, but confirm before generating client code from the spec.
Note —
Requestis a shared, very wide schema.Requestis Sprinklr's generic search/reporting request object. It declares roughly 40 top-level properties (key,timeFilter,previousTimeFilter,query,queries,filters,filter,postFilters,projectionFilters,groupBys,projections,report,permission,tzOffset,timezone,sorts,page,pageForDocuments,sortsForDocuments,merge,excludeFields,additional, and more). Onlysorts,page, andfiltersare documented for this operation. The remaining properties are not documented as supported for content template search — do not assume they are honoured.
Related schema details from sprinklr-v3.yaml:
sorts[]→Sort_request:type(string),key(string),order(Order_enums— a bare string with no enum values declared),additional,postProjectionSort.page→Page_request:page(int32),size(int32),skip(int32),cursor(string). Onlypageandsizeare documented for this operation.filters[]→Filter_request:field,filterType,values(array of object), plusdisplayName,negativeFilter,isCompoundFilter,accessibleValues,userFilter,allValuesAllowed,lockedWithValues,hidden,favourite,mandatory,locked,disabled,details— all undocumented for this operation.
curl --location 'https://api3.sprinklr.com/{env}/api/v3/contentTemplate/search' \
--header 'Authorization: Bearer {{accessToken}}' \
--header 'Key: {{apiKey}}' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--data '{
"sorts": [
{
"key": "MODIFIED_TIME",
"order": "DESC"
}
],
"page": {
"page": 0,
"size": 5
},
"filters": [
{
"field": "TEMPLATE_TYPE",
"filterType": "IN",
"values": [
"CONTENT_TEMPLATE"
]
}
]
}'Illustrative example, reproduced from the source operation document with credentials replaced by placeholders.
{
"data": {
"searchResults": [
{
"id": "6a214d2e1d46a76667fd4b9c",
"name": "pragya testing "
},
{
"id": "6a883d0595239a114d6dbf47",
"name": "Link"
},
{
"id": "6a883d05e7f1f360e3d4f1c2",
"name": "Media"
},
{
"id": "6a883d05e7f1f360e3d4f1c3",
"name": "Text"
},
{
"id": "6a7afc34dff6d5eda924d20e",
"name": "Thread"
}
],
"hasMore": true,
"totalHits": 287
},
"errors": []
}Response fields:
| Parameter | Sub-parameter | Required / Optional | Definition | Type |
|---|---|---|---|---|
data | Required | Contains the search results and pagination information returned by the API. | Object | |
searchResults | Required | List of templates matching the specified search criteria. | Array | |
searchResults[].id | Required | Unique identifier of the template. | String | |
searchResults[].name | Required | Name of the template. | String | |
hasMore | Required | Indicates whether additional results are available beyond the current response. true means another page can be requested. | Boolean | |
totalHits | Required | Total number of records matching the search criteria. 287 means 287 templates match the applied filters. | Integer | |
errors | Required | Details of any errors encountered while processing the request. An empty array indicates that no errors occurred. | Array |
Discrepancy — field names. The declared 200 schema
PaginatedSearchResponseuses abbreviated property names:sR(array),tBC(int64),iBC(string),hM(boolean),tH(int64),fR(array ofSearchFacetResponse),topHits(map ofTuple_Long_List_T). The verified response instead usessearchResults,hasMore, andtotalHits, and is wrapped in adataenvelope thatPaginatedSearchResponsedoes not declare. This is almost certainly a serialization-alias mismatch in the published spec. Code against the documented names (data.searchResults,data.hasMore,data.totalHits) and treat the abbreviated spec names as an outstanding spec bug. Also notesR[]is typed "Unresolved type (T)", so the{id, name}shape comes only from the example.
Dev note. "If the request has no sorting or filters applied and has a pair of empty curly brackets, i.e.,
{}, then the response will show details for all the content templates available on a single page. By default, the size of response per page is equal to 100."
So:
- Body
{}→ all available content templates, one page. - Default page size when
pageis omitted → 100. - Use
hasMoreandtotalHitsto decide whether to request the next page.
curl --location 'https://api3.sprinklr.com/{env}/api/v3/contentTemplate/search' \
--header 'Authorization: Bearer {{accessToken}}' \
--header 'Key: {{apiKey}}' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--data '{}'| Code | Meaning | Declared schema |
|---|---|---|
200 | Success | APIResponse (GET) / PaginatedSearchResponse (POST search) |
400 | Bad Request — shared BadRequest response | ErrorResponse |
401 | Unauthorized — shared Unauthorized response | ErrorResponse |
403 | Forbidden — shared Forbidden response | ErrorResponse |
404 | Not Found — shared NotFound response | ErrorResponse |
No other status codes are declared for either operation.
APIResponse:
{
"data": {},
"errors": [],
"metadata": {}
}| Field | Type | Notes |
|---|---|---|
data | object | Untyped in the specification. The actual shape is documented only by the examples in §4.4 and §5.3. |
errors | array of Error | Empty on success. |
metadata | ResponseMetadata | Declared by APIResponse; absent from the captured examples. |
ErrorResponse:
{
"data": null,
"errors": [
{
"id": "6a2bfe33703a82b2e91dc02a",
"code": 404,
"message": "content.template.not.found"
}
],
"metadata": {}
}Error requires all three fields:
| Field | Type | Notes |
|---|---|---|
id | String | 24-character hexadecimal ObjectId. |
code | Integer | Numeric error code. |
message | String | Dotted message key, for example account.not.found. |
Note. The
messagevalue shown above is an illustrative key following the platform's dotted-key convention. The specification does not enumerate content-template-specific error codes or keys. Logcodeandmessageverbatim; do not pattern-match on message text.
| v2 operation | v2 endpoint | v3 equivalent | Notes |
|---|---|---|---|
| Fetch User-Created Content Template Details | GET /api/v2/contentTemplate/{templateId} | GET /api/v3/contentTemplate?id={templateId} | Path segment becomes a query parameter. |
| Fetch Standard Content Template Details | GET /api/v2/contentTemplate/{templateId}?fromGlobal=true | GET /api/v3/contentTemplate?id={templateId} (+ fromGlobal per the Jira description) | The v3 operation document covers this operation ("Fetch Standard Content Template Details"). fromGlobal is named only in the Jira description and is undeclared in the spec. The returned object exposes governance.visibility.globallyVisible. |
| Fetch Content Template Details Using Sorting and Filters | POST /api/v2/contentTemplate/searchContentTemplates | POST /api/v3/contentTemplate/search | Sub-path renamed from searchContentTemplates to search. |
| Fetch Content Template Details by Channel Type | GET /api/v2/contentTemplate/findAll?channelTypes={channelType} [doc:turn1doc4] | GET /api/v3/contentTemplate (+ channelTypes per the Jira description) | findAll is removed. channelTypes is named only in the Jira description and is undeclared in the spec. |
| — (did not exist) | — | Not delivered | The Jira description announces PUT, PATCH, and DELETE on /api/v3/contentTemplate. QA confirmed they are out of scope and the spec does not define them. |
| Area | v2 | v3 |
|---|---|---|
| Base path | /api/v2/contentTemplate/… | /api/v3/contentTemplate |
| Template addressing | Path segment /{templateId} | Query parameter ?id= |
| Global/standard templates | Distinct URL variant ?fromGlobal=true | Same GET; governance.visibility.globallyVisible on the returned object |
| Channel filtering | Dedicated /findAll?channelTypes= endpoint | Per the Jira description, a query parameter on the standard GET (undeclared in the spec) — or use POST /search with a filters entry |
| Search sub-path | searchContentTemplates | search |
findAll response shape | {"data": [{"id": …, "name": …}], "errors": []} — data is a flat array [doc:turn1doc4] | {"data": {"searchResults": [{"id": …, "name": …}], "hasMore": …, "totalHits": …}, "errors": []} — data is an object with pagination metadata |
| Response envelope | data + errors | data + errors (+ metadata per APIResponse); all responses wrapped in a { "data": … } envelope per v3 convention |
| Pagination signal | Not present on findAll | hasMore, totalHits, default page size 100 |
- Change the base path from
/api/v2/to/api/v3/and confirm your{env}token is in the v3 environment enum (§2). - Move the template id out of the path. Replace
GET /api/v2/contentTemplate/{templateId}withGET /api/v3/contentTemplate?id={templateId}. - Retire the
?fromGlobal=trueURL variant. Call the singleGETand readgovernance.visibility.globallyVisiblefrom the response. Confirm with the API owner whether afromGlobalquery parameter is actually accepted before depending on it. - Retire
/findAll?channelTypes=. Replace it withPOST /api/v3/contentTemplate/searchusing afiltersentry, or confirm thechannelTypesquery parameter with the API owner. - Rename the search sub-path from
searchContentTemplatestosearch. Thesorts/page/filtersbody structure is unchanged in the documented examples. - Update your search response parser.
datais now an object, not an array. Readdata.searchResultsinstead ofdata, and start consuminghasMore/totalHits. - Adopt pagination. v2
findAllreturned an unpaginated list. In v3, omittingpagereturns 100 results; loop onhasMoreand incrementpage.page. - Harden your
GETparser. The full template object varies by template type, andcontentis an escaped JSON string that must be unescaped before parsing. - Update error handling to the
ErrorResponse/Errorshape (id,code,message) and to the 400/401/403/404 set. - Do not plan on v3 write operations.
PUT,PATCH, andDELETEare not delivered. Keep using existing platform mechanisms for template mutation.
| Field | Source | Example values |
|---|---|---|
TEMPLATE_TYPE | Operation document | CONTENT_TEMPLATE |
PUBLISHER_STATUS | Operation document | Not exemplified; the GET response exposes publisherStatus: "completed" |
No complete list of filterable fields is published in any source.
| Source | Values |
|---|---|
| Operation document (behavioural) | IN, GT, GTE, LT, LTE, NIN, BETWEEN, STARTS_WITH, CONTAINS, EQUALS, FILTER, EXISTS |
sprinklr-v3.yaml — FilterType_Filter | FILTER, LIMIT, SEARCH, MATCH_PHRASE_PREFIX, ADHOC_SEARCH, EXPRESSION, GEO_DISTANCE, ADVANCED_QUERY, MATCH_NONE, MATCH_ALL |
The two lists overlap only on FILTER. See the discrepancy note in §5.1.
| Item | Documented values | Specification |
|---|---|---|
sorts[].key | MODIFIED_TIME (only example given) | Sort_request.key — bare string, no enum |
sorts[].order | ASC, DESC | Order_enums — bare string, no enum values declared |
These values are observed in the reference example only; none is declared as an enum in the specification.
| Field | Observed value |
|---|---|
channelType | EMAIL |
accountTypes[] | BULK_EMAIL |
templateType | CONTENT_TEMPLATE |
contentType | PUBLISHING |
publisherStatus | completed |
report | CONTENT_TEMPLATE |
| Schema | Used by | Notes |
|---|---|---|
APIResponse | GET /contentTemplate 200 | {data, errors, metadata}; data untyped |
PaginatedSearchResponse | POST /contentTemplate/search 200 | Abbreviated property names — see §5.3 |
Request | POST /contentTemplate/search body | Generic, wide search/reporting request |
Sort_request | Request.sorts[] | |
Page_request | Request.page | page, size, skip, cursor |
Filter_request | Request.filters[] | field, filterType, values, + many undocumented flags |
FilterType_Filter | Filter_request.filterType | Enum — conflicts with the documented list |
ErrorResponse / Error | 400/401/403/404 |
- Template catalogue sync. Page through
POST /contentTemplate/searchwith{}or aTEMPLATE_TYPEfilter to mirror the id/name catalogue into an external CMS or DAM, then fetch full bodies on demand. - Most-recently-edited view. Sort by
MODIFIED_TIME DESCwith a smallpage.sizeto power a "recently updated templates" panel. - Channel-scoped picker. Filter the search results to the channel your integration publishes to, replacing the v2
findAll?channelTypes=call. - Template rendering/preview. Retrieve the full object with
GET, unescapecontent, and hand the component tree to your renderer; useheight,width, andlocationUrlfor layout and asset resolution. - Governance auditing. Read
governance.visibility.globallyVisible,editDisabled,canEdit,archived,deleted,ownerUserId, andlastModifiedUserIdto report on template access and lifecycle.
- Search first, fetch second. The search response is a lightweight
{id, name}list; theGETresponse can be hundreds of kilobytes because of the embeddedcontentstring. Do not fetch full bodies to build a list view. - Always send
page. Relying on the default of 100 makes your integration silently sensitive to a server-side default change. - Loop on
hasMore, verify againsttotalHits. Stop whenhasMoreisfalse; usetotalHitsfor progress and sanity checks. - Unescape
contentbefore parsing. It is a JSON string, not a nested object. - Parse the
GETresponse defensively. Per the source dev note, fields vary by template. Guard every field exceptidandname. - Treat
createdTime/modifiedTimeas formatted strings. They arrive asJun 12, 2026, 12:40:19 PM, not epoch milliseconds. Parse with an explicit format and confirm the emitting timezone with the API owner. - Do not send
Cookie: JSESSIONID=…. Authenticate withAuthorization+Keyonly. - Do not use undocumented
Requestproperties. Onlysorts,page, andfiltersare documented for this operation. - Filter on the server. Send
filtersrather than pulling all templates and filtering client-side. - Handle
errorseven on200. The envelope carries anerrorsarray independently of the HTTP status; check that it is empty before trustingdata. - Pin the environment. Ensure
{env}matches your partition; a wrong environment yields 401/403 rather than empty results.