# Webhook

A webhook is an HTTPS URL of yours that receives a `POST` with a JSON body when an event happens. Two ways to subscribe:

- **A Webhook resource** — [`POST /webhooks`](/reference/webhook/webhooks-create) with a `url` and an `event`. Delivers that event for every resource of the application.
- **`webhookUrl` on a resource** — set when creating an Item, a Connect Token or a Payment Request. Delivers every event, but only for that resource (or the Items created with that token).

## Webhook resource

```http
POST https://api.pluggy.ai/webhooks
X-API-KEY: {apiKey}
Content-Type: application/json

{
  "url": "https://example.com/pluggy",
  "event": "item/updated",
  "headers": { "X-CLIENT-ID": "…" }
}
```

| Field | Required | Meaning |
| --- | --- | --- |
| `url` | yes | HTTPS only. `localhost` is not accepted — use a tunnel such as ngrok while developing. |
| `event` | yes | One event from the tables below, `item/all` for every Item event, or `all` for everything. |
| `headers` | no | Sent with every delivery to this URL — the way to pass an API key your endpoint requires. Only configurable through the API, never shown in the dashboard. |

Endpoints: [`GET /webhooks`](/reference/webhook/webhooks-list), [`POST /webhooks`](/reference/webhook/webhooks-create), and retrieve, update and delete on [`/webhooks/{id}`](/reference/webhook).

## Events

**Data**

| Event | Fires when |
| --- | --- |
| `item/created` | An Item was created and connected successfully. |
| `item/updated` | An Item was updated and synced successfully. |
| `item/deleted` | An Item was deleted. |
| `item/error` | An execution ended in error; `USER_AUTHORIZATION_PENDING` also fires this. |
| `item/waiting_user_input` | The Item needs input from the user (MFA) to continue. |
| `item/waiting_user_action` | The Item needs the user to act on their device — authorise in the bank app, scan a QR code. |
| `item/login_succeeded` | Login at the institution succeeded; data collection is running. |
| `connector/status_updated` | A connector changed status (`ONLINE`, `UNSTABLE`, `OFFLINE`). Carries `connectorId`. |
| `transactions/created` | New transactions after an update; carries `createdTransactionsLink` to fetch them. |
| `transactions/updated` | Transactions changed after an update; carries their ids. |
| `transactions/deleted` | Transactions removed after an update; carries their ids. |

Transaction events fire only when something changed; an update with no new transactions emits no `transactions/created`.

**Payments**

| Event | Fires when |
| --- | --- |
| `payment_intent/created` | A payment intent was created for a request. |
| `payment_intent/waiting_payer_authorization` | The intent needs the payer's authorisation. |
| `payment_intent/completed` | The intent completed. |
| `payment_intent/error` | The intent failed. |
| `payment_request/updated` | A payment request changed status. |
| `scheduled_payment/created`, `/completed`, `/error`, `/canceled` | One scheduled payment of an authorisation moved. |
| `scheduled_payment/all_created`, `/all_completed` | Every scheduled payment of an authorisation was created / completed. |
| `automatic_pix_payment/created`, `/completed`, `/error`, `/canceled` | A payment of an Automatic PIX request moved. |
| `smart_transfer_preauthorization/completed`, `/error` | A Smart Transfer pre-authorisation was approved, or failed. |
| `smart_transfer_payment/completed`, `/error` | A Smart Transfer payment settled, or failed. |

## Payload

Every notification carries:

| Field | Meaning |
| --- | --- |
| `event` | The event name. |
| `eventId` | Identifies the event; the same value when one event is delivered to several URLs. |
| `triggeredBy` | `USER` (a Connect Token, e.g. the widget), `CLIENT` (an API Key, e.g. a `PATCH`), `SYNC` (auto-sync) or `INTERNAL` (Pluggy support). Absent on `item/deleted`, `connector/status_updated` and `transactions/deleted`. |
| the entity's id | `itemId` on Item events, `transactionIds` on transaction events, `connectorId` on connector events, and so on per event. |
| `clientUserId` | On `item/*` events only — the value set through the Connect Token's `options`. Not on `transactions/*`: map those to your user through `itemId`. |

```json
{
  "event": "item/updated",
  "eventId": "d876fd7c-e9bd-4c4c-bd46-cc96c62aac29",
  "itemId": "a5c763cb-0952-457b-9936-630f79c5b016",
  "triggeredBy": "SYNC",
  "clientUserId": "your-user-id"
}
```

## Delivery and retries

A delivery succeeds when your endpoint answers `2xx` **within 5 seconds**. Respond first, process afterwards — a slow handler is counted as a failure and retried.

On failure: three consecutive attempts; if all fail, three more after 1 hour; if those fail, a final three after 2 hours. Up to **9 deliveries** of one event. Exception: `item/login_succeeded` gets the three consecutive attempts only, with no delayed retries.

Read the guide: [Webhook](/docs/developer-tools/webhooks-ref) — payload examples per event, and troubleshooting.