# Notifications

Notifications are sent every time:

- a status change occurs on a Transaction, Subscription, or Authorization
- an error occurs when trying to confirm a Transaction, Subscription, or Authorization
- a new payment is generated or not after a charge to an Authorization
- a new payment is generated or not due to a Subscription
- actions are performed on a Sale


A `POST` notification is sent to the URL defined in the `notify_url` field provided when the object was created.

> Since the notification URL is defined when creating the object, in the `notify_url` field, the URL can be dynamic, allowing it to be different for each created object.


## Recommended logic

The simplest way to implement notification logic is:

1. Use the `notification_type` field to identify what event has occurred.
2. Check the `fail` field: if it contains an error code, the notification corresponds to a failed event; if it is `null`, the event was successful.


## notification_type values

The `notification_type` field is always present in all notifications.

### Transaction

| Value | Description |
|  --- | --- |
| `transaction_confirmation_error` | The customer attempted to pay and failed |
| `transaction_expired` | Transaction expired |
| `transaction_cancelled` | Transaction cancelled |
| `transaction_rejected_by_rules` | Transaction rejected by fraud rules |


### Subscription

| Value | Description |
|  --- | --- |
| `subscription_confirmation_error` | The customer attempted to confirm the subscription and failed |
| `subscription_done` | Subscription confirmed |
| `subscription_expired` | Subscription expired |
| `subscription_cancelled` | Subscription cancelled |
| `subscription_rejected_by_rules` | Charge rejected by fraud rules |
| `subscription_paused` | Subscription paused |
| `subscription_stopped` | Subscription stopped |
| `subscription_started` | Subscription started |
| `subscription_actived` | Subscription activated |
| `subscription_charge_error` | Error when attempting to charge an active subscription |


### Authorization

| Value | Description |
|  --- | --- |
| `authorization_confirmation_error` | The customer attempted to confirm the authorization and failed |
| `authorization_done` | Authorization confirmed |
| `authorization_expired` | Authorization expired |
| `authorization_cancelled` | Authorization cancelled |
| `authorization_rejected_by_rules` | Authorization rejected by fraud rules |
| `authorization_removed` | Authorization removed |
| `authorization_charge_error` | Error when attempting to charge the authorization |


### Sale

| Value | Description |
|  --- | --- |
| `sale_created` | Payment completed. Can correspond to a confirmed transaction, a subscription charge, or an authorization charge. Use the `type` field to distinguish: `P` = Transaction, `S` = Subscription, `A` = Authorization |
| `sale_refund` | Refund completed |
| `sale_refund_in_process` | Refund in process |
| `sale_capture` | Capture of a payment that was on hold |
| `sale_void` | Release of a payment |
| `sale_settled` | Payment settled |


### Transfer

| Value | Description |
|  --- | --- |
| `transfer_completed` | Transfer completed |
| `transfer_failed` | Transfer failed |


### Marketplace

| Value | Description |
|  --- | --- |
| `client_compliance` | Client compliance verification |
| `wallet_compliance` | Wallet compliance verification |
| `iban_compliance` | IBAN compliance verification |


## Notification contents

The notification consists of a POST that sends a JSON with the following fields:

- `notification_type`: Notification type. See the values table above.
- `fail`: If this field contains content, it refers to an error notification. The content would be an error code, which can be found [here](/tools/errors).
- `signature`: Notification signature, to validate that the notification is sent by Zru. See below for how to calculate the signature.
- `id`: ID of the Transaction, Subscription, or Authorization related to the notification.
- `type`: Type of object related to the notification (P - Transaction, S - Subscription, A - Authorization).
- `order_id`: Includes the content sent in the `order_id` field when creating the object.
- `status`: Transaction status (N - Pending, D - Completed, C - Cancelled, E - Expired).


> The statuses Completed, Cancelled, and Expired are final statuses.


- `subscription_status`: Subscription status, only sent if the notification is related to a subscription (W - Waiting, A - Active, P - Paused, S - Stopped).


> The Stopped status is a final status.


- `authorization_status`: Authorization status, only sent if the notification is related to an authorization (A - Active, R - Removed).


> The Removed status is a final status.


- `amount`: Amount charged to the customer.
- `sale_id`: If the customer has been charged, includes the Sale ID related to the payment.
- `action`: Last action of the object.
- `sale_action`: Last action of the Sale.
- `_extra`: Includes the content sent in the `extra` field when creating the object or when making a charge. Not sent if it was not provided.
- `_charge_id`: Includes the content sent in the `charge_id` field when making a charge.
- `_method`: In the case of card payments, includes the card information used.


> It is important to keep in mind during implementation that new fields can be added to the received JSON at any time.


### Possible values for the `action` field

- I: Error
- D: Completed
- E: Expired
- C: Cancelled
- A: Active Subscription (only for subscriptions)
- T: Started Subscription (only for subscriptions)
- P: Paused Subscription (only for subscriptions)
- S: Stopped Subscription (only for subscriptions)
- R: Removed Authorization (only for authorizations)
- Y: Payment received (only for subscriptions or authorizations)


### Possible values for the `sale_action` field

- I: Error
- G: Amount charged
- H: Amount on hold
- V: Released amount
- C: Captured amount
- R: Refunded amount
- S: Settled amount
- E: Rejected escrow amount


### Values for the `_method` field

- `name`: Card name
- `masked`: Masked card number
- `unique_hash`: Hash that uniquely represents the card. Whenever a customer uses the same card number and the same expiration date, they will receive the same hash.
- `brand`: Card brand
- `expiration_month`: Card expiration month
- `expiration_year`: Card expiration year


## Examples

### Completed payment (sale_created)

```json
{
  "id": "a1b2c3d4-0000-0000-0000-000000000001",
  "fail": null,
  "type": "P",
  "notification_type": "sale_created",
  "status": "D",
  "action": "D",
  "amount": 157.5,
  "sale_id": "b2c3d4e5-0000-0000-0000-000000000001",
  "sale_action": "G",
  "order_id": "order_example_001",
  "signature": "c1eed82e684cccf2507535f137085d9aafa818114009d9c7f6b2a9edad013014"
}
```

### Failed payment attempt (transaction_confirmation_error)

```json
{
  "id": "a1b2c3d4-0000-0000-0000-000000000002",
  "fail": "MC2P-07001",
  "type": "P",
  "notification_type": "transaction_confirmation_error",
  "status": "N",
  "action": "I",
  "amount": 13.2,
  "sale_id": "",
  "sale_action": "",
  "order_id": "order_example_002",
  "signature": "859e878993ccd736aec1c089f7dd5b73469d47b9213e88659e0ef22cc36f91d4"
}
```

## Calculating the signature

The steps to calculate the signature and verify its correctness are as follows:

1. Start from the received JSON dictionary and ignore the keys:
  - `fail`
  - `signature`
  - any other key starting with `_`
2. Sort the remaining JSON keys in alphabetical order, for example:
  - `['action', 'amount', 'authorization_status', 'id', 'order_id', 'sale_action', 'sale_id', 'status', 'subscription_status', 'type']`
3. In that order, put the values one after the other in a variable, ignoring nulls, replacing the symbols <, >, ", ', (, ), \ with a space, and removing leading and trailing spaces from each value, for example:
  - `D5.0d825c974-7288-4ddf-ae8b-21635c44eac3323232G545b8519-3e3c-4ee7-adef-9da7eefe5283DP`
4. Append the Secret Key of your environment at the end, for example:
  - `D5.0d825c974-7288-4ddf-ae8b-21635c44eac3323232G545b8519-3e3c-4ee7-adef-9da7eefe5283DP18754581c5434008b9262dd5a6938ed3`
5. Finally, apply sha256 to that variable to obtain the signature and compare it with the one received in the JSON, for example:
  - `783600a129c93cad54f561bca60e60c9b8dc328209841751a600a5e1c941ccee`


## Most important flows

### Transaction

| Event | `notification_type` | Notes |
|  --- | --- | --- |
| Error when attempting to confirm | `transaction_confirmation_error` | Check error code in `fail` |
| Cancellation | `transaction_cancelled` | `status=C` |
| Expiration | `transaction_expired` | `status=E` |
| Transaction completed | `sale_created` | `status=D`, `type=P`, includes `sale_id` |


The rest of the possible notifications will always be related to the payment.

### Subscription

| Event | `notification_type` | Notes |
|  --- | --- | --- |
| Error when attempting to confirm | `subscription_confirmation_error` | Check error code in `fail` |
| Error when charging active subscription | `subscription_charge_error` | `status=D`, check error code in `fail` |
| Cancellation | `subscription_cancelled` | `status=C` |
| Expiration | `subscription_expired` | `status=E` |
| Subscription confirmed | `subscription_done` | `status=D`, no `sale_id` |
| Payment received | `sale_created` | `type=S`, includes `sale_id`. Triggered the first time if confirmation includes a charge and on each subsequent charge. |


The rest of the possible notifications will always be related to the subscription payments.

### Authorization

| Event | `notification_type` | Notes |
|  --- | --- | --- |
| Error when attempting to confirm | `authorization_confirmation_error` | Check error code in `fail` |
| Error when charging active authorization | `authorization_charge_error` | `status=D`, check error code in `fail` |
| Cancellation | `authorization_cancelled` | `status=C` |
| Expiration | `authorization_expired` | `status=E` |
| Authorization confirmed | `authorization_done` | `status=D`, no `sale_id` |
| Payment received | `sale_created` | `type=A`, includes `sale_id`. Triggered if confirmation includes a charge and on each charge made with the `charge` endpoint. |


The rest of the possible notifications will always be related to the authorization payments.

### Sale

> These notifications always include the `id` of the object related to the payment and `status=D`.


| Event | `notification_type` | Notes |
|  --- | --- | --- |
| Error on a sale action | (varies) | Such as refund, release, etc. Check error code in `fail`. |
| Capture (can be partial) | `sale_capture` | Check the `amount` field |
| Release (can be partial) | `sale_void` | Check the `amount` field |
| Refund (can be partial) | `sale_refund` | Check the `amount` field |
| Settlement | `sale_settled` | - |


## Panel

In the **Developers** section of the panel you have access to tools designed to facilitate integration tasks. Go to the side menu and select **Developers** to access the **Notifications** and **Webhooks** tabs.

### Notifications

Shows all notifications sent to your server, the response it returned, and allows you to resend them if necessary.

When expanding a notification you will see:

- **Information**: Notification ID, notification URL, date and time.
- **Request**: Complete JSON sent by Zru to your server.
- **Response**: Response returned by your server.


You can filter by ID, external ID, notification URL, date, and response code. You can also export the list as CSV.

To resend a notification: expand the detail and click **Resend**.

### Webhooks

Webhooks allow you to configure the endpoints to which Zru will send notifications globally for the entire environment, as an alternative to defining `notify_url` on each object.

> The difference between Webhooks and Notifications: **Webhooks** are the endpoint configuration (which URL to send to). **Notifications** are the specific events sent to those endpoints, with their request and response.