---
updatedAt: 2026-08-10T23:26:46.000Z
---

Fetch the complete documentation index at: https://documentation.telegramd.com/llms.txt. Use this file to discover all available pages before exploring further.

# Webhooks v2 — Overview

## What changed in v2

Webhooks v2 introduces two independent improvements:

| Feature             | v1 (legacy)                           | v2                                                                            |
| ------------------- | ------------------------------------- | ----------------------------------------------------------------------------- |
| Payload versioning  | Full raw event objects, including PHI | Sanitized envelopes with per-category allowlists                              |
| Signature header    | `sha256={base64_hmac}` over body only | `t={unix_ts},sha256={base64_hmac}` over `t.body` — replay protection included |
| `api_version` field | Not present                           | `"2026-08-09"` (Journey events: `"2026-08-06"`)                               |

Existing webhooks default to **v1**. Newly created webhooks default to **v2**.

***

## Payload versioning

Every v2 payload carries a fixed `api_version` field:

```json
{
  "event_type": "order_created",
  "event_id": "event::abc123",
  "api_version": "2026-08-09",
  "timestamp": "2026-05-30T14:00:00.000Z",
  "affiliate_id": "aff::xyz",
  "order_id": "order::abc"
}
```

The `api_version` value for most v2 envelopes is `2026-08-09`. It identifies the payload schema and will be bumped if a breaking change is ever made. Journey-native events are the exception and use `"2026-08-06"` (see [Versioning guarantees](#versioning-guarantees)).

> ⚠️ `timestamp` is the **delivery-attempt time**, not the event's creation time — it is regenerated on every retry. Don't use it to order or dedupe events; use `event_id` for dedup and reconcile state per entity for ordering (see [Delivery & Retries](./delivery-and-retries)).

### PHI sanitization — per-category allowlists

PHI is removed from v2 payloads at dispatch time. Each event category has an explicit allowlist governing which `eventData` fields pass through; any field not on the list is stripped before delivery. `patient_id` does not appear on any category's allowlist below — but every v2 payload, regardless of category, also carries four patient-identity fields (`patient_id`, `patient_external_id`, `patient_marketing_consent`, `is_returning_patient`) added by a separate, always-on enrichment step that isn't governed by the category allowlist at all.

| Category     | Allowed fields                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| ORDER        | `order_id`, `order_status`, `case_status`, `case_id`, `ecommerce_order_id`, `journey_id`, `commerce_status`, `product_variation_ids`, `product_display_names`, `subscription_status`, `total_value_cents`, `currency`, `order_tag`, `patient_conversation_id`, `channel_type`, `visit_type`, `visit_id`, `external_case_identifier`, `external_case_status`, `order_asset_id`, `unlocked_at`, `order_external_identifier`, `asset_link`, `titration_config_id`, `titration_direction`, `config_name`, `status_transition`, `questionnaire_id`, `location_id`, `previous_product_variation_id`, `current_product_variation_ids`, `future_product_variation_ids`, `current_pv_count`, `future_pv_count`, `future_prescriptions_to_create`, `video_requested`, `reason`, `message_type`, `order_link`, `reminder_type` |
| PRESCRIPTION | `prescription_id`, `prescription_status`, `pharmacy_id`, `order_id`, `commerce_status`, `product_variation_ids`, `product_display_names`, `visit_id`, `video_requested`, `reason`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| SHIPPING     | `order_id`, `prescription_id`, `shipment_status`, `commerce_status`, `tracking_number`, `tracking_url`, `shipping_carrier`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| PHARMACY     | `prescription_id`, `pharmacy_id`, `pharmacy_status`, `order_id`, `commerce_status`, `reason`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| PAYMENT      | `order_id`, `total_value_cents`, `currency`, `payment_status`, `consultation_id`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| LAB          | `lab_order_id`, `lab_order_status`, `order_id`, `commerce_status`, `interpretation`, `lab_name`, `external_order_id`, `provider_order_status`, `reported_at`, `provider_event_type`, `latest_provider_event_status`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| SUPPORT      | `support_case_id`, `support_case_status`, `support_case_name`, `support_case_category`, `order_id`, `external_case_identifier`, `external_case_status`, `external_case_url`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| JOURNEY      | `journey_id`, `template_id`, `template_display_name`, `journey_type`, `ecommerce_order_id`, `started_at`, `completed_at`, `abandoned_at`, `total_value_cents`, `currency`, `products`, `coupon_code`, `recovery_url`, `recovery_url_expires_at`, `commerce_status`, `product_variation_ids`, `product_display_names`, `subscription_status`, `attribution`                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| COMMERCE     | `ecommerce_order_id`, `subscription_id`, `subscription_status`, `commerce_status`, `total_value_cents`, `currency`, `payment_status`, `product_variation_ids`, `product_display_names`, `journey_id`, `order_id`, `refund_amount_cents`, `refund_type`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| PATIENT      | *(empty — no `eventData` fields exposed beyond the universal patient-identity fields above)*                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| INTERNAL     | *(empty — no `eventData` fields exposed beyond the universal patient-identity fields above)*                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |

There is no `SUBSCRIPTION` or `CHANNEL` category — subscription fields (`subscription_id`, `subscription_status`) are exposed under `COMMERCE` and `ORDER`/`JOURNEY` instead.

Beyond the allowlist, a separate blocklist strips known-PHI keys (`email`, `phone`, `firstName`/`lastName`, `dateOfBirth`, `address`/`city`/`state`/`zip`, `medications`, `allergies`, `diagnosis`, `clinicalNotes`, credentials/tokens, and others) as defense in depth if they ever appear on an allowlisted path.

### Field coverage on v2 payloads

The allowlist above only keeps an `eventData` field if its *name* matches an allowlist entry (directly, or via a small alias table). Events introduced alongside the v2 payload system (Journey, Commerce/subscription, Payment events) use field names that match their category's allowlist, so their v2 payloads carry full detail. Patient events (`patient_enrolled`) carry full detail too, but for a different reason — their entire meaningful payload is the universal patient-identity fields described above, not anything from the (empty) `PATIENT` category allowlist.

Most events now include their event-specific fields directly in v2 payloads. Where detail is not included in the payload itself, it is retrievable through the authenticated API using the entity IDs the payload delivers — v2 payloads are designed as *notifications*, not data transfers. Status reasons and order-history details are retrievable through dedicated endpoints without requiring v1 payloads.

***

## Migration path

1. Create a new webhook or use the upgrade endpoint to switch an existing webhook to v2 payload delivery.
2. Update your consumer to verify the new signature format (see [Signature Verification](./webhook-signature-v2)).
3. Remove any code that expects PHI fields — they will not appear in v2 payloads.
4. If you need to roll back from v2 to v1, use the rollback endpoint (requires master token).

***

## Event dictionary

The webhook dictionary defines **59 event types**, of which **56 are publicly subscribable** by affiliates. Two are internal-only (never delivered to affiliate webhooks), and one additional public event (`pharmacy_rejected_prescription`) is defined but not yet implemented — it is excluded from subscription (56 + 2 + 1 = 59). All 56 subscribable events are emitted by live code paths. To retrieve the full list programmatically:

```http
GET /webhooks/actions/getDictionary
```

Note this endpoint lives on the legacy v1 webhook management API (`/webhooks/...`), not the `/v2/webhooks/...` module — it predates payload versioning and works the same regardless of which payload version your webhook is configured for. See the [getDictionary endpoint](../IAS%20API%20Documentation/webhooks-2/webhooksactionsgetdictionary) for the response shape.

For a complete per-event breakdown of which fields are guaranteed, conditional, or not delivered, see [Field Guarantees](./field-guarantees).

For narrative documentation of individual events (purpose, example payload), see the event pages under each category: Order, Prescription, Pharmacy, Lab, Payment, Journey, Commerce, Patient, and Support Events.

***

## Versioning guarantees

* Most v2 envelopes use `api_version: "2026-08-09"`. This replaced `"2026-05-24"` when marketing attribution was extended beyond journey events — see [Attribution Passthrough](./journey-events/attribution-passthrough). The change is additive: consumers that ignore unknown fields need no action.
* **Exception — Journey-native events** (`journey_checkout_started`, `journey_completed`, `journey_abandoned`) always use `api_version: "2026-08-06"`, including when the optional `attribution` key is omitted. See [Attribution Passthrough](./journey-events/attribution-passthrough).
* Within a given `api_version`, fields are additive (never removed or renamed). Adding a significant new block such as `attribution` may still bump `api_version` so documentation and consumers can target the schema explicitly — as with the Journey bump to `"2026-08-06"`.
* Breaking changes (field removal, rename, type change) always bump `api_version` and are announced in advance.