# Webhooks

Webhooks let you subscribe to real-time events in Cakewalk and trigger external workflows.

### Setup

To register a webhook, you need to provide:

* Target URL
* Events to subscribe to
* Secret for HMAC verification

<table><thead><tr><th>Event</th><th>Description</th></tr></thead><tbody><tr><td><pre><code>action_task.actionable
</code></pre></td><td>This event is triggered when the action step of the request needs to be executed. e.g. "all the review steps are completed and the task to do the provisioning is ready to be done"</td></tr></tbody></table>

### Event envelope

Each element of the body array is an object with:

| Field       | Type     | Description                                    |
| ----------- | -------- | ---------------------------------------------- |
| `eventType` | `string` | Discriminator; determines the shape of `data`. |
| `data`      | `object` | Event-specific payload.                        |

***

### Event types

#### `test`

**Purpose:** Validates that a registered URL accepts webhook POSTs (webhook verification flow).

**`data`:**

| Field     | Type     | Notes                     |
| --------- | -------- | ------------------------- |
| `message` | `string` | Always `"Hello, World!"`. |

***

#### `action_task.actionable`

**Purpose:** When a user submits a request, the policy dictates whether it requires zero, one, or multiple review steps (for example, a manager may need to approve a "grant access request"). Once all reviews are complete, the process concludes with an "action step" where the task is executed in the third-party system (such as creating the user account in the external application). The system triggers this event when the action step is ready to be executed.

**`data`:**

| Field             | Type                       | Description                                                                        |
| ----------------- | -------------------------- | ---------------------------------------------------------------------------------- |
| `taskId`          | UUID string                | Identifier of the task.                                                            |
| `assignedTo`      | array                      | Users assigned to the task; may be empty. Each item has `id`, `email`, `fullName`. |
| `requestMetadata` | object or omitted / `null` | Context for policy-based request tasks; structure below.                           |

**`requestMetadata` (when present):**

| Field                   | Type             | Description                                                  |
| ----------------------- | ---------------- | ------------------------------------------------------------ |
| `reviewedBy`            | array of users   | Same shape as `assignedTo` items.                            |
| `requestType`           | string           | One of the policy-based request type names (see enum below). |
| `requestedBy`           | user object      | User who requested the action.                               |
| `targetWorkApp`         | object or `null` | `id` (UUID), `name` (display name).                          |
| `permissionLevel`       | object or `null` | `id` (UUID), `name`.                                         |
| `targetUser`            | user or `null`   | Subject user when applicable.                                |
| `triggeredByUsersGroup` | object or `null` | `id` (UUID), `name`.                                         |

**`requestType` possible values** (from `PolicyBasedRequestType` in domain):

* `GrantAccessRequest`
* `RemoveAccessRequest`
* `ArchiveWorkAppRequest`
* `ChangePermissionLevelRequest`
* `AddNewManagedWorkAppRequest`

***

### Examples

#### Test webhook

```json
[
  {
    "eventType": "test",
    "data": {
      "message": "Hello, World!"
    }
  }
]
```

#### Actionable task (with request metadata)

```json
[
  {
    "eventType": "action_task.actionable",
    "data": {
      "taskId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "assignedTo": [
        {
          "id": "7b9e3e2a-1111-4111-8111-111111111111",
          "email": "reviewer@example.com",
          "fullName": "Reviewer Name"
        }
      ],
      "requestMetadata": {
        "reviewedBy": [],
        "requestType": "GrantAccessRequest",
        "requestedBy": {
          "id": "8c0f4f3b-2222-4222-8222-222222222222",
          "email": "requester@example.com",
          "fullName": "Requester Name"
        },
        "targetWorkApp": {
          "id": "9d1e5a4c-3333-4333-8333-333333333333",
          "name": "Example App"
        },
        "permissionLevel": {
          "id": "ae2f6b5d-4444-4444-8444-444444444444",
          "name": "Member"
        },
        "targetUser": {
          "id": "bf3g7c6e-5555-4555-8555-555555555555",
          "email": "target@example.com",
          "fullName": "Target User"
        },
        "triggeredByUsersGroup": {
          "id": "c04h8d7f-6666-4666-8666-666666666666",
          "name": "Engineering"
        }
      }
    }
  }
]
```

#### Batching

Multiple events may appear in one request:

```json
[
  { "eventType": "test", "data": { "message": "Hello, World!" } },
  {
    "eventType": "action_task.actionable",
    "data": {
      "taskId": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
      "assignedTo": [],
      "requestMetadata": null
    }
  }
]
```

***

### JSON Schema

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://cakewalk.internal/schemas/customer-webhook-events.json",
  "title": "CakewalkCustomerWebhookEventBatch",
  "description": "JSON array POSTed to customer webhook URLs.",
  "type": "array",
  "items": { "$ref": "#/$defs/webhookEvent" },
  "$defs": {
    "uuid": {
      "type": "string",
      "format": "uuid"
    },
    "webhookUser": {
      "type": "object",
      "additionalProperties": false,
      "required": ["id", "email", "fullName"],
      "properties": {
        "id": { "$ref": "#/$defs/uuid" },
        "email": { "type": "string" },
        "fullName": { "type": "string" }
      }
    },
    "webhookWorkApp": {
      "type": "object",
      "additionalProperties": false,
      "required": ["id", "name"],
      "properties": {
        "id": { "$ref": "#/$defs/uuid" },
        "name": { "type": "string" }
      }
    },
    "webhookPermissionLevel": {
      "type": "object",
      "additionalProperties": false,
      "required": ["id", "name"],
      "properties": {
        "id": { "$ref": "#/$defs/uuid" },
        "name": { "type": "string" }
      }
    },
    "webhookUsersGroup": {
      "type": "object",
      "additionalProperties": false,
      "required": ["id", "name"],
      "properties": {
        "id": { "$ref": "#/$defs/uuid" },
        "name": { "type": "string" }
      }
    },
    "policyBasedRequestTypeName": {
      "type": "string",
      "enum": [
        "GrantAccessRequest",
        "RemoveAccessRequest",
        "ArchiveWorkAppRequest",
        "ChangePermissionLevelRequest",
        "AddNewManagedWorkAppRequest"
      ]
    },
    "requestMetadata": {
      "type": "object",
      "additionalProperties": false,
      "required": ["reviewedBy", "requestType", "requestedBy"],
      "properties": {
        "reviewedBy": {
          "type": "array",
          "items": { "$ref": "#/$defs/webhookUser" }
        },
        "requestType": { "$ref": "#/$defs/policyBasedRequestTypeName" },
        "requestedBy": { "$ref": "#/$defs/webhookUser" },
        "targetWorkApp": {
          "anyOf": [{ "$ref": "#/$defs/webhookWorkApp" }, { "type": "null" }]
        },
        "permissionLevel": {
          "anyOf": [{ "$ref": "#/$defs/webhookPermissionLevel" }, { "type": "null" }]
        },
        "targetUser": {
          "anyOf": [{ "$ref": "#/$defs/webhookUser" }, { "type": "null" }]
        },
        "triggeredByUsersGroup": {
          "anyOf": [{ "$ref": "#/$defs/webhookUsersGroup" }, { "type": "null" }]
        }
      }
    },
    "testEventData": {
      "type": "object",
      "additionalProperties": false,
      "required": ["message"],
      "properties": {
        "message": { "type": "string", "const": "Hello, World!" }
      }
    },
    "actionTaskActionableData": {
      "type": "object",
      "additionalProperties": false,
      "required": ["taskId", "assignedTo"],
      "properties": {
        "taskId": { "$ref": "#/$defs/uuid" },
        "assignedTo": {
          "type": "array",
          "items": { "$ref": "#/$defs/webhookUser" }
        },
        "requestMetadata": {
          "anyOf": [{ "$ref": "#/$defs/requestMetadata" }, { "type": "null" }]
        }
      }
    },
    "webhookEvent": {
      "oneOf": [
        {
          "type": "object",
          "additionalProperties": false,
          "required": ["eventType", "data"],
          "properties": {
            "eventType": { "type": "string", "const": "test" },
            "data": { "$ref": "#/$defs/testEventData" }
          }
        },
        {
          "type": "object",
          "additionalProperties": false,
          "required": ["eventType", "data"],
          "properties": {
            "eventType": { "type": "string", "const": "action_task.actionable" },
            "data": { "$ref": "#/$defs/actionTaskActionableData" }
          }
        }
      ]
    }
  }
}
```
