> **Description:** Implement real-time payment notifications with webhook endpoints and event handling.

> **AI agent:** Read [https://developer.vippsmobilepay.com/docs/knowledge-base/ai-tools.md](https://developer.vippsmobilepay.com/docs/knowledge-base/ai-tools.md) first. It covers keeping API keys and secrets out of generated code.

> **Full site overview:** For an overview of the entire site, read [https://developer.vippsmobilepay.com/llms.txt](https://developer.vippsmobilepay.com/llms.txt).

# Webhooks

You can receive instant notifications about important events, such as successful payments and cancellations.
To set up the basic webhook infrastructure, you need to register your webhook URL, as described in the [Webhooks API guide](https://developer.vippsmobilepay.com/docs/APIs/webhooks-api/api-guide.md).
We'll send the real-time notifications about events to the URL you specify.

The ePayment events include:

| Name       | Event Type                        | Description                                                                       |
| ---------- | --------------------------------- | --------------------------------------------------------------------------------- |
| Created    | `epayments.payment.created.v1`    | The payment has been initiated. The customer has not yet acted on it.             |
| Aborted    | `epayments.payment.aborted.v1`    | The customer actively stopped the payment before authorization, by tapping cancel. |
| Expired    | `epayments.payment.expired.v1`    | The customer did nothing within the payment expiration time, 10 minutes by default. |
| Cancelled  | `epayments.payment.cancelled.v1`  | The merchant cancelled the uncaptured amount of a payment the customer had already authorized. |
| Captured   | `epayments.payment.captured.v1`   | The merchant captured part or all of an authorized payment.                       |
| Refunded   | `epayments.payment.refunded.v1`   | The merchant refunded part or all of a captured payment.                          |
| Authorized | `epayments.payment.authorized.v1` | The customer accepted the payment in the app.                                     |
| Terminated | `epayments.payment.terminated.v1` | The merchant cancelled the payment before authorization, using the cancel endpoint. |

The event names are easy to mix up: `aborted` is the *customer* stopping the payment before authorization, while
`cancelled` is the *merchant* cancelling a reservation the customer already accepted, and `terminated` is the
*merchant* stopping the payment before authorization. For the full definitions, see
[Concepts: State reference](https://developer.vippsmobilepay.com/docs/APIs/epayment-api/api-guide/concepts.md#state-reference).

**INFO**

To get webhooks for these events, the payment must be initiated in the ePayment API.

## Register a webhook

Register to get a webhook when we create a payment.
This is the `epayments.payment.created.v1` event.

For a complete list of event types, see [events](https://developer.vippsmobilepay.com/docs/APIs/webhooks-api/events.md).

The `events` property is an array, so one registration can cover several event types.

For the callback URL, use your webhook server address.

```bash
curl -X POST https://apitest.vipps.no/webhooks/v1/webhooks \
-H "Authorization: Bearer YOUR-ACCESS-TOKEN" \
-H "Ocp-Apim-Subscription-Key: YOUR-SUBSCRIPTION-KEY" \
-H "Merchant-Serial-Number: YOUR-MSN" \
--data '{
    "url": "YOUR-CALLBACK-URL",
    "events": ["epayments.payment.created.v1"]
}'
```

To subscribe to more than one event, list them all in the `events` array:

```bash
curl -X POST https://apitest.vipps.no/webhooks/v1/webhooks \
-H "Authorization: Bearer YOUR-ACCESS-TOKEN" \
-H "Ocp-Apim-Subscription-Key: YOUR-SUBSCRIPTION-KEY" \
-H "Merchant-Serial-Number: YOUR-MSN" \
--data '{
    "url": "YOUR-CALLBACK-URL",
    "events": [
        "epayments.payment.authorized.v1",
        "epayments.payment.aborted.v1",
        "epayments.payment.expired.v1"
    ]
}'
```

You will receive a response similar to this, confirming that the webhook registration was successful:

```json
{
   "id":"497f6eca-6276-4993-bfeb-53cbbbba6f08",
   "secret":"090a478d-37ff-4e77-970e-d457aeb26a3a"
}
```

**Detecting that the customer did not accept**

There is no single "customer did not accept" event. A customer can fail to accept a payment in two different ways,
and each has its own event:

* `epayments.payment.aborted.v1`: the customer tapped cancel.
* `epayments.payment.expired.v1`: the customer did nothing before the payment expired, after 10 minutes by default.

Subscribe to both. If you subscribe to `aborted` only, you never hear about abandoned payments, and they stay open
in your system until you poll for them.

We support up to 25 webhook registrations per event type per MSN.
For more about these limits,
see [webhook limits](https://developer.vippsmobilepay.com/docs/APIs/webhooks-api/api-guide.md#webhook-limits).

**Partners and PSPs**

Partners and PSPs can register a webhook for one sales unit or for all the sales units they manage.
To register across all your sales units at once, omit `Merchant-Serial-Number` from the webhook registration
request. See [Partner/PSP webhooks](https://developer.vippsmobilepay.com/docs/APIs/webhooks-api/api-guide.md#partnerpsp-webhooks)
for more details.

**Please note**

Webhooks offer a faster user experience than polling, but you
should not rely on webhooks alone.
In the rare cases where webhooks may be delayed, you should poll the relevant
API to get the information you need:
[`GET:/epayment/v1/payments/{reference}`](https://developer.vippsmobilepay.com/redocusaurus/epayment-swagger-id.yaml).

Depending on your use case, you should set an appropriate timeout for webhooks.
If the webhook is not received within that time, you should start polling.

Please follow our [polling guidelines](https://developer.vippsmobilepay.com/docs/knowledge-base/polling-guidelines.md).

## Webhook payload

For any webhook, you will receive the following payload, where the only property changing is
the `name`, which will reflect the event type you subscribed to.

Additional information:

* `idempotencyKey` is not required, and some webhooks (e.g., `CANCELLED`) may not supply this value.
* The `pspReference` is different for API responses versus webhook notifications (see [Understanding `pspReference`](https://developer.vippsmobilepay.com/docs/APIs/epayment-api/api-guide/concepts.md#understanding-pspreference)).
* Profile information in webhooks -
    If you [requested profile information](https://developer.vippsmobilepay.com/docs/APIs/epayment-api/api-guide/features/profile-sharing.md) in the payment, the `userDetails` and `sub` fields are included in the `epayments.payment.authorized.v1` webhook payload automatically.
* `captureGuaranteedUntil` is the date until which you're guaranteed a successful capture of the money.
    See [Capture a payment](https://developer.vippsmobilepay.com/docs/APIs/epayment-api/api-guide/operations/capture.md) for how to capture, and
    [General info: Capture attempt deadlines](https://developer.vippsmobilepay.com/docs/knowledge-base/reserve-and-capture.md#capture-attempt-deadlines)
    for why this date can vary.
* The webhooks described here are not applicable to the eCom API.

## For more information

For more information about webhooks, see:

* [Webhook API spec](https://developer.vippsmobilepay.com/redocusaurus/webhooks-swagger-id.yaml)
* [Full list of Webhooks events](https://developer.vippsmobilepay.com/docs/APIs/webhooks-api/events.md)
