> ## Documentation Index
> Fetch the complete documentation index at: https://docs.talview.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Webhook Concepts

> Key behavioral rules that apply across all Talview webhook event types.

Understanding these concepts will help you correctly interpret webhook payloads and build reliable integrations.

***

## Event Naming Convention

Every webhook event follows a consistent naming pattern:

| Format                                | Example                 |
| :------------------------------------ | :---------------------- |
| **Subscription Key** (dot-separated)  | `can.candidate.created` |
| **Event Type** (underscore-separated) | `can_candidate_created` |

Events are always one of three operations: `created`, `updated`, or `deleted`.

***

## Payload Visibility Rules

All webhook payloads follow two strict visibility rules:

| Excluded Field | Reason                                                                                                                                                                                |
| :------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `tenant_id`    | Implicit from your subscription context. Your webhook subscription is scoped to your tenant, so this field is redundant.                                                              |
| `is_deleted`   | Internal soft-delete flag. Instead of seeing `is_deleted: true`, you will receive a `deleted` event. Subordinate arrays in payloads are pre-filtered to exclude soft-deleted records. |

<Note>
  If you previously relied on `tenant_id` in payloads, note that it is no longer included. Your subscription already scopes events to your tenant.
</Note>

***

## Subordinate Bubble-Up

Talview webhooks operate on **root-level objects** only. When a nested (subordinate) record changes, the system does not fire a separate event for the subordinate. Instead, the parent root object's `updated_at` is touched in the same database transaction, which fires an `updated` event on the root with **the full current payload**.

### Example

Adding an education record to a candidate does **not** produce a `can.education.created` event. Instead, it triggers a `can.candidate.updated` event containing the candidate's complete profile, including the new education entry in the `education` array.

### Why this design?

* **Simplicity**: Consumers subscribe to a small set of root events instead of tracking dozens of subordinate tables.
* **Consistency**: Every `updated` payload is a complete snapshot of the root object — no need to merge partial updates.
* **Atomicity**: The subordinate change and the root's `updated_at` touch happen in the same transaction, preventing ordering issues.

***

## Versioned-Snapshot Objects

Most root objects have a dedicated history table (e.g., `sch.meeting_history`, `pay.transaction_status_history`) that records prior states. For these objects, `updated` event payloads contain only the **current** state.

However, some objects have no history table. These are called **versioned-snapshot** objects, and their `updated` payloads include both the previous and current state:

```json theme={null}
{
  "old": { /* previous state */ },
  "new": { /* current state */ }
}
```

### Objects with versioned-snapshot behavior

| Root Object         | Reason                                                                                                                    |
| :------------------ | :------------------------------------------------------------------------------------------------------------------------ |
| `frm.form_instance` | No `form_instance_history` table exists. The `old` key provides the complete previous row so consumers can compute diffs. |

<Tip>
  Check each event's documentation page to see whether `old` state is included in `updated` payloads.
</Tip>

***

## Cross-Service Payloads

Some root objects aggregate data from multiple services to provide full context in a single payload. This means the webhook delivers a rich, denormalized view — no additional API calls needed.

| Root Object         | Services Joined                             | What's Included                                                                                                                  |
| :------------------ | :------------------------------------------ | :------------------------------------------------------------------------------------------------------------------------------- |
| `coordinator.exam`  | coordinator, workflow-tools, scheduler, pm  | Workflow steps, drive schedules, rooms, and proctoring center details.                                                           |
| `pm.center`         | pm, workflow-tools, scheduler, geo-location | Workflow steps, drive schedules with rooms and seats, operating schedule with availabilities and overrides, geographic location. |
| `ae.test_instance`  | assessment-engine, candidate, evaluation    | Candidate snapshot, catalog/assessment metadata, measurement scores and attributes.                                              |
| `pay.transaction`   | payment, order                              | Full order chain including order items, SKUs, and applied coupons.                                                               |
| `sch.meeting`       | scheduler, auth                             | Participant list with user identity snapshots from the auth service.                                                             |
| `incident.instance` | incident, session                           | Session snapshot with status and score from the session service.                                                                 |
