# Webhooks

## Intro

With our webhook system we allow you to **receive events in real-time** (or almost) without the need to poll our API on a regular basis (which might be an issue with regards to your rate-limits as well).

:::note

**Make sure to read our[guide](/docs/webhooks) about Webhooks first 📖**

:::

## Overview

![](/images/partner/ddca096a2f5401108b3e753f02e7244f9a0ea052d59668bdf39604648d6352f4-webhooks_overview.png)

## Supported Entities

See [https://docs.partner-api.monta.com/docs/webhooks#supported-event-types](/docs/webhooks#supported-event-types)

## Configuration

To be able to receive events via a webhook you need to provide an HTTPS endpoint as well as a secret.

Make use of the `PUT /webhooks/config`([docs](/api/webhooks#update-your-webhook-config)) endpoint to provide both:

* `webhookUrl`: A HTTPS URL to send the webhook payload to when an event occurs.
* `webhookSecret`: A cryptoghrapic secret used to sign the webhook payload.

## Format of incoming events

### Webhook Request Model

Any call to your webhook endpoint follows this structure (request payload):

**`POST {webhookUrl}`**

```Text json
{
	"entries": [],
	"pending": 42,
	"timestamp": 1690550358254
}
```

* **`entries`**: List of entries (Webhook Entry Model, see next paragraph) delivered in this batch
* **`pending`**: Number of pending events left for delivery
* **`timestamp`**: Timestamp of the request (milliseconds from the epoch of `1970-01-01T00:00:00Z`). Check this to avoid replay attacks.

### Webhook Entry Model

```Text json
{
	"entityType": "charge",
	"entityId": "21",
	"eventType": "created",
	"payload": {}
}
```

* **`entityType`**: Type of the entity
* **`entityId`**: ID of the entity
* **`eventType`**: Type of event, ie. `created`, `deleted`, `updated`
* **`payload`**: Payload of this entity, e.g. a full **Charge** object

## Validating incoming events

To allow you to validate incoming events, we are signing every request with a signature as part of the header field `X-Monta-Signature`.

The signature has the following format: `sha1={signature}`

It is generated using this algorithm: **HMAC-SHA1** with your `webhookSecret` as **key** (Bytes) and the request body as  **input**.

To validate that the requests was indeed coming from Monta, re-generate the signature using your secret and the payload and compare. To detect/prevent replay attacks you can parse the `timestamp` field of the request body.

:::note{title="Generating the signature"}

You can find more about how to generate and validate the signature here: [Generating the signature (Example)](/reference/generating-the-signature-example)

:::

## Responding to our webhook calls

When we call your webhook endpoint we expect you to do 2 things:

1. Reply immediately
2. Reply with `200` status code

Any processing, parsing and what not that could lead to long response times should be done asynchronously.

## Failed deliveries

When a delivery failed - regardless if it was on our or your end (ie. when you provided anything other than 200 status code) - we mark the event and their entries as failed and they will be picked up in our retry schedule (currently every 60 seconds).

:::warning

**Please note that we delete any events older than 24 hours.**

:::

## Debugging

To make everyone's life easier, we provide you with an endpoint to debug any webhook events relevant for your consumer:

* completed webhook entries are stored for 1 hour
* failed webhook entries are stored for 24 hours

Use the endpoint `GET /webhooks/entries` ([docs](/api/webhooks#retrieve-webhook-entries)) to retrieve all `pending` or `failed` entries. You can also filter by status to only check for `pending` or `failed` entries.

In case of a failed entry, inspect the `error` field to learn more about the potential cause.
