# Webhook Format and Processing

Connect Webhooks service is a logical extension of our [messages](https://docs.lhv.com/home/connect/services/messages "mention"). When Customer has subscribed to any of the Message types via Subscription services our system will start sending the `POST` requests to the host and uri configured.

Our Webhook messages contain similar data already covered in Messages Services - request and response ID's, message type, creation time etc.  Business information is only provided if either [webhook-metadata](https://docs.lhv.com/home/connect/services/webhooks/webhook-metadata "mention") or [full-bodied-webhooks](https://docs.lhv.com/home/connect/services/webhooks/full-bodied-webhooks "mention") are enabled.  If not, the customer must use the Messages Services to read the actual message content. Webhook payloads can be optionally compressed to reduce message size and optimize delivery performance. In this case the message will include the HTTP header `Content-Encoding: gzip`.

The main benefit of using Webhooks for the customer is significantly improving how the general integration is built. With Webhooks there is no need to constantly poll `GET /messages` endpoints to detect any new Messages pending. This is especially important for services that are not directly triggered by the customer requests like [transaction-notification](https://docs.lhv.com/home/connect/services/account-reports/transaction-notification "mention"). This improves both the speed of getting the newest events from the system and also reduces the load from both Client and Server side.

{% hint style="info" %}
Subscription services are described at [managing-webhook-configurations](https://docs.lhv.com/home/connect/services/webhooks/managing-webhook-configurations "mention")
{% endhint %}

Sample of a typical Webhook message:

```json
{
    "eventId": "7c334869-9c9e-43e7-b11a-be8f605f44fd",
    "eventTimestamp": "2024-08-19T07:41:18.421145632+01:00",
    "subscriptionReference": "9ab35ca0-2f58-4578-aea2-0e611f686ca9",
    "messageResponseId": "RESfaf42325221c4ba3a162286aaf76d00c",
    "messageRequestId": "REQce11219c581840199ca1e4cca0edbd17",
    "messageType": "ACCOUNT_BALANCE",
    "messageCreatedTime": "2024-08-19T07:41:18.404298+01:00",
    "regCode": "13180211",
    "regCodeIssuer": "GB",
    "bankCode": "LHVUK"
}
```

The message body can be retrieved using [get-specific-message](https://docs.lhv.com/home/connect/services/messages/get-specific-message "mention"), or automatically received within the webhook if the subscription is configured to include the full body.&#x20;

{% hint style="info" %}
When you have processed the message, you should mark it is processed ( [mark-message-as-processed](https://docs.lhv.com/home/connect/services/messages/mark-message-as-processed "mention")) just the same as if you were not using webhooks.

Alternatively, you can configure the webhook subscription to automatically mark successfully delivered webhook messages as processed.
{% endhint %}

{% hint style="warning" %}
If a webhook fails to deliver (non-2xx HTTP response), it enters a **Retry Pending** state.&#x20;

While in this state, delivery is automatically re-attempted on a scheduled basis. Retries will continue for up to 24 hours from the time the webhook was first generated.

If the webhook is successfully delivered during this period, its status will be updated to **Success**. If delivery is still unsuccessful after 24 hours, the webhook status will be marked as **Failed**, and no further retries will be attempted.&#x20;

Webhook events that are not successfully delivered within the retry window can be manually resent using the [replay-webhooks](https://docs.lhv.com/home/connect/services/webhooks/webhook-services/replay-webhooks "mention") service.
{% endhint %}

## Preventing Duplicate Processing

It is possible to receive the same webhook event more than once. This can occur if the network connection breaks or an error code is returned after the event has already been processed.

Webhooks retried by the system will use the same `eventId`, allowing the event to be uniquely identified and safely ignored if already handled. In contrast, webhook events replayed via the API will generate a new `eventId`, as each replay is treated as a separate delivery.

The `eventId` field serves as an idempotency key for identifying original deliveries and system retries. This helps prevent duplicate processing and mitigates replay attacks, where an attacker could resend a previously signed webhook.

As keeping a complete history of all received `eventIds` is not practical, old entries can be expired from cache after a day. Similarly, webhooks with an `eventTimestamp` older than one day can be rejected.

## Webhooks & Source IP Addresses

Webhooks are sent from a fixed LHV IP address range. Currently the list is shared for Production and Prelive [environments](https://docs.lhv.com/home/connect/fundamentals/environments "mention"). Please make sure this IP range is added to your systems IP Access List.

{% hint style="info" %}
Actual IP list will be provided by our implementation or support team!
{% endhint %}

## Webhook Event Payload Schema

<table><thead><tr><th width="257">Field</th><th width="119">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>eventId</code></td><td><p>String</p><p>(UUID)</p></td><td>A unique identifier for this webhook event. </td></tr><tr><td><code>eventTimestamp</code></td><td><p>String</p><p>(ISO-8601 datetime)</p></td><td>The server time when this webhook was queued to send. This will stay the same if we retry the notification.</td></tr><tr><td><code>subscriptionReference</code></td><td>String</td><td>The reference of the associated webhook configuration.</td></tr><tr><td><code>messageRequestId</code></td><td>String</td><td>The ID of the request message that this response message pertains to.</td></tr><tr><td><code>messageResponseId</code></td><td>String</td><td>The ID of this response message. This is the key field you should use to retrieve the actual message body.</td></tr><tr><td><code>messageType</code></td><td>String</td><td>The type of the message. See the list at <a data-mention href="../../messages#message-types">#message-types</a></td></tr><tr><td><code>messageCreatedTime</code></td><td><p>String</p><p>(ISO-8601 datetime)</p></td><td>Server time when the message occurred</td></tr><tr><td><code>clientCode</code></td><td>String</td><td>The client this message pertains to</td></tr><tr><td><code>clientCountry</code></td><td>String</td><td>The country of the client this message pertains to</td></tr><tr><td><code>bankCode</code></td><td>String</td><td>Either <code>LHVUK</code> or <code>LHVEE</code>, indicating whether this message originated from the UK or Estonian branch of Connect</td></tr><tr><td><code>metadata</code> (Optional)</td><td>String</td><td>The most relevant values and keys. See <a data-mention href="webhook-metadata">webhook-metadata</a></td></tr><tr><td><code>messageBase64</code> (Optional)</td><td>String</td><td>The full message body encoded in Base64. See <a data-mention href="full-bodied-webhooks">full-bodied-webhooks</a></td></tr></tbody></table>
