# Webhooks

- **Applies to:** Sprinklr Webhook Subscription API V3 (`/api/v3/webhook-subscriptions`)
- **V2 API reference:** [Sprinklr Webhooks | Sprinklr Developer Portal](https://dev.sprinklr.com/sprinklr-webhooks)


## 1. Overview

A webhook (also called a web callback or HTTP push API) enables third-party services to send real-time updates to your app. Updates are triggered by an event that occurs in Sprinklr, and the data is delivered to your endpoint immediately as it happens. Webhooks are also referred to as "Reverse APIs" — unlike typical APIs where you poll frequently for data, Sprinklr pushes the event to you, which is more efficient for both provider and consumer.

The Webhook Subscription API V3 manages the subscriptions that deliver those platform events to your endpoints. It supports listing and fetching, creating, updating, and deleting subscriptions, activating, deactivating, or verifying a subscription, and listing all webhook types.

V3 collapses the V2 endpoint family onto **two paths plus one action path**, differentiated by HTTP method and a query parameter:

| Operation | Method | Path |
|  --- | --- | --- |
| List or fetch webhook subscriptions | `GET` | `/api/v3/webhook-subscriptions` |
| Create webhook subscription | `POST` | `/api/v3/webhook-subscriptions` |
| Update webhook subscription | `PUT` | `/api/v3/webhook-subscriptions?subscriptionId=` |
| Delete webhook subscription | `DELETE` | `/api/v3/webhook-subscriptions?subscriptionId=` |
| Activate, deactivate, or verify a subscription | `POST` | `/api/v3/webhook-subscriptions/action?subscriptionId=&action=` |
| List all webhook types | `GET` | `/api/v3/webhook-subscriptions/webhook-types` |


### 1.1 The subscription lifecycle

1. **Expose a callback URL.** It must be publicly reachable and must answer a `POST` with an empty payload (`{}`) with a `2XX` response. See [§10 Callback URL verification check](#10-caveats-and-best-practices).
2. **Create the subscription** — `POST /api/v3/webhook-subscriptions`. A newly created subscription comes back with `"verified": false` and `"active": false`.
3. **Verify it** — `POST /api/v3/webhook-subscriptions/action?subscriptionId=…&action=verify`.
4. **Activate it** — `POST /api/v3/webhook-subscriptions/action?subscriptionId=…&action=activate`. Only then does Sprinklr start dispatching events.
5. **Maintain it** — update the subscribed types with `PUT`, pause delivery with `action=deactivate`, remove it with `DELETE`.


### 1.2 The subscription data model

| Layer | Field | What it holds |
|  --- | --- | --- |
| Identity | `id`, `name`, `description` | Subscription ID and human-readable labels |
| Delivery | `url`, `preSharedKey`, `viaProxy` | Where events are pushed and how the payload is signed |
| Event selection | `subscriptions[]`, `filteredSubscriptions[]` | Which webhook types fire, and optional per-type attribute filters |
| State | `verified`, `active`, `lastSuccessTimestamp`, `lastFailedTimestamp` | Verification/activation state and last delivery outcomes |


## 2. Base URLs and environments

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

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

So the webhook subscription resource in production is:

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

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

## 3. Authentication and common headers

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

| Header | Value | Purpose | Required on |
|  --- | --- | --- | --- |
| `Authorization` | `Bearer {{accessToken}}` | Authenticates the user with the server | All requests |
| `Key` | `{{apiKey}}` | The API key acts as both a unique identifier and a secret token for authentication to a set of access rights | All requests |
| `Content-Type` | `application/json` | Request format should be JSON, as the endpoint expects a JSON body | `POST`, `PUT` |
| `Accept` | `application/json` | Declares the acceptable response type | All requests |


## 4. Write operations

### 4.1 Create a webhook subscription

**`POST /api/v3/webhook-subscriptions`**

Creates a webhook subscription. The response returns the subscription `id`, which you need for every other operation. A new subscription is created with `verified: false` and `active: false`.

#### Request body — `WebhookSubscriptionCreateRequest`

| Parameter | Sub-parameter | Required | Type | Description |
|  --- | --- | --- | --- | --- |
| `name` |  | Required | String | The name of the webhook subscription. |
| `description` |  | Optional | String | The description of the webhook subscription. |
| `subscriptions` |  | Conditional | Array[String] | The list of webhook types on which you want to create the subscription. Either `subscriptions` or `filteredSubscriptions` must be provided. |
| `filteredSubscriptions` |  | Conditional | Array[Object] | The list of subscriptions with filters. Either `subscriptions` or `filteredSubscriptions` must be provided. |
|  | `webhookType` | Required | String | Webhook type the filter set applies to. |
|  | `filters` | Optional | Array[Object] | Subscription filters. See the filter table below. |
| `url` |  | Required | String | The URL of the webhook endpoint. |
| `preSharedKey` |  | Required | String | An authorization key that can be used to confirm if the request is valid. A valid webhook will have a header `X-Hub-Signature` with value `sha256={sha256 digested payload using the preSharedKey}`. |
| `viaProxy` |  | Optional | Boolean | If `true`, the webhooks are dispatched via Sprinklr proxy. |


#### `filters[]` — `Filter_webhooks`

| Parameter | Required | Type | Description |
|  --- | --- | --- | --- |
| `id` | Required | String | Filter identifier. |
| `type` | Required | String | Filter type — for example `PARTNER_CUSTOM_PROPERTY`, `ACCOUNT_TYPE`. |
| `checkCondition` | Required | String | Filter check condition, for example `IS`, `IS_NOT`. |
| `values` | Required | Array[String] | Filter values. |


#### Request

```bash
curl --location 'https://api3.sprinklr.com/{env}/api/v3/webhook-subscriptions' \
--header 'Authorization: Bearer {{accessToken}}' \
--header 'Key: {{apiKey}}' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--data-raw '{
  "name": "My Webhook",
  "url": "https://mycallback.com",
  "preSharedKey": "{{preSharedKey}}",
  "subscriptions": [
    "CASE_CREATED"
  ]
}'
```

#### Response — `201 Created`

```json
{
    "data": {
        "id": "6a1d7399e944edfa60817e9d",
        "name": "My Webhook",
        "subscriptions": [
            "CASE_CREATED"
        ],
        "filteredSubscriptions": [
            {
                "webhookType": "CASE_CREATED"
            }
        ],
        "url": "https://mycallback.com",
        "preSharedKey": "secret",
        "viaProxy": false,
        "verified": false,
        "active": false
    },
    "errors": []
}
```

Note that the platform echoes the flat `subscriptions` array back as a `filteredSubscriptions` entry with no `filters` — a subscription with no filters is equivalent to an unfiltered subscription on that type.

#### Creating with filters

```bash
curl --location 'https://api3.sprinklr.com/{env}/api/v3/webhook-subscriptions' \
--header 'Authorization: Bearer {{accessToken}}' \
--header 'Key: {{apiKey}}' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--data-raw '{
  "name": "API test",
  "description": "Webhook for case creation.",
  "subscriptions": [
    "CASE_CREATED"
  ],
  "filteredSubscriptions": [
    {
      "webhookType": "CASE_CREATED",
      "filters": [
        {
          "id": "ACCOUNT_TYPE",
          "type": "ACCOUNT_TYPE",
          "checkCondition": "IS",
          "values": [
            "Whatsapp_Business"
          ]
        }
      ]
    }
  ],
  "url": "https://mycallback.com",
  "preSharedKey": "{{preSharedKey}}"
}'
```

### 4.2 Update a webhook subscription

**`PUT /api/v3/webhook-subscriptions?subscriptionId={subscriptionId}`**

Updates the name, description, and subscribed webhook types of an existing subscription. The update is **incremental on subscription types** — you add and remove types rather than resubmitting the full list.

#### Query parameters

| Parameter | Required | Type | Description |
|  --- | --- | --- | --- |
| `subscriptionId` | Required in practice | String | The Sprinklr webhook `subscriptionId`. |


#### Request body — `WebhookSubscriptionUpdateDTO`

| Parameter | Required | Type | Description |
|  --- | --- | --- | --- |
| `name` | Optional | String | The name of the webhook subscription. |
| `description` | Optional | String | The description of the webhook subscription. |
| `addSubscriptions` | Optional | Array[String] | Add subscriptions to the list of subscribed Sprinklr webhook types. |
| `removeSubscriptions` | Optional | Array[String] | Remove subscriptions from the list of subscribed Sprinklr webhook types. |


#### Request

```bash
curl --location --request PUT 'https://api3.sprinklr.com/{env}/api/v3/webhook-subscriptions?subscriptionId=6a1e8c2d4adcdb00e372fc37' \
--header 'Authorization: Bearer {{accessToken}}' \
--header 'Key: {{apiKey}}' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--data-raw '{
    "name": "vaibhav_api_4",
    "description": "updated the string",
    "addSubscriptions": [
        "CASE_CREATED"
    ],
    "removeSubscriptions": [
        "CASE_UPDATED"
    ]
}'
```

#### Response — `204 No Content`

The response returns `204 No Content` with an empty body.

### 4.3 Delete a webhook subscription

**`DELETE /api/v3/webhook-subscriptions?subscriptionId={subscriptionId}`**

Deletes a Sprinklr webhook subscription.

| Parameter | Required | Type | Description |
|  --- | --- | --- | --- |
| `subscriptionId` | Required in practice | String | The webhook `subscriptionId`. |


```bash
curl --location --request DELETE 'https://api3.sprinklr.com/{env}/api/v3/webhook-subscriptions?subscriptionId=6a1d7399e944edfa60817e9d' \
--header 'Authorization: Bearer {{accessToken}}' \
--header 'Key: {{apiKey}}' \
--header 'Accept: application/json'
```

The endpoint returns `204 No Content` on success.

### 4.4 Activate, deactivate, or verify a subscription

**`POST /api/v3/webhook-subscriptions/action?subscriptionId={subscriptionId}&action={action}`**

Performs a lifecycle action on an existing subscription. This single V3 endpoint replaces the three separate V2 endpoints for verify, activate, and deactivate.

#### Query parameters

| Parameter | Required | Type | Description |
|  --- | --- | --- | --- |
| `subscriptionId` | Required | String | The webhook `subscriptionId`. |
| `action` | Required | String | Action to perform: `activate`, `deactivate`, or `verify`. |


| `action` value | Effect |
|  --- | --- |
| `verify` | Runs the callback URL verification check against the configured `url`. Sets `verified` to `true` on success. |
| `activate` | Activates the subscription so Sprinklr dispatches matching events. Sets `active` to `true`. |
| `deactivate` | Deactivates the subscription and stops dispatch. Sets `active` to `false`. |


#### Request

```bash
curl --location --request POST 'https://api3.sprinklr.com/{env}/api/v3/webhook-subscriptions/action?subscriptionId=6a0d7df617ab2359996fb225&action=verify' \
--header 'Authorization: Bearer {{accessToken}}' \
--header 'Key: {{apiKey}}' \
--header 'Accept: application/json'
```

#### Response — `200 OK`

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

`data` is `true` when the action succeeds, otherwise `false`.

## 5. Read operations

### 5.1 `GET /api/v3/webhook-subscriptions` — List or fetch subscriptions

Returns one subscription when `subscriptionId` is supplied, or a page of subscriptions when it is not. This single endpoint replaces the V2 *Read Subscription* and *Read All Subscription* endpoints.

#### Query parameters

| Parameter | Required | Type | Description |
|  --- | --- | --- | --- |
| `subscriptionId` | Optional | String | Subscription id(s), comma-separated. Omit to list all subscriptions. |
| `pageNumber` | Optional | String | Page number (0-based). |
| `pageSize` | Optional | String | Page size. |
| `sinceTime` | Optional | String | Pagination cursor. |


#### Request

```bash
curl --location 'https://api3.sprinklr.com/{env}/api/v3/webhook-subscriptions?subscriptionId=6a0d7df617ab2359996fb225' \
--header 'Authorization: Bearer {{accessToken}}' \
--header 'Key: {{apiKey}}' \
--header 'Accept: application/json'
```

#### Response — `200 OK`

```json
{
    "data": [
        {
            "id": "6a0d7df617ab2359996fb225",
            "name": "SALESFORCE - Paris_test",
            "description": "Webhook subscription for SALESFORCE connector: Paris_test",
            "subscriptions": [
                "CASE_CREATED",
                "CASE_UPDATED"
            ],
            "filteredSubscriptions": [
                {
                    "webhookType": "CASE_CREATED",
                    "filters": [
                        {
                            "id": "6a0d7fa117ab23599970b714",
                            "type": "PARTNER_CUSTOM_PROPERTY",
                            "checkCondition": "IS",
                            "values": [
                                "DEV"
                            ]
                        }
                    ]
                },
                {
                    "webhookType": "CASE_UPDATED",
                    "filters": [
                        {
                            "id": "6a0d7fa117ab23599970b714",
                            "type": "PARTNER_CUSTOM_PROPERTY",
                            "checkCondition": "IS",
                            "values": [
                                "DEV"
                            ]
                        }
                    ]
                }
            ],
            "url": "https://qa6-std-connector-tier1.sprinklr.com/crm/SALESFORCE/6a0d7dc917ab2359996f90db?sprPartnerId=66000000",
            "viaProxy": false,
            "verified": true,
            "active": true,
            "lastSuccessTimestamp": 1779270302235
        }
    ],
    "errors": []
}
```

`data` is always an array on this endpoint, even when a single `subscriptionId` is requested.

#### Response fields — `WebhookSubscriptionConfigAPIResponse`

| Field | Type | Description |
|  --- | --- | --- |
| `id` | String | The subscription ID associated with the subscription you created via an API call or in the Sprinklr UI. |
| `name` | String | Name of the webhook subscription. |
| `description` | String | Description of the webhook subscription. |
| `subscriptions` | Array[String] | List of Sprinklr webhook types subscribed. |
| `filteredSubscriptions` | Array[Object] | The list of subscriptions with filters (`webhookType` plus `filters[]`). |
| `url` | String | The URL of the webhook endpoint. |
| `preSharedKey` | String | An authorization key that can be used to confirm if the request is valid. A valid webhook will have a header `X-Hub-Signature` with value `sha256={sha256 digested payload using the preSharedKey}`. |
| `viaProxy` | Boolean | If `true`, the webhooks are dispatched via Sprinklr proxy. |
| `verified` | Boolean | `true` if the webhook subscription is verified. |
| `active` | Boolean | `true` if the webhook subscription is active. |
| `lastSuccessTimestamp` | Integer (int64) | Last success timestamp of the webhook, in epoch milliseconds. |
| `lastFailedTimestamp` | Integer (int64) | Last failed timestamp of the webhook, in epoch milliseconds. |


### 5.2 `GET /api/v3/webhook-subscriptions/webhook-types` — List all webhook types

Returns every webhook subscription type available in your environment. Use the returned `type` value in `subscriptions[]` or `filteredSubscriptions[].webhookType` when creating or updating a subscription. This endpoint takes no parameters.

```bash
curl --location 'https://api3.sprinklr.com/{env}/api/v3/webhook-subscriptions/webhook-types' \
--header 'Authorization: Bearer {{accessToken}}' \
--header 'Key: {{apiKey}}' \
--header 'Accept: application/json'
```

#### Response — `200 OK` (truncated)

```json
{
    "data": [
        {
            "type": "ACCOUNT_CREATED",
            "label": "Account Created Event",
            "category": "Account"
        },
        {
            "type": "CASE_CREATED",
            "label": "Case Created",
            "category": "Case"
        }
    ],
    "errors": []
}
```

#### Response fields — `WebhookType`

| Field | Type | Description |
|  --- | --- | --- |
| `type` | String | Webhook type. Use this value in `subscriptions[]`. |
| `label` | String | Label of the webhook type, as shown in the Sprinklr UI. |
| `category` | String | Parent category of the webhook type. |


## 6. Response format and status codes

### 6.1 The V3 envelope

Every V3 webhook subscription endpoint that returns a body returns the standard envelope:

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

| Field | Type | Description |
|  --- | --- | --- |
| `data` | Array / Object / Boolean | Payload of the operation. Array on `GET /webhook-subscriptions` and `GET /webhook-subscriptions/webhook-types`, object on `POST /webhook-subscriptions`, boolean on `POST /webhook-subscriptions/action`. |
| `errors` | Array[Error] | Array of error objects (empty if no errors). Each `Error` carries `id`, `code`, and `message`. |


### 6.2 Response codes

| HTTP code | Scenario | Description |
|  --- | --- | --- |
| `200 OK` | Success | Subscriptions or webhook types returned; action performed (`data: true`). |
| `201 Created` | Success | Subscription created. Observed in the Postman collection; not declared in `sprinklr-v3.yaml`. |
| `204 No Content` | Success | Update succeeded with no response body. Observed in the Postman collection; `sprinklr-v3.yaml` declares `200` with a `string` schema. |
| `400 Bad Request` | Invalid parameters | Missing required parameters or invalid parameter combinations. |
| `401 Unauthorized` | Authentication failed | Invalid or missing `Authorization` token. |
| `403 Forbidden` | Insufficient permissions | Caller lacks permission on the webhook subscription entity. |
| `404 Not Found` | Not found | No subscription matches the supplied `subscriptionId`. |


`400`, `401`, `403`, and `404` are the four shared responses declared on all six operations in `sprinklr-v3.yaml`. No `429` or `5xx` response is declared anywhere in the V3 specification.

## 7. V2 → V3 migration

### 7.1 Endpoint mapping

| V2 | V3 |
|  --- | --- |
| `POST /api/v2/webhook-subscriptions` | `POST /api/v3/webhook-subscriptions` |
| `GET /api/v2/webhook-subscriptions/{subscriptionId}` (Read Subscription) | `GET /api/v3/webhook-subscriptions?subscriptionId=` |
| Read All Subscription | `GET /api/v3/webhook-subscriptions` (omit `subscriptionId`) |
| Update Subscription | `PUT /api/v3/webhook-subscriptions?subscriptionId=` |
| `DELETE /api/v2/webhook-subscriptions/{subscriptionId}` | `DELETE /api/v3/webhook-subscriptions?subscriptionId=` |
| Verify Subscription | `POST /api/v3/webhook-subscriptions/action?subscriptionId=&action=verify` |
| `POST /api/v2/webhook-subscriptions/{subscriptionId}/activate` | `POST /api/v3/webhook-subscriptions/action?subscriptionId=&action=activate` |
| `POST /api/v2/webhook-subscriptions/deactivate` | `POST /api/v3/webhook-subscriptions/action?subscriptionId=&action=deactivate` |
| `GET /api/v2/webhook-subscriptions/webhook-types` | `GET /api/v3/webhook-subscriptions/webhook-types` |


### 7.2 Key changes

| Aspect | API V2 | API V3 | Impact |
|  --- | --- | --- | --- |
| Subscription addressing | Path segment `/{subscriptionId}` | Query parameter `?subscriptionId=` | Rebuild every URL; V3 never puts the ID in the path. |
| Verify / activate / deactivate | Three distinct endpoints, two of them path-based | One `POST /webhook-subscriptions/action` with an `action` query parameter | Collapse three client methods into one. |
| Update verb | `POST` | `PUT` | Change the HTTP method on the update call. |
| Read single vs. read all | Two endpoints | One `GET`, switched by presence of `subscriptionId` | Merge two client methods; `data` is an array in both cases. |
| Pagination | Not documented on the V2 read pages | `pageNumber`, `pageSize`, `sinceTime` query parameters | New capability on `GET /webhook-subscriptions`. |
| Multi-ID fetch | One ID per call | `subscriptionId` accepts comma-separated IDs | Batch reads in a single call. |


## 8. Supported webhook types

The following 91 types across 32 categories were returned by `GET /api/v3/webhook-subscriptions/webhook-types` in the supplied collection. Available types are environment-dependent — always call the endpoint rather than hard-coding this list.

| Type | Label | Category |
|  --- | --- | --- |
| `ACCOUNT_CREATED` | Account Created Event | Account |
| `ACCOUNT_UPDATED` | Account Updated Event | Account |
| `AUDIENCE_ACTIVITY_CREATED` | Audience Activity | Activity |
| `ASSET_GROUP_CREATED` | Asset Group Created | Asset Group |
| `ASSET_GROUP_DELETED` | Asset Group Deleted | Asset Group |
| `ASSET_GROUP_UPDATED` | Asset Group Updated | Asset Group |
| `ASSIGNMENT_CHANGE` | Assignment Change | Assignment Change |
| `BUSINESS_HOLIDAY_LIST_CREATED` | Business Holiday List Created | Business Holiday List |
| `BUSINESS_HOLIDAY_LIST_UPDATED` | Business Holiday List Updated | Business Holiday List |
| `BUSINESS_HOURS_CREATED` | Business Hours Created | Business Hours |
| `BUSINESS_HOURS_UPDATED` | Business Hours Updated | Business Hours |
| `CAMPAIGN_CREATED` | Campaign Created | Campaign |
| `CAMPAIGN_DELETED` | Campaign Deleted | Campaign |
| `CAMPAIGN_UPDATED` | Campaign Updated | Campaign |
| `CASE_CREATED` | Case Created | Case |
| `CASE_DELETED` | Case Deleted | Case |
| `CASE_UPDATED` | Case Updated | Case |
| `MESSAGE_ASSOCIATION_CHANGE` | Message Association Change | Case |
| `COMMENT_CREATED` | Comment Created | Comment |
| `COMMENT_UPDATED` | Comment Updated | Comment |
| `COMMUNITY_MESSAGE_CREATED` | Community Message Created | Community |
| `COMMUNITY_USER_CREATED` | Community User Created | Community |
| `COMMUNITY_USER_UPDATED` | Community User Updated | Community |
| `API_COMPLIANCE_EVENT` | API Compliance event | Compliance |
| `CUSTOM_FIELD_CREATED` | Custom Field Created | Custom Field |
| `CUSTOM_FIELD_UPDATED` | Custom Field Updated | Custom Field |
| `DIGITAL_ASSET_CREATED` | Asset Created | DAM |
| `DIGITAL_ASSET_DELETED` | Asset Deleted | DAM |
| `DIGITAL_ASSET_UPDATED` | Asset Updated | DAM |
| `TEMPLATE_ASSET_CREATED` | Template Asset Created | DAM |
| `TEMPLATE_ASSET_DELETED` | Template Asset Deleted | DAM |
| `TEMPLATE_ASSET_UPDATED` | Template Asset Updated | DAM |
| `DRAFT_CREATED` | Draft Created | Draft |
| `DRAFT_SCHEDULED` | Draft Scheduled | Draft |
| `DRAFT_UPDATED` | Draft Updated | Draft |
| `SMART_RESPONSE_FEEDBACK` | Feedback given on smart responses | Intuition |
| `KB_CONTENT_CREATED` | Knowledge Base Content Created | Knowledge Base |
| `KB_CONTENT_DELETED` | Knowledge Base Content Deleted | Knowledge Base |
| `KB_CONTENT_UPDATED` | Knowledge Base Content Updated | Knowledge Base |
| `MESSAGE_APPROVAL_REJECTED` | Message Approval Rejected | Message |
| `MESSAGE_BOUNCED` | Message Bounced | Message |
| `MESSAGE_COMPLAINT` | Message Complaint | Message |
| `MESSAGE_DELETED` | Message Deleted | Message |
| `MESSAGE_DELIVERED` | Message Delivered | Message |
| `MESSAGE_DELIVERY_DELAYED` | Message Delivery Delayed | Message |
| `MESSAGE_ENGAGEMENT_UPDATED` | Message Engagement Updated | Message |
| `MESSAGE_FAILED` | Message Failed | Message |
| `MESSAGE_PUBLISH_FAILED` | Message Publish Failed | Message |
| `MESSAGE_PUBLISHED` | Message Published | Message |
| `MESSAGE_READ` | Message Read | Message |
| `MESSAGE_CREATED` | Message Received | Message |
| `MESSAGE_REJECTED` | Message Rejected | Message |
| `MESSAGE_RENDERING_FAILED` | Message Rendering failed | Message |
| `MESSAGE_SENT` | Message Sent | Message |
| `MESSAGE_SENT_FOR_APPROVAL` | Message Sent For Approval | Message |
| `MESSAGE_SUBSCRIPTION_UPDATED` | Message Subscription Updated | Message |
| `MESSAGE_UPDATED` | Message Updated | Message |
| `OUTBOUND_MESSAGE_CHANNEL_EVENT` | Outbound Message Channel Event | Message |
| `OUTBOUND_WORKFLOW_UPDATED` | Outbound Workflow Updated | Message |
| `POST_TREND_METRICS_CHANGE` | Post Trend Metrics Change | Message |
| `SOURCE_AGNOSTIC_MESSAGE_CREATED` | Source Agnostic Message Created | Message |
| `SOURCE_AGNOSTIC_MESSAGE_EDITED` | Source Agnostic Message Edited | Message |
| `PROFILE_CREATED` | Profile Created | Profile |
| `PROFILE_DELETED` | Profile Deleted | Profile |
| `PROFILE_SUBSCRIBED` | Profile Subscribed | Profile |
| `PROFILE_UNSUBSCRIBED` | Profile Unsubscribed | Profile |
| `PROFILE_UPDATED` | Profile Updated | Profile |
| `PROFILES_MERGED` | Profiles Merged | Profile |
| `RECOMMENDATION_CREATED` | Recommendation Created Event | Recommendation |
| `SURVEY_RESPONSE_CREATED` | Survey Response Created | Survey Response |
| `TASK_CREATE` | Task Create | Task |
| `TASK_DELETE` | Task Delete | Task |
| `TASK_UPDATE` | Task Update | Task |
| `THREAD_CONTROL_UPDATED` | Thread Control Updated | Thread Control |
| `UI_LOG_CREATED` | UI Log Created | UI Logging |
| `USER_CREATED` | User Create | User |
| `USER_DELETED` | User Delete | User |
| `USER_UPDATED` | User Update | User |
| `USER_ACTIVITY_CREATED` | User Activity Created | User Activity |
| `USER_CURRENT_STATE` | User Current State | User Current State |
| `VOICE_CALL_EVENT_UPDATES` | Voice Call Event Updates | Voice Call Event Updates |
| `VOICE_CALL_QUALITY_EVENT` | Voice Call Quality Event | Voice Call Quality Event |
| `WORK_QUEUE_CREATED` | Work Queue Create | Work Queue |
| `WORK_QUEUE_DELETED` | Work Queue Delete | Work Queue |
| `WORK_QUEUE_UPDATED` | Work Queue Update | Work Queue |
| `WORKFLOW_UPDATED` | Workflow Updated | Workflow |


Event payload shapes for each type are documented on the V2 portal under [Webhook Response Payloads](https://dev.sprinklr.com/webhook-response-payloads). The payload contract is unchanged by the V3 subscription API — V3 changes how you *manage* subscriptions, not what Sprinklr posts to your callback URL.

## 9. Use cases

### 9.1 Stand up a new case-event integration

1. `GET /webhook-subscriptions/webhook-types` — confirm `CASE_CREATED` and `CASE_UPDATED` are available.
2. `POST /webhook-subscriptions` with `name`, `url`, `preSharedKey`, and `"subscriptions": ["CASE_CREATED","CASE_UPDATED"]`. Store the returned `id`.
3. `POST /webhook-subscriptions/action?subscriptionId={id}&action=verify` — expect `"data": true`.
4. `POST /webhook-subscriptions/action?subscriptionId={id}&action=activate`.
5. `GET /webhook-subscriptions?subscriptionId={id}` — confirm `"verified": true` and `"active": true`.


### 9.2 Restrict a subscription to one segment

Create the subscription with `filteredSubscriptions` instead of `subscriptions`, setting `type` to `PARTNER_CUSTOM_PROPERTY`, `checkCondition` to `IS`, and `values` to the property values you want, so only matching cases are dispatched. The `GET` example in [§5.1](#51-get-apiv3webhook-subscriptions--list-or-fetch-subscriptions) shows this shape on a live subscription.

### 9.3 Add an event type to a running integration

`PUT /webhook-subscriptions?subscriptionId={id}` with `"addSubscriptions": ["CASE_CREATED"]`. Use `removeSubscriptions` in the same call to drop types you no longer want. There is no need to deactivate and recreate the subscription.

### 9.4 Pause delivery during a downstream outage

`POST /webhook-subscriptions/action?subscriptionId={id}&action=deactivate` while your consumer is down, then `action=activate` when it is back. Deactivating stops dispatch without losing the subscription configuration. For events missed while deactivated, see the Webhook Replay and Retrieve API — failed webhook events are retrievable for **7 days**.

### 9.5 Audit every subscription in a workspace

`GET /webhook-subscriptions` with no `subscriptionId`, paging with `pageNumber` and `pageSize`. Inspect `lastSuccessTimestamp` and `lastFailedTimestamp` on each record to find subscriptions whose endpoints have started failing.

### 9.6 Rotate a callback endpoint

No V3 operation updates `url` or `preSharedKey` on an existing subscription. Create a new subscription against the new URL, verify and activate it, confirm delivery, then `DELETE` the old one.

## 10. Caveats and best practices

**Callback URL verification check**

- For any callback URL to work within a webhook subscription, a `POST` to that URL with an **empty payload** (`{}`) must return a `2XX` response.
- Test it directly before calling `action=verify`:

```bash
curl -X POST 'https://{Callback Url}' \
--header 'Content-Type: application/json' \
--data-raw '{}'
```
- The callback URL must be publicly reachable over the internet.


**Webhook retries logic**

- Sprinklr's webhook retries logic works on a count of **10 seconds**. Once the webhook is triggered, Sprinklr waits **10 seconds** to receive an HTTP `200` status code.
- If a webhook cannot be delivered successfully, it is retried **three times** through different queues (Queue 1 → Queue 2 → Queue 3) until the request receives a `200`. Events that fail all three consecutive tries are stored in the **Deleted Queue**.
- The default 10-second window is **unalterable** — changing it would delay every webhook in the queue.
- Use an **asynchronous webhook endpoint that returns `200 OK` within 10 seconds**. This avoids congestion at either the sender's or the receiver's end.


**Payload signing**

- The payload is signed with the `preSharedKey` using SHA-256 and added to the header `X-Hub-Signature` with the value `sha256={sha256 digested payload using the preSharedKey}`. Validate this signature on every inbound request.
- `preSharedKey` is **required** on create. Never log it or commit it.


**Lifecycle**

- A newly created subscription is `verified: false` and `active: false`. It dispatches nothing until it is verified and activated.
- `verify` and `activate` are separate actions — performing one does not perform the other.


**Parameters**

- `subscriptionId` on `GET` accepts **comma-separated** IDs; on `PUT`, `DELETE`, and `/action` supply exactly one.
- Do not wrap query values in braces. `{6a0d7df617ab2359996fb225}` is a Postman placeholder artifact, not a value format.
- `pageNumber` is **0-based** and is typed as `string` in `sprinklr-v3.yaml`, as are `pageSize` and `sinceTime`.


**Responses**

- `data` is an array on `GET /webhook-subscriptions` even for a single-ID fetch.
- `POST /webhook-subscriptions/action` returns a boolean in `data` — `true` on success, `false` otherwise. Inspect it; a `200` alone does not prove the action succeeded.
- Always inspect the `errors` array even on a `200` response.


**Authentication types**

- The V3 create schema exposes only `preSharedKey` and `viaProxy`. The additional authentication types available in the Sprinklr UI — Salesforce, Public URL, Basic Auth, OAuth 2.0, External Authentication Credentials, and Marketplace Apps — have no representation in the V3 request schema. Configure those in the UI (see [Create and Manage Webhook Subscription in Sprinklr](https://www.sprinklr.com/help/articles/platform-modules/create-and-manage-webhook-subscription-in-sprinklr/633c5c2b59534970b26f96da))


**Rate limiting and server errors**

- No `429` or `5xx` response is declared for these operations in `sprinklr-v3.yaml`. Implement retry with exponential backoff defensively rather than relying on the specification.