# Events

> Every webhook event type, when it fires and what its data carries; the envelope.

Source: https://developers.processcart.com/reference/events

Every outbound event type, from the catalog the webhooks subscribe to. A subscription lists concrete types and/or `*`; `*` covers everything except the opt-in types marked below. The payload shape of each event is in the OpenAPI document's `webhooks` object (one entry per type) and summarized here.

| Event | When | `data` | In `*` |
| --- | --- | --- | --- |
| `run.created` | A run was started (by a member, the API, a schedule or a public kickoff form). | `run`; `kickoffLinkId` when a public form started it. | yes |
| `run.updated` | A run's name, priority, labels or due date changed. | `run` + `changes` keyed by attribute (`name`, `priority`, `labels`, `dueAt`), each `{ from, to }`. | yes |
| `run.status_changed` | A run's status changed (active / completed / on_hold / archived), by hand or automatically. | `run` + `changes.status { from, to }`. | yes |
| `run.completed` | Every task is done, or the run was marked completed by hand. | `run`. | yes |
| `run.trashed` | A run moved to Trash — on its own, or with its workflow. | `run` (the lite header `{ id, name, revision, workflow, deletedAt }` when a workflow trash cascaded) + `withWorkflow`. | yes |
| `run.restored` | A run came back from Trash — on its own, or with its workflow. | `run` (lite when a workflow restore cascaded) + `withWorkflow`. | yes |
| `task.ready` | A task became actionable: visible, unlocked and not done. | `run` + `task`. | yes |
| `task.assigned` | A task's assignees were resolved or changed, or the task became actionable for them. | `run` + `task` + `assignees`. | yes |
| `task.completed` | A task was completed. | `run` + `task`. | yes |
| `task.uncompleted` | A done task was reopened, by hand or by a rejected approval. | `run` + `task`; `byApproval` names the approval task whose rejection reopened it. | yes |
| `field.updated` | A field value changed (opt-in: excluded from `*`; `filters.fieldKeys` narrows it). | `run` + `field` (the resource's field entry: key, label, type, format, value, formatted, …) + `field.previous`. | no (opt-in) |
| `approval.requested` | An approval task became actionable for its approvers (again when a decided approval is voided by a reviewed-value change). | `run` + `task`. | yes |
| `approval.decided` | An approval was approved or rejected. | `run` + `task` + `approval { id, decision, comment, decidedBy, decidedByEmail, decidedAt }`. | yes |
| `comment.created` | A comment was posted on a task. | `run` + `task` + `comment { id, authorId, text, mentions }`. | yes |
| `attachment.created` | A file finished uploading to a field or a comment. | `run` + `task` + `attachment { id, filename, size, mime, fieldKey, taskKey, commentId }`. | yes |
| `guest.task_viewed` | A guest first opened their task link (opt-in: excluded from `*`). | `run` + `task` + `guest { email, linkId }`. | no (opt-in) |
| `guest.task_completed` | A guest submitted their task (fires beside `task.completed`, whose actor is the guest). | `run` + `task` + `guest { email, linkId }`. | yes |
| `workflow.published` | A workflow version was published. | `workflow { id, name }` + `version { id, number }`. | yes |
| `schedule.run_created` | A recurrence schedule started a run. | `run` + `schedule { id, name }`. | yes |
| `schedule.created` | A recurrence schedule was created. | `schedule` — the Schedule resource, as `GET /v1/schedules/{id}` returns it. | yes |
| `schedule.updated` | A schedule changed: its settings were edited, it was paused or resumed, or the system paused it. | `schedule` + `change`: `settings`, `paused`, `resumed` or `auto_disabled` (`auto_disabled`: the system paused it, and `schedule.disabledReason` says why). | yes |
| `schedule.deleted` | A schedule was deleted. | `schedule` — its last state. | yes |
| `rule.created` | An automation rule was created. | `rule` — the AutomationRule resource, as `GET /v1/automation-rules/{id}` returns it. | yes |
| `rule.updated` | An automation rule changed: its settings were edited, it was turned on or off, or the system turned it off after repeated failures. | `rule` + `change`: `settings`, `enabled`, `disabled` or `auto_disabled` (`auto_disabled`: the system turned it off, and `rule.disabledReason` says why). | yes |
| `rule.deleted` | An automation rule was deleted. | `rule` — its last state. | yes |
| `webhook.created` | A webhook endpoint was created. | `webhook` — the Webhook resource, as `GET /v1/webhooks/{id}` returns it (never the signing secret). | yes |
| `webhook.updated` | A webhook endpoint changed: its settings were edited, it was enabled or disabled, its secret was rotated, or the system disabled it. | `webhook` + `change`: `settings`, `enabled`, `disabled`, `secret_rotated` or `auto_disabled` (`auto_disabled`: the system disabled it, and `webhook.disabledReason` says why). Never the secret. | yes |
| `webhook.deleted` | A webhook endpoint was deleted. | `webhook` — its last state. | yes |
| `webhook.test` | A test event sent from Settings or `POST /v1/webhooks/{id}/test`. | `webhook { id }`. | yes |

## Configuration events

`schedule.created`, `schedule.updated`, `schedule.deleted`, `rule.created`, `rule.updated`, `rule.deleted`, `webhook.created`, `webhook.updated`, `webhook.deleted` announce the lifecycle of your automations themselves — a webhook, schedule or automation rule created, changed or deleted — so an integration learns by webhook when one is switched off.

- `data.webhook` / `data.schedule` / `data.rule` is the resource exactly as `GET` returns it ([Webhook](https://developers.processcart.com/reference/schemas#webhook), [Schedule](https://developers.processcart.com/reference/schemas#schedule), [AutomationRule](https://developers.processcart.com/reference/schemas#automationrule)); a `*.deleted` event carries its last state. No payload ever carries a signing secret or key material.
- `*.updated` adds `data.change`: for a webhook `settings`, `enabled`, `disabled`, `secret_rotated`, `auto_disabled`; for a schedule `settings`, `paused`, `resumed`, `auto_disabled`; for a rule `settings`, `enabled`, `disabled`, `auto_disabled`. `auto_disabled` means Process Cart turned it off — the resource's `disabledReason` says why; switching something to the state it is already in announces nothing.
- `actor` is the member (`user`), the API key (`api`, with its name), or `system` for an automatic change.
- In `*`, subscribable by name like every other type; automation rules never trigger on them. A disabled or deleted webhook is not delivered to, so its own `disabled`, `auto_disabled` and `webhook.deleted` events reach the workspace's other enabled endpoints only.

## Envelope

Every delivery is one JSON object:

```json
{
  "id": "evt_7f2c1c2e-0f3a-4f0e-9d6c-2b7a4c9e1f00",
  "type": "task.completed",
  "timestamp": "2026-10-07T18:42:11.000Z",
  "org": {
    "id": "0f7c4b3e-5a2d-4e1b-8c9f-1a2b3c4d5e6f",
    "slug": "acme"
  },
  "actor": {
    "kind": "api",
    "keyId": "6a1f0c2d-3b4e-4f5a-8b6c-7d8e9f0a1b2c",
    "name": "Zapier"
  },
  "data": {
    "run": {
      "…": "the full Run resource"
    },
    "task": {
      "…": "the run's task entry"
    }
  }
}
```

- `id` is also the `webhook-id` header — stable across retries and redeliveries; dedupe on it.
- `actor` is who caused the change: `{ kind: "user", userId }` (a member), `{ kind: "guest", email }`, `{ kind: "api", keyId, name }` (an API key), `{ kind: "schedule", scheduleId, name }` (a recurrence schedule started the run), `{ kind: "rule", ruleId, name }` (an automation rule acted) or `{ kind: "system" }` (an automatic change), plus a display `name` for a member when known.
- `data.run` is the full [Run](https://developers.processcart.com/reference/schemas#run) resource except on the cascade variants of `run.trashed` / `run.restored` (a workflow moved to or from Trash), which carry the lite header `{ id, name, revision, workflow, deletedAt }`. `workflow.published`, `webhook.test` and the configuration events carry no `data.run` — route on `type` first.
- Deliveries are not ordered. Order by `data.run.revision` when it matters, and treat an older revision than the one you hold as stale.

See [Webhooks](https://developers.processcart.com/webhooks) for signatures, retries and redelivery.
