# Webhooks

Setup webhooks through the API in order to be notified of any Vibrant events.

{% tabs %}
{% tab title="curl" %}

```json
curl -X 'POST' \
  'https://pos-api.sandbox.vibrant.app/pos/v1/webhooks' \
  -H 'accept: application/json' \
  -H 'apikey: vibrant_pos.YOUR_SECRET_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
  "enabledEvents": [   
    "payment_intent.succeeded"
  ],
  "description": "My PI succeeded webhook",
  "url": "https://myPlaceToReceiveWebhhoks.com/thanks",
  "status": "enabled"
  "metadata": {
    "remember_this": "something"
  }
}'
```

{% endtab %}
{% endtabs %}

**enabledEvents**

It is possible to subscribe to one or more event types or `*` to get all events.

See the full list of possible event types in the API documentation: [REST API doc create webhook](https://pos.dev-api.vibrant.app/docs#/webhooks/WebhookController_create)

**url**

The endpoint to which the events will be posted.

**status**

Here it is possible to `enable` or `disable` the webhook.

**metadata**

If desired it is possible to add some meta data to the webhook that can be retrieved again when getting the webhook object. The meta data will not be attached to the events.

{% openapi src="/files/dpD1DfJWd0tHsdtLsmdE" path="/pos/v1/webhooks" method="post" %}
[local2.json](https://3273535141-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHcN7n2RefgutErEy6gSW%2Fuploads%2FLIzYoY0CLj3682HAlTcD%2Flocal2.json?alt=media\&token=86b17484-e443-41c6-a2e4-72fc31c415a0)
{% endopenapi %}

## Receiving a webhook

Once a webhook was created successfully, the url defined on the webhook will start receiving the events selected on the `enabledEvents` field.

It's important to verify the `vibrant-signature` in order for you to ensure that the message received is from vibrant. More details on the vibrant-signature can be read just in the next section: [#webhook-event-verification](#webhook-event-verification "mention")

And example scenario of the payload sent by Vibrant follows:

**Headers**

| Name              | Value                                         |
| ----------------- | --------------------------------------------- |
| Content-Type      | `application/json`                            |
| vibrant-signature | `t=123132131,v0=213cds123ds12es231ds132ds123` |

**Body**

```
{
   "accountId": "aacct_1xv12v31-7111-1111-1111-11111110e93e",
   "apiVersion": "v1",
   "created": 1764845184522,
   "data": {
     "accountId": "aacct_1xv12v31-7111-1111-1111-11111110e93e",
     "amount": 9961,
     "arrivalDate": "2025-12-06T00:00:00.000000",
     "automatic": true,
     "balanceTransactions": [
      {
        "accountId": "aacct_1xv12v31-7111-1111-1111-11111110e93e",
        "amount": 7101,
        "availableOn": "2025-12-05T00:00:00.000000",
        "balanceTransactionId": null,
        "created": "2025-12-04T11:45:11.297000",
        "currency": "DKK",
        "description": "Charge",
        "failureCode": null,
        "failureMessage": null,
        "fee": 148,
        "feeDetails": [
          {
            "amount": 19,
            "currency": "DKK",
            "type": "auth_fee"
          },
          {
            "amount": 19,
            "currency": "DKK",
            "type": "mdr"
          }
        ],
        "id": "txn_t4AP9WVroDRZFFjg3BSWMf",
        "metadata": {
          "note": null
        },
        "net": 6953,
        "refund": null,
        "reportingCategory": "charge",
        "settlementId": "06605c5c-4926-51e4-a7ba-accd641b7033",
        "source": "ch_bxif2MDo5W5kGLzYhN7Wug",
        "sourceType": null,
        "status": "PENDING",
        "type": "CHARGE"
      },
      {
        "accountId": "aacct_1xv12v31-7111-1111-1111-11111110e93e",
        "amount": -9961,
        "availableOn": "2025-12-06T00:00:00.000000",
        "balanceTransactionId": null,
        "charge": null,
        "created": "2025-12-04T11:46:16.955000",
        "currency": "DKK",
        "description": "Settlement payout 123131231231",
        "failureCode": null,
        "failureMessage": null,
        "fee": 0,
        "feeDetails": [],
        "id": "txn_prDgtYRw4dNXn4XjSrEcoE",
        "metadata": {},
        "net": -9961,
        "refund": null,
        "reportingCategory": "payout",
        "settlementId": "06605c5c-4926-51e4-a7ba-accd641b7033",
        "source": "po_11231231231231231",
        "sourceType": null,
        "status": "PENDING",
        "type": "PAYOUT"
      },
      {
        "accountId": "aacct_1xv12v31-7111-1111-1111-11111110e93e",
        "amount": 3100,
        "availableOn": "2025-12-05T00:00:00.000000",
        "balanceTransactionId": null,
        "created": "2025-12-04T11:45:11.274000",
        "currency": "DKK",
        "description": "Charge",
        "failureCode": null,
        "failureMessage": null,
        "fee": 92,
        "feeDetails": [
          {
            "amount": 19,
            "currency": "DKK",
            "type": "auth_fee"
          },
          {
            "amount": 13,
            "currency": "DKK",
            "type": "mdr"
          }
        ],
        "id": "txn_CNGFeZw93m99fvF4oSGxZV",
        "metadata": {
          "correlationId": "internal_order_id"
        },
        "net": 3008,
        "refund": null,
        "reportingCategory": "charge",
        "settlementId": "06605c5c-4926-51e4-a7ba-accd641b7033",
        "source": "ch_53X4R8zHDDtpQxwA8pGsvS",
        "sourceType": null,
        "status": "PENDING",
        "type": "CHARGE"
      }
    ],
     "currency": "DKK",
     "description": "Settlement payout 123131231231",
     "destination": "DK_bank_1a2b123132131i0j",
     "failureBalanceTransaction": null,
     "failureCode": null,
     "failureMessage": null,
     "id": "po_11231231231231231",
     "metadata": {},
     "method": "standard",
     "originalPayout": null,
     "reconciliationStatus": null,
     "reversedBy": null,
     "settlementId": "06605c5c-4926-51e4-a7ba-accd641b7033",
     "sourceType": "card",
     "statementDescriptor": "bank descriptor",
     "status": "PENDING",
     "type": "bank_account"
  },
   "id": "evt_d87a1cbcfd6e4287b0ec",
   "object": "event",
   "source": "brokkr",
   "type": "payout.created",
   "updated": 1764845184522
}
```

## Webhook event verification

Each webhook created in Vibrant holds a secret key.

This can be used to verify that the events posted to your webhook url is actually coming from Vibrant.

The secret key can be used to calculate an expected hash from a received message, to validate that the message in fact is from Vibrant and to this unique webhook.

**How to verify messages:**

Messages to a webhook hold a header named `Vibrant-Signature`.

The signature holds a timestamp and a hash, with comma in between.

`t=1652744532,v0=1327f867e7efdzecb36ahfg46cgfs4fa51cad7e57f5g59pf736d6ce8f406d3fv`

&#x20;Follow these three steps to verify the Vibrant signature.

1. Create a string combining the value of timestamp `t` then a . and then the message body.
2. Compute a HMAC with the SHA256 hash function. Use the endpoint’s secret key as the key, and use the string from step 1. as the message.
3. Compare the Vibrant signature `v0` from the header to the expected signature from step 2. For an equality match, compute the difference between the current timestamp and the received timestamp, then decide if the difference is within your tolerance.

The timestamp is used to prevent replay attacks resending a valid message to your endpoint. So you can check if the timestamp is too old.

## Webhook Retrial behaviour

Upon the registration of the webhook, Vibrant will initiate delivery attempts for the selected events specified during the webhook creation process. In the event of a delivery failure, Vibrant will engage in a series of retransmission attempts employing an exponential backoff strategy, initially prioritizing expedited delivery followed by subsequent attempts spread over a maximum period of 31 days.

## Webhooks best practices

These are some of the practices recommended by Vibrant for a smooth webhook integration.

**Acknowledgement of the webhooks**

Upon receipt of a webhook from our system, it is imperative that the customer endpoint service promptly acknowledges receipt by sending a HTTP 200 OK response. This response serves as confirmation that the webhook payload has been successfully received and acknowledged by the third-party system. Failure to promptly respond with a 200 status code will result in unintended consequences, such as repeated delivery attempts.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.vibrant.io/vibrant/vibrant-sandbox/webhooks.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
