# CFM Workflow API V3 — Developer Guide

- **Applies to:** Sprinklr Customer Feedback Management (CFM) Workflow API V3 (`/api/v3/cfmWorkflow`)
- **V2 API reference:** [CFM Workflow API | Sprinklr Developer Portal](https://dev.sprinklr.com/cfm-workflow-api)
- **CFM module overview:** [Customer Feedback Management | Sprinklr Developer Portal](https://dev.sprinklr.com/customer-feedback-management)
- **Source ticket:** [IN-12886 — CRUD for Custom Feedback Management APIs](https://sprinklr.atlassian.net/browse/IN-12886) (Epic [IN-12622 — V3 parity APIs all entities](https://sprinklr.atlassian.net/browse/IN-12622))


## 1. Overview

The **CFM Workflow API** starts a Customer Feedback Management workflow from an external system event. You supply a workflow identifier and a set of context parameters; Sprinklr runs the configured workflow, which can create or update a customer profile and trigger a personalized survey distribution over **Email, SMS, or WhatsApp**.

This turns real customer-journey moments — an online purchase, a form submission, an abandoned cart, a support-case closure — into a targeted, automated feedback request.

V3 exposes **two POST operations** under a single resource prefix:

| Operation | Method | Path | operationId |
|  --- | --- | --- | --- |
| Run workflow via event | `POST` | `/api/v3/cfmWorkflow/trigger` | `CfmWorkflowApiV3_triggerWorkflow` |
| Run workflow via event with profile details | `POST` | `/api/v3/cfmWorkflow/triggerWithNewProfile` | `CfmWorkflowApiV3_triggerWorkflowWithProfile` |


Both are tagged **CFM Workflow V3** in the OpenAPI specification.

The central design change from V2: **V2 documented a single endpoint** — `POST /api/v2/cfm-workflow/triggerWithNewProfile` — which always required a `unifiedProfile` object. V3 splits the capability in two, so a caller who only needs to fire an event against an already-known workflow context can use the lighter `/trigger` operation and omit profile construction entirely.

> **Prerequisite.** CFM must be enabled in your environment before you can use these APIs. Contact your Success Manager. (Source: [Customer Feedback Management | Sprinklr Developer Portal](https://dev.sprinklr.com/customer-feedback-management))


> **⚠️ Conflict to resolve — resource path.**
The IN-12886 description lists the workflow endpoint as `POST /api/v3/cfm/workflow/trigger`.
The OpenAPI specification (`sprinklr-v3.yaml`, line 2010), the supplied endpoint specifications, and the QA-verified cURL in the ticket all use `POST /api/v3/cfmWorkflow/trigger`.
**This guide documents `/api/v3/cfmWorkflow/…`**, on the basis that the specification and the QA-verified request agree against the ticket prose. Confirm with the API owner before publishing. See [§12](#12-questions-for-the-api-owner).


> **⚠️ Conflict to resolve — undocumented second operation.**
The IN-12886 description does not mention `triggerWithNewProfile` at all. The operation exists in the OpenAPI specification (line 2037), has a dedicated endpoint specification, and was exercised in the QA verification comment dated **2026-08-20**. Treat the ticket description as incomplete, not the endpoint as unsupported.


### 1.1 The workflow trigger data model

A trigger request is composed of at most three parts:

| Part | Field | Type | What it does | Present on |
|  --- | --- | --- | --- | --- |
| Workflow selector | `workflowId` | String | Identifies the active CFM workflow to execute | Both operations — **required** |
| Runtime context | `contextParams` | Object (map) | Free-form key/value pairs passed into the workflow, used by its conditions and actions | Both operations — optional |
| Customer identity | `unifiedProfile` | Object (`UnifiedProfile`) | A new or upserted customer profile the workflow acts on and distributes the survey to | `triggerWithNewProfile` only |


The workflow itself — its conditions, its branching, and the **Trigger Survey Distribution** action that actually sends the survey — is configured in the Sprinklr UI under **Sprinklr Insights → Customer Feedback Management → *survey* → Automation**, using the **CFM Workflow API** event type. The API only starts it. See [Setting Up a CFM Workflow API Event Workflow](https://www.sprinklr.com/help/articles/setting-workflow-trigger-events/setting-up-a-cfm-workflow-api-event-workflow/6807458589cac71a44d0022c) for the configuration side.

### 1.2 Where `workflowId` comes from

`workflowId` is the identifier of a workflow you have already created and activated in the CFM Automation canvas. It is a UUID-shaped string, for example `595b4041-6eba-400f-aff0-797f1029c6f2`.

You can obtain a ready-made request — with `workflowId` pre-filled from the current workflow — by opening the workflow record and choosing **Test API Connection**. That screen also lets you pick a **Channel Type** (Email, WhatsApp Business, SMS), supply a first name, full name, and social network user ID, and add extra `contextParams`, then click **Get API Request**. Copy the generated request, add your authentication headers, and run it. (Source: [Setting Up a CFM Workflow API Event Workflow](https://www.sprinklr.com/help/articles/setting-workflow-trigger-events/setting-up-a-cfm-workflow-api-event-workflow/6807458589cac71a44d0022c))

### 1.3 Scope note

IN-12886 is a single ticket covering the whole CFM surface: **Workflow**, **Survey Response**, and **Transaction**. This guide documents only the **two Workflow operations**, which is what the supplied endpoint specifications cover. The Survey Response and Transaction endpoints are summarized for orientation in [§11.2](#112-related-cfm-v3-endpoints-not-covered-by-this-guide) but are not documented here.

## 2. Base URLs and environments

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

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

So the workflow resources in production are:

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

Replace `{env}` with your assigned environment identifier (`prod0`, `prod2`, `prod3`, `prod4`, `prod5`, `prod6`, `prod8`, `prod11`, `prod12`, `prod15`, `prod16`, `prod17`, `prod18`, `prod19`, `prod21`, `prod24`, `production`, `spr-uat`, `azrqa` — see [APIs | Sprinklr Developer Portal](https://dev.sprinklr.com/apis) for the full environment list).

QA and pre-production environments use a different host shape, in which the environment is a **hostname prefix** rather than a path segment:

| Environment | Base URL | Trigger resource |
|  --- | --- | --- |
| Production | `https://api3.sprinklr.com/{env}/api/v3` | `https://api3.sprinklr.com/{env}/api/v3/cfmWorkflow/trigger` |
| QA6 (internal) | `https://qa6-api2-v3.sprinklr.com/api/v3` | `https://qa6-api2-v3.sprinklr.com/api/v3/cfmWorkflow/trigger` |


Do not hard-code either host. Make the base URL a single configuration value so promotion from QA to production is a config change, not a code change.

> **⚠️ Conflict to resolve — `{env}` path segment.**
The V2 developer-portal page uses `https://api3.sprinklr.com/{env}/api/v2/cfm-workflow/triggerWithNewProfile`, with an explicit `{env}` segment. The in-product sample in the Help Center article omits it entirely (`https://api3.sprinklr.com//api/v2/cfm-workflow/triggerWithNewProfile` — note the doubled slash, which is a defect in that sample). Both supplied V3 endpoint specifications, and both QA-verified cURLs, use the QA6 host with **no** `{env}` segment.
The production `{env}` form above is carried over from the Profile V3 guide and the V2 page. **The production V3 base URL has not been verified against a shipped V3 production deployment.** Confirm before publishing. See [§12](#12-questions-for-the-api-owner).


> The V3 examples in this guide use the **QA6** form, because that is the form used verbatim in the supplied specifications and in the QA verification comment. Substitute your production base URL when you go live.


## 3. Authentication and common headers

All CFM Workflow API calls are authenticated with OAuth 2.0. See [API Overview](https://dev.sprinklr.com/api-overview) for portal registration, API key and secret generation, and the Authorize flow.

| Header | Value | Purpose | Required on |
|  --- | --- | --- | --- |
| `Authorization` | `{{accessToken}}` | 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` | `{{apiKey}}` | API key that authenticates the application with the server. For generating an API key, refer to the **Getting Started** guide. | All requests |
| `Content-Type` | `application/json` | Determines the type of data (media/resource) present in the request body | Both `POST` operations |
| `Accept` | `application/json` | Determines the acceptable response type from the server | All requests |


**Permissions:** the CFM Workflow API event does not require any special permission within the Sprinklr Audience Profile Event module. However, you must configure the CFM Workflow API within your own systems and hold valid Sprinklr API authentication. (Source: [Setting Up a CFM Workflow API Event Workflow](https://www.sprinklr.com/help/articles/setting-workflow-trigger-events/setting-up-a-cfm-workflow-api-event-workflow/6807458589cac71a44d0022c))

> **Specification gap.** The OpenAPI specification declares `403 Forbidden` on both operations but does not name the entity or permission that governs it. The specific permission required to trigger a CFM workflow is not stated in any supplied source. See [§12](#12-questions-for-the-api-owner).


> **⚠️ Conflict to resolve — is `Key` mandatory?**
Both endpoint specifications list `Key` in the headers table. The QA-verified cURL for **`/triggerWithNewProfile` sends `Key`**; the QA-verified cURL for **`/trigger` does not** — it sends only `Authorization`, `Content-Type`, and `Accept`, and was reported as verified. Either `Key` is optional on `/trigger`, or the QA request succeeded through a path that does not enforce it. Confirm before telling developers they can omit it. **This guide sends `Key` on both operations.**


> **Credential hygiene.** Never commit an access token or API key to source control, never paste one into a ticket or chat, and never log the `Authorization` or `Key` header values. Every credential in this guide is a placeholder.
**⚠️ Action required.** The QA verification comment on IN-12886 (Santhosh M., 2026-08-20) contains **three live-looking secrets in plaintext**: two `Authorization` bearer values and one `Key` value against the QA6 environment. They have been redacted from this guide. **Revoke and regenerate all three immediately**, and delete or redact the comment.


## 4. Run workflow via event

Triggers an active CFM workflow using only a workflow identifier and runtime context. Use this when the customer profile the workflow acts on is already resolvable from the workflow's own configuration or from the supplied context, and you do not need to create or update a profile in the same call.

```
POST /api/v3/cfmWorkflow/trigger
```

- **operationId:** `CfmWorkflowApiV3_triggerWorkflow`
- **Summary (OpenAPI):** Run workflow via event
- **Request schema:** `CfmWorkflowTriggerV3Request`
- **Request body:** required
- **Response schema:** `APIResponse`


### 4.1 Request body

Schema `CfmWorkflowTriggerV3Request` — *Request body for triggering a CFM workflow via API v3.*

| Parameter | Sub-parameter | Type | Required | Description |
|  --- | --- | --- | --- | --- |
| `workflowId` | — | String | **Yes** | Unique identifier of the active workflow to be executed. |
| `contextParams` | — | Object | No | Contains contextual parameters passed to the workflow at runtime. Declared in OpenAPI as an object with `additionalProperties: {type: string}`. |
| `contextParams` | `IGNORE_DEDUP` | Boolean | No | Determines whether duplicate detection is ignored during workflow execution. |
| `contextParams` | `lang` | String | No | Language code used to localize workflow behavior or content. |
| `contextParams` | `country` | String | No | Country name used as contextual input for the workflow. |
| `contextParams` | `countryCode` | String | No | Two-letter country code associated with the specified country. |
| `contextParams` | `surveyFilled` | String | No | Indicates whether the survey has been completed. |


`workflowId` is the only field in the OpenAPI `required` array.

`IGNORE_DEDUP`, `lang`, `country`, `countryCode`, and `surveyFilled` are the keys shown in every supplied example. They are **conventional keys, not a closed enum** — `contextParams` is an open map, so you can pass any key your workflow's conditions reference.

> **⚠️ Conflict to resolve — `contextParams` value type.**
The OpenAPI schema declares `contextParams` as `additionalProperties: {type: string}`, i.e. **all values must be strings**. Every supplied example — the V2 portal page, the Help Center sample, both V3 endpoint specifications, and both QA-verified cURLs — sends `"IGNORE_DEDUP": true` as a **JSON boolean**, and `"surveyFilled": "true"` as a **string**. Either the schema is too narrow or the examples are wrong. **Do not rely on non-string values until this is confirmed**; the safest payload sends every `contextParams` value as a string. See [§12](#12-questions-for-the-api-owner).


### 4.2 Example request

```bash
curl --request POST \
  --url 'https://qa6-api2-v3.sprinklr.com/api/v3/cfmWorkflow/trigger' \
  --header 'Authorization: {{accessToken}}' \
  --header 'Key: {{apiKey}}' \
  --header 'Content-Type: application/json' \
  --header 'Accept: application/json' \
  --data '{
    "workflowId": "595b4041-6eba-400f-aff0-797f1029c6f2",
    "contextParams": {
      "IGNORE_DEDUP": true,
      "lang": "ar",
      "country": "Jordan",
      "countryCode": "SA",
      "surveyFilled": "true"
    }
  }'
```

*Illustrative example. `workflowId` is the value used in the supplied specification and QA verification; substitute your own. Credentials are placeholders.*

### 4.3 Example response

```json
{
  "data": "Success",
  "errors": []
}
```

**Dev note:** a `"Success"` value in `data` indicates that the API endpoint successfully triggered the CFM workflow for the profile. It does **not** confirm that the survey was delivered — delivery happens asynchronously inside the workflow. See [§10](#10-caveats-and-best-practices).

### 4.4 Response parameters

| Parameter | Type | Description |
|  --- | --- | --- |
| `data` | String | Indicates the outcome of the API request. `"Success"` when the workflow was triggered. |
| `errors` | Array[`Error`] | Contains any errors encountered during the request. Empty when no errors occurred. |
| `metadata` | Object (`ResponseMetadata`) | Response metadata. Declared on the `APIResponse` envelope but **absent from every supplied example** for this endpoint. |


## 5. Run workflow via event with profile details

Triggers an active CFM workflow and supplies a **new unified customer profile** in the same request. Sprinklr creates or updates the profile from the payload and then runs the workflow against it — which is what lets the workflow's **Trigger Survey Distribution** action reach a customer the platform has never seen before.

```
POST /api/v3/cfmWorkflow/triggerWithNewProfile
```

- **operationId:** `CfmWorkflowApiV3_triggerWorkflowWithProfile`
- **Summary (OpenAPI):** Run workflow via event with profile details
- **Request schema:** `CfmWorkflowTriggerProfileV3Request`
- **Request body:** required
- **Response schema:** `APIResponse`


This is the direct V3 successor to the single V2 endpoint `POST /api/v2/cfm-workflow/triggerWithNewProfile`.

### 5.1 Request body

Schema `CfmWorkflowTriggerProfileV3Request` — *Request body for triggering a CFM workflow with a new profile via API v3.*

| Parameter | Sub-parameter | Type | Required | Description |
|  --- | --- | --- | --- | --- |
| `workflowId` | — | String | **Yes** | Unique identifier of the active workflow to be executed. |
| `contextParams` | — | Object | No | Contextual parameters passed to the workflow at runtime. Same semantics and same caveat as [§4.1](#41-request-body). |
| `unifiedProfile` | — | Object (`UnifiedProfile`) | No | Unified profile of the new user. |


`workflowId` is the only field in the OpenAPI `required` array.

> **⚠️ Conflict to resolve — is `unifiedProfile` required?**
The **V2** portal page marks `unifiedProfile` **Required**. The V3 OpenAPI `required` array lists **only `workflowId`**, and the supplied V3 endpoint specification marks `unifiedProfile` **No** (optional). If it is genuinely optional in V3, `POST /triggerWithNewProfile` with no profile is behaviourally identical to `POST /trigger`, which makes the two operations redundant. This looks like a specification defect rather than an intended relaxation. Confirm. See [§12](#12-questions-for-the-api-owner).


### 5.2 The `unifiedProfile` object

`unifiedProfile` is the platform-wide **`UnifiedProfile`** schema — *"Unified view of a profile in sprinklr."* It is the same object the Profile V3 API returns, and it is large. Only a small subset is relevant to a workflow trigger.

**Fields used in practice** (per every supplied example):

| Parameter | Sub-parameter | Type | Required | Description |
|  --- | --- | --- | --- | --- |
| `unifiedProfile` | `id` | String | No | Unique identifier of the unified profile. Omit when creating a new profile. |
| `unifiedProfile` | `contact` | Object (`ContactInfo`) | No | Contact information of the profile. |
| `unifiedProfile.contact` | `firstName` | String | No | First name of the profile. |
| `unifiedProfile.contact` | `lastName` | String | No | Last name of the profile. |
| `unifiedProfile.contact` | `maidenName` | String | No | Maiden name of the profile. |
| `unifiedProfile.contact` | `fullName` | String | No | Full name of the profile. |
| `unifiedProfile.contact` | `email` | String | No | Email ID of the profile. |
| `unifiedProfile.contact` | `username` | String | No | Username of the profile. |
| `unifiedProfile.contact` | `phoneNo` | String | No | Phone number of the profile. |
| `unifiedProfile.contact` | `address` | Object (`Address`) | No | Address of the profile. See [§5.3](#53-address-object). |
| `unifiedProfile.contact` | `website` | Array[String] | No | List of websites for the profile. |
| `unifiedProfile.contact` | `phoneDetails` | Array[`PhoneDetail`] | No | Phone details for the profile. |
| `unifiedProfile.contact` | `emailDetails` | Array[`EmailDetail`] | No | Email details for the profile. |
| `unifiedProfile` | `profiles` | Array[`Profile`] | No | List of social identities linked to the profile. **This is the array that determines which channels the survey can be distributed over.** |
| `unifiedProfile.profiles[]` | `name` | String | **Yes**¹ | Name of the person. |
| `unifiedProfile.profiles[]` | `channelType` | String | **Yes**¹ | Channel type of the profile — for example `EMAIL`, `SMS`, `WHATSAPP_BUSINESS`. |
| `unifiedProfile.profiles[]` | `channelId` | String | **Yes**¹ | Unique identifier of the customer on that channel. **If the `channelId` is unique, a new profile is created and a journey is associated with it; otherwise the journey is associated with the existing profile.** |
| `unifiedProfile.profiles[]` | `permalink` | String | **Yes**¹ | Link of the profile on the social channel. |
| `unifiedProfile.profiles[]` | `avatarUrl` | String | No | Profile image link. |
| `unifiedProfile.profiles[]` | `profileImageUrl` | String | No | Profile image link. |
| `unifiedProfile.profiles[]` | `bio` | String | No | Detailed description about the user. |
| `unifiedProfile.profiles[]` | `followers` | Integer (int32) | No | Followers count of the user. |
| `unifiedProfile.profiles[]` | `following` | Integer (int32) | No | Count of users/pages followed by this user. |
| `unifiedProfile.profiles[]` | `username` | String | No | Unique identifier of the user. |
| `unifiedProfile.profiles[]` | `verified` | Boolean | No | `true` if the user is verified by the channel. Default `false`. |
| `unifiedProfile.profiles[]` | `unSubscribed` | Boolean | No | `true` if the user is subscribed for email and other activities. Default `false`. |
| `unifiedProfile.profiles[]` | `deleted` | Boolean | No | `true` if the profile is deleted natively. Default `false`. |
| `unifiedProfile.profiles[]` | `snCreatedTime` | Integer (int64) | No | Social channel created time (epoch milliseconds). |
| `unifiedProfile.profiles[]` | `snModifiedTime` | Integer (int64) | No | Social channel modified time (epoch milliseconds). |
| `unifiedProfile.profiles[]` | `statusCount` | Integer (int32) | No | Status count for the profile. |
| `unifiedProfile.profiles[]` | `accountSpecificInfos` | Array[`AccountSpecificInfo`] | No | Account-specific information. See [§5.4](#54-accountspecificinfo-object). |
| `unifiedProfile` | `demographics` | Object (`Demographics`) | No | Demographic details of the profile. |
| `unifiedProfile` | `profileWorkflow` | Object (`ProfileWorkflow`) | No | Partner-level workflow container. See [§5.5](#55-profileworkflow-and-profilespaceworkflow). |
| `unifiedProfile` | `createdTime` | Integer (int64) | No | Created time of the profile in Sprinklr (epoch milliseconds). |
| `unifiedProfile` | `modifiedTime` | Integer (int64) | No | Last modified time of the profile in Sprinklr (epoch milliseconds). |
| `unifiedProfile` | `customPropertiesMetadata` | Array[`CustomPropertyWithMetadata`] | No | Custom property details. |
| `unifiedProfile` | `restricted` | Boolean | No | Profile masked flag. |


¹ `name`, `channelType`, `channelId`, and `permalink` are listed in the `required` array of the `Profile` schema. Note that **no supplied example sends `permalink`** — including the V2 portal page, which marks it Optional, and the Help Center in-product sample. Treat the OpenAPI `required` list on `Profile` as unverified for this use case.

`UnifiedProfile` additionally carries `works`, `organizations`, `certificates`, `recommendations`, `educations`, `languages`, `skills`, `courses`, `honors`, `patents`, `projects`, `publications`, `testScores`, `voluntaryExp`, and `operatingHours`. None of these are referenced by any supplied CFM example; they are inherited from the shared profile model and are not documented further here. See the Profile API V3 guide for their semantics.

> **⚠️ Conflict to resolve — flat vs nested `unifiedProfile`.**
The supplied `Post-CFM Workflow API` endpoint specification contains a `unifiedProfile` table describing **flat** fields: `id`, `externalId`, `firstName`, `lastName`, `email`, `phoneNumber`, `language`, `country`, `customProperties`.
This contradicts (a) the OpenAPI `UnifiedProfile` schema, which nests these under `contact` / `demographics` / `profileWorkflow`; (b) the V2 portal page, which is nested; and (c) **that same document's own example request**, which is nested (`unifiedProfile.contact.firstName`).
**This guide documents the nested form**, because the OpenAPI schema, the V2 baseline, and every executable example agree. The flat table appears to be an authoring error. See [§12](#12-questions-for-the-api-owner).


> **⚠️ Conflict to resolve — `unifiedProfile` tables placed on the wrong endpoint.**
The `unifiedProfile`, `address`, `accountSpecificInfo`, and `profileSpaceWorkflow` tables appear in the **`/trigger`** endpoint specification. The `/trigger` request schema (`CfmWorkflowTriggerV3Request`) has **no `unifiedProfile` field at all** — it carries only `workflowId` and `contextParams`. Those four tables belong to `/triggerWithNewProfile`, and are documented here accordingly.


### 5.3 `Address` object

`unifiedProfile.contact.address`, schema `Address` — *Describes the schema for Address.*

| Parameter | Type | Required | Description |
|  --- | --- | --- | --- |
| `street1` | String | No | First line of the user's address. |
| `street2` | String | No | Second line of the user's address. |
| `city` | String | No | The city of the user's address, to help identify the location. |
| `state` | String | No | The state of the user's address. |
| `country` | String | No | The country of the user's address. |
| `postalCode` | String | No | ZIP code of the address. |


> **⚠️ Conflict to resolve — address field names.**
The supplied endpoint specification's address table lists `addressLine1`, `addressLine2`, `city`, `state`, `postalCode`, `country`, `countryCode`, `latitude`, `longitude`.
The OpenAPI `Address` schema and the V2 portal page both use `street1`, `street2`, `city`, `state`, `country`, `postalCode` — with **no** `countryCode`, `latitude`, or `longitude`.
**This guide documents the OpenAPI/V2 field names.** Do not send `addressLine1` or geo-coordinates until confirmed. See [§12](#12-questions-for-the-api-owner).


### 5.4 `AccountSpecificInfo` object

`unifiedProfile.profiles[].accountSpecificInfos[]`, schema `AccountSpecificInfo`.

| Parameter | Type | Required | Description |
|  --- | --- | --- | --- |
| `accountId` | Integer (int64) | No | Account ID of the profile. |
| `externalId` | String | No | External ID of the profile. |
| `lastBrandEngagedTime` | Integer (int64) | No | Last brand engagement time (epoch milliseconds). |
| `lastFanEngagedTime` | Integer (int64) | No | Last fan engagement time (epoch milliseconds). |
| `optIn` | Boolean | No | `true` if opted in. Default `false`. |
| `fanSubscriptionState` | String | No | Subscription state of the fan. |
| `activeUser` | Boolean | No | `true` if the user is active. Default `false`. |
| `invited` | Boolean | No | `true` if invited. Default `false`. |


> **⚠️ Conflict to resolve — `accountSpecificInfo` field names.**
The supplied endpoint specification lists `accountId`, `accountName`, `accountType`, `accountStatus`, `customerSince`, `tier`, `region`, `currency`, `customProperties` — a **CRM account** model. The OpenAPI schema and the V2 portal page both describe a **social-account engagement** model (the table above). These are two entirely different objects sharing a name. **This guide documents the OpenAPI/V2 form.** See [§12](#12-questions-for-the-api-owner).


### 5.5 `ProfileWorkflow` and `ProfileSpaceWorkflow`

`unifiedProfile.profileWorkflow`, schema `ProfileWorkflow` — *Describes the schema of partner-level workflow in profile.*

| Parameter | Type | Required | Description |
|  --- | --- | --- | --- |
| `profileLists` | Array[Integer (int64)] | No | Partner profile lists on the profile, if any. |
| `customProperties` | Object (map of String → Array[String]) | No | Partner custom properties on the profile, if any. **Profile-level custom fields are not currently supported** (per V2 documentation). |
| `profileSpaceWorkflows` | Array[`ProfileSpaceWorkflow`] | No | List of client-level workflows on the profile, if any. |


`unifiedProfile.profileWorkflow.profileSpaceWorkflows[]`, schema `ProfileSpaceWorkflow`:

| Parameter | Type | Required | Description |
|  --- | --- | --- | --- |
| `spaceId` | String | **Yes** | Client ID. The only required field on this schema. |
| `modifiedTime` | Integer (int64) | No | Last modified time of the space workflow (epoch milliseconds). |
| `customProperties` | Object (map of String → Array[String]) | No | Client custom properties on the asset, if any. |
| `queues` | Array[`Queue`] | No | Client queue details of the message, if any. |
| `profileLists` | Array[Integer (int64)] | No | Client profile lists on the profile, if any. |
| `tags` | Array[String] | No | Client tags on the profile, if any. |


> **⚠️ Conflict to resolve — `profileSpaceWorkflow` field names.**
The supplied endpoint specification lists `workflowId`, `workflowName`, `workflowType`, `description`, `status`, `triggerType`, `contextParams`, `createdBy`, `createdTime`, `modifiedBy`, `modifiedTime` — that is, a description of **the CFM workflow definition itself**, not of the profile's workspace-scoped workflow container. The OpenAPI schema and V2 portal page both describe the container (the table above), keyed on `spaceId`.
**This guide documents the OpenAPI/V2 form.** Note also the field-name drift: V2 documents this field as `customFields`, whereas V3 OpenAPI declares `customProperties`. See [§7.2](#72-field-and-payload-changes).


### 5.6 Example request

```bash
curl --request POST \
  --url 'https://qa6-api2-v3.sprinklr.com/api/v3/cfmWorkflow/triggerWithNewProfile' \
  --header 'Authorization: {{accessToken}}' \
  --header 'Key: {{apiKey}}' \
  --header 'Content-Type: application/json' \
  --header 'Accept: application/json' \
  --data-raw '{
    "workflowId": "595b4041-6eba-400f-aff0-797f1029c6f2",
    "contextParams": {
      "IGNORE_DEDUP": true,
      "lang": "ar",
      "country": "Jordan",
      "countryCode": "SA",
      "surveyFilled": "true"
    },
    "unifiedProfile": {
      "contact": {
        "firstName": "Alex",
        "lastName": "Doe",
        "email": "alex.doe@example.com",
        "phoneNo": "9876543210"
      },
      "profiles": [
        {
          "name": "Alex Doe",
          "channelType": "EMAIL",
          "channelId": "alex.doe@example.com"
        }
      ]
    }
  }'
```

*Illustrative example. Names, email addresses, and phone numbers are synthetic placeholders, not real customer data.*

**Multi-channel variant** — attach several channel identities so the workflow can select a distribution channel:

```json
{
  "workflowId": "{{workflowId}}",
  "contextParams": {
    "IGNORE_DEDUP": true,
    "lang": "en",
    "country": "India",
    "countryCode": "IN",
    "surveyFilled": "false"
  },
  "unifiedProfile": {
    "contact": {
      "firstName": "Alex"
    },
    "profiles": [
      { "channelType": "WHATSAPP_BUSINESS", "channelId": "918012345678", "name": "Alex Doe" },
      { "channelType": "SMS",               "channelId": "918012345678", "name": "Alex Doe" },
      { "channelType": "EMAIL",             "channelId": "alex.doe@example.com", "name": "Alex Doe" }
    ]
  }
}
```

*Illustrative example, adapted from the V2 developer-portal and Help Center samples with placeholder values.*

### 5.7 Example response

```json
{
  "data": "Success",
  "errors": []
}
```

### 5.8 Response parameters

| Parameter | Type | Description |
|  --- | --- | --- |
| `data` | String | Indicates the outcome of the API request. `"Success"` when the workflow was triggered for the profile. |
| `errors` | Array[`Error`] | Contains any errors encountered during the request. Empty when no errors occurred. |
| `metadata` | Object (`ResponseMetadata`) | Response metadata. Declared on the `APIResponse` envelope; absent from every supplied example. |


## 6. Response format and status codes

### 6.1 The V3 envelope

Both operations declare the shared **`APIResponse`** schema:

```json
{
  "data": {},
  "errors": [],
  "metadata": {}
}
```

| Field | Type | Description |
|  --- | --- | --- |
| `data` | Object | Operation result. For both CFM Workflow operations this is the string `"Success"`. |
| `errors` | Array[`Error`] | Array of error objects. Empty when no errors occurred. |
| `metadata` | Object (`ResponseMetadata`) | Response metadata. |


> **Specification gap.** `APIResponse.data` is declared as `type: object`, but both CFM Workflow operations return a **JSON string**. The `ResponseMetadata` schema is declared with an **empty `properties` map**, so no metadata fields can be documented from the specification, and no supplied example returns a `metadata` key at all for these endpoints. Parse defensively: treat `metadata` as possibly absent.


> **⚠️ Conflict to resolve — the shape of `data`.**
The V2 portal page shows `"data": "\"Success\""` — a JSON string containing an **escaped, quoted** string. Both V3 endpoint specifications show `"data": "Success"` — a plain string. If your V2 integration strips the inner quotes, that stripping must be removed during migration or it will corrupt the V3 value. Confirm the exact V3 serialization. See [§12](#12-questions-for-the-api-owner).


### 6.2 Response codes

Declared in the OpenAPI specification for **both** operations:

| HTTP code | Scenario | Description |
|  --- | --- | --- |
| `200 OK` | Success | The CFM workflow was triggered successfully. |
| `400 Bad Request` | Invalid parameters | Missing `workflowId`, malformed JSON, or an invalid `contextParams`/`unifiedProfile` payload. |
| `401 Unauthorized` | Authentication failed | Invalid or missing `Authorization` token. |
| `403 Forbidden` | Insufficient permissions | The caller lacks the permission required to trigger the workflow. |
| `404 Not Found` | Not found | No matching workflow for the supplied `workflowId`. |


> **Specification gap.** `500 Internal Server Error` is **not declared** on either operation in the OpenAPI specification, unlike the Profile V3 endpoints. This does not mean the API cannot return `5xx`. Build retry handling for `5xx` regardless — see [§10](#10-caveats-and-best-practices). Also, the specification does not state the scenario descriptions above for `400`/`403`/`404`; those are inferred from the request contract and are marked as recommendations, not specification facts.


For the full status-code catalogue see [REST API Error and Status Codes](https://dev.sprinklr.com/) on the developer portal.

## 7. V2 → V3 migration

### 7.1 Endpoint mapping

| V2 | V3 | Notes |
|  --- | --- | --- |
| `POST /api/v2/cfm-workflow/triggerWithNewProfile` | `POST /api/v3/cfmWorkflow/triggerWithNewProfile` | Direct successor. Resource segment renamed from kebab-case `cfm-workflow` to camelCase `cfmWorkflow`. |
| *No V2 equivalent* | `POST /api/v3/cfmWorkflow/trigger` | **New in V3.** Lets you trigger a workflow without constructing a profile payload. |


**The single most important change:** the resource segment is renamed. `cfm-workflow` → `cfmWorkflow`. A find-and-replace on the version string alone (`v2` → `v3`) will produce a 404.

### 7.2 Field and payload changes

| Aspect | API V2 | API V3 | Impact |
|  --- | --- | --- | --- |
| Base path | `/api/v2/cfm-workflow/…` | `/api/v3/cfmWorkflow/…` | Path rewrite required. |
| Operations | 1 endpoint | 2 endpoints | New lightweight `/trigger` option. |
| `workflowId` | Required | Required | No change. |
| `contextParams` | Optional object, key/value pairs | Optional object, `additionalProperties: string` in OpenAPI | Value type possibly narrowed to string — see [§4.1](#41-request-body). |
| `unifiedProfile` | **Required** | Declared **optional** on `/triggerWithNewProfile`; **absent** from `/trigger` | Verify before relying on omission — see [§5.1](#51-request-body). |
| Response envelope | `data` + `errors` | `data` + `errors` + `metadata` (`APIResponse`) | New optional `metadata` key; parse defensively. |
| `data` value | `"\"Success\""` (escaped) | `"Success"` (plain) | Remove any inner-quote stripping. |
| `profileSpaceWorkflow` custom fields | `customFields` | `customProperties` | Rename required. |
| Profile custom properties | *"Profile Level Custom Fields are not supported currently"* | Same limitation carried forward, `profileWorkflow.customProperties` | No change in capability. |


### 7.3 Migration checklist

1. **Update the base URL** to `https://api3.sprinklr.com/{env}/api/v3` — subject to the `{env}` confirmation in [§2](#2-base-urls-and-environments).
2. **Rename the resource segment** from `cfm-workflow` to `cfmWorkflow`. This is not covered by a version-string search-and-replace.
3. **Decide which operation each call site needs.** If a call site always sent the same static `unifiedProfile`, or sent one only to satisfy the V2 required-field rule, move it to `POST /trigger`.
4. **Rename `customFields` to `customProperties`** anywhere you populate `profileSpaceWorkflows[]`.
5. **Stop stripping the escaped quotes** from `data` — V3 returns a plain `"Success"`.
6. **Handle the `metadata` key** on the response envelope, treating it as optional.
7. **Coerce `contextParams` values to strings** until the schema question in [§4.1](#41-request-body) is resolved.
8. **Re-verify your `channelType` values.** They are uppercase and case-sensitive: `EMAIL`, `SMS`, `WHATSAPP_BUSINESS`.
9. **Regression-test the workflow itself**, not just the HTTP call. A `200 OK` with `"Success"` only proves the trigger was accepted.
10. **Run both versions side by side** against a non-production workflow before cutover, and compare the resulting survey distributions.


## 8. Reference values

### 8.1 `channelType` values used in CFM distribution

| Value | Channel | Typical `channelId` |
|  --- | --- | --- |
| `EMAIL` | Email survey distribution | Email address, e.g. `alex.doe@example.com` |
| `SMS` | SMS survey distribution | Phone number in international format, e.g. `918012345678` |
| `WHATSAPP_BUSINESS` | WhatsApp Business survey distribution | Phone number in international format, e.g. `918012345678` |


These three are the channels named in the CFM Workflow API description and used in the V2 and Help Center samples. `channelType` on the `Profile` schema is declared as an open `type: string`, not a closed enum, so the platform-wide channel list also applies. **Values are uppercase and case-sensitive.**

> **Note.** The supplied `/triggerWithNewProfile` QA example uses lowercase `"channelType": "email"`. Every other supplied source — the V2 portal page, the Help Center sample, and the Profile V3 guide — uses uppercase. **Use uppercase.** See [§12](#12-questions-for-the-api-owner).


### 8.2 Conventional `contextParams` keys

| Key | Type in examples | Meaning |
|  --- | --- | --- |
| `IGNORE_DEDUP` | Boolean | Ignore duplicate detection during workflow execution. |
| `lang` | String | Language code used to localize workflow behavior or content, e.g. `ar`, `en`. |
| `country` | String | Country name used as contextual input, e.g. `Jordan`. |
| `countryCode` | String | Two-letter country code, e.g. `SA`, `IN`. |
| `surveyFilled` | String | Whether the survey has been completed, e.g. `"true"`. |


`contextParams` is an **open map**. Any additional key you pass becomes available as a workflow variable to the workflow's conditions and actions. Add extra keys through **Test API Connection** in the workflow record to see them reflected in a generated request.

### 8.3 Workflow actions and conditions reachable from a trigger

Once triggered, the workflow can run any of the elements supported by the CFM Workflow API (Audience Profile) event:

| Bucket | Element | Description |
|  --- | --- | --- |
| Journey Processes | **Trigger Survey Distribution** | Selects an already-created trigger-based survey distribution on Email, SMS, or WhatsApp and fires it based on the workflow conditions. |
| Journey Processes | Custom Field Actions | Sets case or profile custom fields directly, or copies them from workflow variables. |
| Journey Processes | Update Properties | Updates supported custom properties, attributes, or metadata from workflow variables. |
| Journey Processes | Decision Box | Adds a decision point to branch on specific conditions. |
| Communication | Send Resolved Message | Sends a follow-up email, SMS, or WhatsApp message, customizable with workflow variables. |
| Records | Get Records | Retrieves data from Sprinklr entity records for use in later actions or conditions. |
| Utility | Go to Node | Directs flow to a specific node, allowing custom paths. |
| Utility | Add or remove from queues | Adds or removes cases from queues based on workflow conditions. |
| Actions | End Event | Marks the end of the workflow. |
| Actions | Create Record | Creates a new record from workflow information. |
| Actions | Update Record | Modifies an existing record based on triggers or conditions. |


(Source: [Setting Up a CFM Workflow API Event Workflow](https://www.sprinklr.com/help/articles/setting-workflow-trigger-events/setting-up-a-cfm-workflow-api-event-workflow/6807458589cac71a44d0022c))

## 9. Use cases

### 9.1 Cart-abandonment follow-up

A customer abandons a shopping cart. Your commerce platform calls `POST /cfmWorkflow/triggerWithNewProfile` with the shopper's contact details and `contextParams` describing the cart. The workflow updates the profile and triggers a personalized survey or incentive over email or SMS to encourage the customer to complete the purchase. If the customer responds, the team follows up with targeted offers or addresses the issue that caused the abandonment.

### 9.2 Post-purchase feedback collection

After a purchase completes, your order-management system triggers the workflow with transaction context. The workflow sends a personalized survey over the customer's preferred channel. Use `contextParams` to carry order value, product category, and store identifier so the workflow's conditions can route high-value orders to a longer survey.

### 9.3 Cross-channel customer-journey insight

Send a trigger after each key interaction — purchase, profile update, service visit. Because every trigger consolidates into the same unified profile (keyed on `channelId`), you accumulate a complete view of the customer's interactions across channels while still gathering point-in-time feedback.

### 9.4 Known customer, no profile payload

Your CRM already synchronizes profiles into Sprinklr nightly. At event time you only need to fire the workflow. Use `POST /cfmWorkflow/trigger` with `workflowId` and `contextParams` only — no profile construction, smaller payload, fewer moving parts. **This case had no V2 equivalent.**

### 9.5 Localized survey distribution

Set `lang`, `country`, and `countryCode` in `contextParams`. The workflow branches on these values to select a localized survey template and an appropriate distribution channel per market — for example the `"lang": "ar"`, `"country": "Jordan"`, `"countryCode": "SA"` combination used in the reference examples.

### 9.6 Suppressing deduplication for a deliberate re-send

Set `"IGNORE_DEDUP": true` when you intentionally want a second survey to reach a customer who has already been contacted — for example a re-survey after a service recovery. Leave it unset (or `false`) for normal traffic so the platform's duplicate detection protects the customer from survey fatigue.

### 9.7 Multi-channel fallback

Attach `WHATSAPP_BUSINESS`, `SMS`, and `EMAIL` identities in a single `profiles[]` array, as in the [§5.6](#56-example-request) multi-channel variant. The workflow's distribution action can then choose the channel, and you have not had to decide it at trigger time.

### 9.8 Verifying an integration before go-live

Open the workflow record, choose **Test API Connection**, fill in channel type, first name, full name, social network user ID, and any extra `contextParams`, then click **Get API Request**. The `workflowId` is filled in automatically. Add your authentication headers and run the generated request from Postman. A successful execution confirms the API connection before you wire the trigger into your production system flow.

### 9.9 Support-case-closure feedback

When your ticketing system closes a case, trigger the workflow with the case reference in `contextParams`. The workflow sends a post-support satisfaction survey and, based on the response, can create a follow-up record or route the customer to a recovery journey.

## 10. Caveats and best practices

**`"Success"` is an acknowledgement, not a delivery receipt.** The dev note in the endpoint specification is precise: `"Success"` indicates the API endpoint was successful in *triggering* the CFM workflow. Survey delivery happens asynchronously inside the workflow. Do not treat a `200 OK` as proof the customer received anything. Instrument delivery on the workflow side.

**`channelId` is the deduplication key.** Per the V2 documentation, if the `channelId` is unique a new profile is created and a journey is associated with it; otherwise the journey attaches to the existing profile. Get `channelId` normalization right — inconsistent phone-number formatting between systems (with and without country code, with and without `+`) will silently fragment one customer into several profiles.

**Send the same phone number consistently across `SMS` and `WHATSAPP_BUSINESS`.** They are separate `profiles[]` entries with separate `channelType` values but typically the same `channelId`. Both must be present if you want the workflow to be able to choose between them.

**`channelType` is uppercase and case-sensitive.** `email` is not `EMAIL`.

**Do not enable `IGNORE_DEDUP` globally.** It exists for deliberate re-sends. Left on by default it will over-survey your customers and depress response rates.

**Treat `contextParams` as your workflow's public interface.** Every key you send becomes a workflow variable that conditions may reference. Adding a key is safe; renaming or removing one silently breaks the branch that reads it. Version your key names and coordinate changes with whoever owns the workflow canvas.

**Profile-level custom fields are not supported.** The V2 documentation states this explicitly for `profileWorkflow.customProperties`, and no supplied V3 source contradicts it. Use `profileSpaceWorkflows[].customProperties` (workspace-scoped) instead.

**Build retry handling despite the specification.** No `500` is declared on either operation, and no rate limit, idempotency, or retry behavior is documented in any supplied source. Implement exponential backoff on `5xx` and on network timeouts. Note that **these operations are not documented as idempotent** — a retried `POST /triggerWithNewProfile` may fire the workflow twice. Guard retries with your own request-deduplication key until idempotency semantics are confirmed. See [§12](#12-questions-for-the-api-owner).

**Never log request bodies verbatim.** `unifiedProfile.contact` carries names, email addresses, and phone numbers — personally identifiable information. Redact before logging.

**Never embed credentials in code, tickets, or chat.** See the credential-hygiene callout in [§3](#3-authentication-and-common-headers), including the **outstanding rotation action** for the three secrets exposed on IN-12886.

**Parse the response envelope defensively.** `metadata` is declared on `APIResponse` but is absent from every supplied CFM example, and `ResponseMetadata` has no declared properties. Do not require the key to be present.

**Confirm the conflicts in [§12](#12-questions-for-the-api-owner) before publishing this guide.** Nine material contradictions between the ticket, the OpenAPI specification, the endpoint specifications, and the V2 baseline are flagged inline. Several affect the request contract directly.

## 11. Quick reference

### 11.1 CFM Workflow V3 operations

| Operation | Method | Path | Required field | Response |
|  --- | --- | --- | --- | --- |
| Run workflow via event | `POST` | `/api/v3/cfmWorkflow/trigger` | `workflowId` | `{"data": "Success", "errors": []}` |
| Run workflow via event with profile details | `POST` | `/api/v3/cfmWorkflow/triggerWithNewProfile` | `workflowId` | `{"data": "Success", "errors": []}` |


| Item | Value |
|  --- | --- |
| OpenAPI tag | `CFM Workflow V3` |
| Production base URL | `https://api3.sprinklr.com/{env}/api/v3` *(unverified — see §2)* |
| QA6 base URL | `https://qa6-api2-v3.sprinklr.com/api/v3` |
| Request schemas | `CfmWorkflowTriggerV3Request`, `CfmWorkflowTriggerProfileV3Request` |
| Response schema | `APIResponse` (`data`, `errors`, `metadata`) |
| Declared status codes | `200`, `400`, `401`, `403`, `404` |
| Required headers | `Authorization`, `Key`, `Content-Type: application/json`, `Accept: application/json` |
| Distribution channels | `EMAIL`, `SMS`, `WHATSAPP_BUSINESS` |
| Fix version | 26.10 (release date 2026-09-07) |


### 11.2 Related CFM V3 endpoints not covered by this guide

IN-12886 also covers the following. They are listed for orientation only and are **not documented here**.

**Per the IN-12886 description:**

```
GET    /api/v3/cfm/surveyResponses?id=responseId1,responseId2
POST   /api/v3/cfm/surveyResponses
PUT    /api/v3/cfm/surveyResponses?id=responseId1,responseId2
PATCH  /api/v3/cfm/surveyResponses?id=responseId1,responseId2
DELETE /api/v3/cfm/surveyResponses?id=responseId1,responseId2
POST   /api/v3/cfm/surveyResponses/search

GET    /api/v3/cfm/transactions?id=transactionId1,transactionId2
POST   /api/v3/cfm/transactions
DELETE /api/v3/cfm/transactions?id=transactionId1,transactionId2
```

> **⚠️ Conflicts to resolve before documenting these.**
- **Path form.** The ticket says `/api/v3/cfm/surveyResponses` (plural, nested under `cfm`). The QA-verified cURLs and the OpenAPI specification both use `/api/v3/surveyResponse` (singular, **not** nested under `cfm`), plus `/api/v3/surveyResponse/search`. The specification also exposes `/api/v3/surveyTransactions` and `/api/v3/surveyDistribution/transactions/link`, neither of which matches the ticket's `/api/v3/cfm/transactions`.
- **Missing operation.** QA reported on **2026-08-20** that the **`PATCH` API for CFM Survey Response is not available in the latest PR**. The PR includes `GET`, `POST`, `PUT`, `DELETE`, and `POST /search` only. The ticket description still lists `PATCH`.
- **CFM Transaction APIs** were reported by QA as **already covered in another Postman collection**.



The V2 CFM surface for reference: **CFM Workflow API**, **CFM Survey Response APIs** (import, fetch, search, update, delete responses), **CFM Transaction APIs** (create, fetch, delete transactions), and **Generate Personalized Survey Link**. See [Customer Feedback Management | Sprinklr Developer Portal](https://dev.sprinklr.com/customer-feedback-management).

## 12. Questions for the API owner

Suggested owners drawn from IN-12886: **Aman Joshi** (assignee, implementation), **Prateek Agrawal** (reviewer), **Santhosh M.** (QA), **Ruchika Grover** (reporter).

| # | Question | Why it blocks | Suggested owner |
|  --- | --- | --- | --- |
| 1 | Is the resource path `/api/v3/cfmWorkflow/…` (OpenAPI, endpoint specs, QA cURLs) or `/api/v3/cfm/workflow/…` (ticket description)? | Wrong path = 404 for every reader. **Blocking.** | Aman Joshi |
| 2 | Is `/triggerWithNewProfile` in scope for the 26.10 release? It is absent from the ticket description but present in the specification and QA-verified. | Determines whether §5 ships. **Blocking.** | Ruchika Grover |
| 3 | Is `unifiedProfile` genuinely optional on `/triggerWithNewProfile`? If so, how does it differ behaviourally from `/trigger`? | Determines the required-field table and the "which operation do I use" guidance. **Blocking.** | Aman Joshi |
| 4 | Are `contextParams` values restricted to strings, per `additionalProperties: {type: string}`? Every example sends `IGNORE_DEDUP` as a boolean. | Readers will copy an example that may fail schema validation. **Blocking.** | Prateek Agrawal |
| 5 | Which `unifiedProfile` shape is correct — the nested OpenAPI/V2 form, or the flat form in the endpoint specification's table? | Two mutually exclusive request contracts. **Blocking.** | Aman Joshi |
| 6 | Which `Address` field names are correct — `street1`/`street2` (OpenAPI, V2) or `addressLine1`/`addressLine2` + `countryCode`/`latitude`/`longitude` (endpoint spec)? | Field-name mismatch = silently dropped address data. | Aman Joshi |
| 7 | Which `accountSpecificInfo` model is correct — the social-engagement model (OpenAPI, V2) or the CRM-account model (endpoint spec)? | Two different objects sharing one name. | Aman Joshi |
| 8 | Which `profileSpaceWorkflow` model is correct — the `spaceId`-keyed container (OpenAPI, V2) or the workflow-definition model (endpoint spec)? | Same. Also confirm the `customFields` → `customProperties` rename. | Aman Joshi |
| 9 | Is the production V3 base URL `https://api3.sprinklr.com/{env}/api/v3`? No supplied V3 source shows a production host. | Readers cannot go live without it. **Blocking.** | Aman Joshi |
| 10 | Is the `Key` header mandatory on `/trigger`? The QA-verified cURL omits it. | Determines whether the headers table is accurate. | Santhosh M. |
| 11 | Does V3 return `"data": "Success"` (plain) or `"data": "\"Success\""` (escaped, as in V2)? | Affects every migrating client's parser. | Santhosh M. |
| 12 | Which permission governs `403 Forbidden` on these operations, and on which entity? | §3 currently has a gap where the Profile V3 guide states a concrete permission. | Prateek Agrawal |
| 13 | Are these operations idempotent? Is there a request-deduplication key, or will a retried `POST` fire the workflow twice? | Determines safe retry guidance in §10. | Aman Joshi |
| 14 | Are there rate limits on workflow triggers? None are documented in any supplied source. | High-volume integrations need this before go-live. | Aman Joshi |
| 15 | Is `500 Internal Server Error` intentionally undeclared, or is it a specification omission? | Affects error-handling guidance. | Prateek Agrawal |
| 16 | Are `name`, `channelType`, `channelId`, **and `permalink`** all genuinely required on `profiles[]`? No supplied example sends `permalink`. | Readers will copy an example that omits a supposedly required field. | Aman Joshi |
| 17 | Should `channelType` be uppercase? The `/triggerWithNewProfile` QA example uses lowercase `"email"`. | Case sensitivity determines whether a profile resolves. | Santhosh M. |
| 18 | Do the `surveyResponse`/`transaction` endpoints live at `/api/v3/surveyResponse` (spec, QA) or `/api/v3/cfm/surveyResponses` (ticket)? And is `PATCH` shipping in 26.10? | Needed before the companion Survey Response guide can be written. | Aman Joshi |
| 19 | **Action, not a question:** the three credentials exposed in the 2026-08-20 QA comment on IN-12886 must be revoked and regenerated, and the comment redacted. | Live secrets in a Jira comment. **Urgent.** | Santhosh M. |


*All examples in this guide are illustrative and generated from the supplied OpenAPI specification, endpoint specifications, Jira ticket IN-12886, and the V2 developer-portal and Help Center pages. All credentials, names, email addresses, phone numbers, and identifiers are placeholders — none are real customer, account, or production data. No API call was executed and no linting or validation tool was run against the specification while producing this guide. Statements attributed to a source are specification facts; recommendations are explicitly marked as such.*