# Webhooks

Webhooks are used to communicate changes in transactions. You can subscribe on multiple events types for the same transaction when creating the transaction. A transaction will have an optional field called "webhooks" where you can specify the webhook for a specific event. If you don't specify any webhooks, none will be sent.

## Key Considerations

> 🚧 webhooks are only a "best effort" mechanism
>
> In the payment process, it is essential to stay informed about the status of a transaction (e.g., whether it has been successfully paid or has expired).
>
> Receiving a webhook notification (if configured) is helpful, but you should not depend on it to check the transaction details.
>
> Once a transaction is created, you can retrieve its latest details at any time, and **it is your responsibility to do so**.
>
> For example, if a transaction has been created and a significant amount of time has passed without receiving a webhook notification, but you suspect the payment status may have changed, then you can directly request the latest details to verify whether the status has been updated.

## Webhook events

Each event type can be used at most once per transaction. A URL can have multiple events.

```json json
{
  ...
   "webhooks": [
    {
      "url": "https://yourdomain.tld/statuschange?purchaseId=order123",
      "events": [
        "FINALSTATUS","STATUS_CHANGE"
      ]
    },
    {
      "url": "https://yourdomain.tld/refundchange?purchaseId=order123",
      "events": [
        "REFUND_STATUS"
      ]
    }
  ]
  ...
}
```

All event types:

| Webhook Events       | Description                                                                              |
| :------------------- | :--------------------------------------------------------------------------------------- |
| `FINALSTATUS`        | When the status of the transaction becomes `SUCCESS`, `CANCELLED`, `EXPIRED`, `FAILURE`. |
| `STATUS_CHANGE`      | When the status of the transaction has any change.                                       |
| `REFUND_STATUS`      | When the status of a refund on the transaction has changed.                              |
| `QR_PAYMENT_CREATED` | When a payment is created using an iDEAL QR code.                                        |

Not all transaction types support the same webhook events. Below is a list specifying which event types are available per transaction type.

| Transaction type        | Supported Webhook Events                                              |
| :---------------------- | :-------------------------------------------------------------------- |
| Checkout transaction    | `FINALSTATUS`, `STATUS_CHANGE`, `REFUND_STATUS`                       |
| iDEAL transaction       | `FINALSTATUS`, `STATUS_CHANGE`, `REFUND_STATUS`                       |
| iDEAL QR transaction    | `FINALSTATUS`, `STATUS_CHANGE`, `REFUND_STATUS`, `QR_PAYMENT_CREATED` |
| Credit Card transaction | `FINALSTATUS`, `STATUS_CHANGE`, `REFUND_STATUS`                       |
| Bancontact transaction  | `FINALSTATUS`, `STATUS_CHANGE`, `REFUND_STATUS`                       |
| Apple Pay transaction   | `FINALSTATUS`, `STATUS_CHANGE`, `REFUND_STATUS`                       |
| Google Pay transaction  | `FINALSTATUS`, `STATUS_CHANGE`, `REFUND_STATUS`                       |
| in3 transaction         | `FINALSTATUS`, `STATUS_CHANGE`                                        |

## Request Body

```json
{
  "createdAt": "2006-01-02T15:04:05Z",
  "event": "FINALSTATUS",
  "transaction": "8db1e7fa-ba8a-4189-92fd-67a20217443d",
  "reference": "20210623130413",
  "payment": "fe77cd5f-2054-432d-b1c7-f019282785b2"
}
```

## Parameters

| Parameter   | Type            | Description                                                            | Constraints                                                                                       |
| :---------- | :-------------- | :--------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------ |
| createdAt   | String(RFC3339) | The creation time of the webhook.                                      | ISO 8601 date and time.                                                                           |
| event       | String          | The event that triggered the webhook.                                  | The possible values are: `FINALSTATUS`, `STATUS_CHANGE` , `REFUND_STATUS`,  `QR_PAYMENT_CREATED`. |
| transaction | String(36)      | The unique identifier of the transaction to which the webhook belongs. |                                                                                                   |
| reference   | String(1...255) | The `reference` you provided in the original transaction request       |                                                                                                   |

## Optional parameters

| Parameter | Type       | Description                                                  | Constraint                                                     |
| :-------- | :--------- | :----------------------------------------------------------- | :------------------------------------------------------------- |
| payment   | String(36) | The unique identifier of a payment related to a transaction. | Only for specific webhook events such as `QR_PAYMENT_CREATED`. |

## What to do after receiving a webhook

A webhook call on its own does not contain the information you usually require to update the transaction in your application. Best practice is to see the webhook as a trigger. This trigger should then cause your application to GET the transaction. This insures you have the latest data and that the data originates from CM.com instead of being spoofed.

## Error handling

In cases where your response is not a `2xx` status code we will retry the webhook at a later time. We will attempt up to 50 deliveries over a span of about 14 days for the same webhook. If the webhook was not delivered successfully within that time, it will be discarded and not tried again.

> 📘 Our webhook mechanism uses a circuit breaker pattern, by temporarily blocking requests to a host after detecting a certain number of consecutive failures, allowing time for the issue to resolve before trying again.