# Zendesk webhook trigger

> Run a workflow on Zendesk Support ticket events: created, status and tag changes, spam, merges, and deletes, with signature verification.

Source: https://cotera.co/docs/reference/webhooks/zendesk

---

Run a workflow on Zendesk Support ticket events — a ticket is created, its status or tags change, it's marked as spam or merged. The ticket event becomes the workflow's input, so you can triage, route, or sync it.

For behavior shared by every provider (the delivery URL, testing), see the [webhook triggers reference](https://cotera.co/docs/reference/webhooks.md).

## Prerequisites

Zendesk webhooks are **auto-registered**: Cotera creates the webhook for you over Zendesk's API, using a connected Zendesk account (OAuth or API token). Without one, install fails with `zendesk_credentials_missing`.

## Setup

1. Add a **From an app** trigger and pick **Zendesk**.
2. Choose the event (see below).
3. Save. Cotera creates a Zendesk webhook subscribed to that event, pointed at the trigger's unique URL, and reads back its signing secret.

Deleting the trigger removes the webhook from Zendesk.

## Events

The event key maps to a Zendesk ticket event type; deliveries carry it in the payload's `type` field as `zen:event-type:<key>`.

| Event key                      | Fires when                                        |
| ------------------------------ | ------------------------------------------------- |
| `ticket.created`               | A new ticket is created                           |
| `ticket.status_changed`        | A ticket's status changes (including when solved) |
| `ticket.custom_status_changed` | A ticket's custom status changes                  |
| `ticket.tags_changed`          | Tags are added to or removed from a ticket        |
| `ticket.marked_as_spam`        | A ticket is marked as spam                        |
| `ticket.merged`                | Tickets are merged                                |
| `ticket.soft_deleted`          | A ticket is soft deleted                          |
| `ticket.undeleted`             | A previously deleted ticket is restored           |

## Payload

The Zendesk event payload is passed through as the workflow input. `detail` holds a snapshot of the ticket; `event` holds the change-specific data. A `ticket.status_changed` delivery looks like:

```json
{
  "type": "zen:event-type:ticket.status_changed",
  "id": "01ARZ3NDEKTSV4RRFFQ69G5FAW",
  "time": "2023-07-15T11:00:00Z",
  "account_id": 12345,
  "zendesk_event_version": "1",
  "detail": {
    "id": "987654",
    "status": "solved",
    "priority": "high",
    "subject": "Unable to log in",
    "assignee_id": "222",
    "requester_id": "777",
    "group_id": "555",
    "tags": ["login", "urgent"],
    "via": { "channel": "email" },
    "created_at": "2023-07-15T10:30:00Z",
    "updated_at": "2023-07-15T11:00:00Z"
  },
  "event": {
    "previous": "open",
    "current": "solved",
    "meta": { "version": "1", "occurred_at": "2023-07-15T11:00:00Z" }
  }
}
```

| Field    | Description                                                                                                                                  |
| -------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| `type`   | The event type, prefixed `zen:event-type:`.                                                                                                  |
| `id`     | The event's unique id (a ULID), used to deduplicate retries.                                                                                 |
| `time`   | When the event was emitted.                                                                                                                  |
| `detail` | The ticket snapshot: `id`, `status`, `priority`, `subject`, assignee/requester/group ids, `tags`, `via`, and timestamps.                     |
| `event`  | The change-specific payload — for `ticket.status_changed`, `previous` / `current`; for `ticket.tags_changed`, `tags_added` / `tags_removed`. |

## Signature verification

Zendesk signs each delivery with the `X-Zendesk-Webhook-Signature` header — a base64 HMAC-SHA256 over `<timestamp><raw-body>`, where the timestamp comes from the `X-Zendesk-Webhook-Signature-Timestamp` header. The signing secret is read from Zendesk when the webhook is created, so there's no per-trigger secret for you to manage. Cotera verifies it on every delivery and rejects anything that fails.

