---
title: "Receivables webhooks"
canonical: https://documentation.maventa.com/integration-guide/accounts-receivable/webhooks/
---

Receivables webhooks notify your system when something happens on an assignment — a payment is booked, a credit note is issued, a reminder goes out, or the case moves to a new collection stage. Instead of polling the [Receivables API](https://documentation.maventa.com/api-specification/rest-api/receivables-api/) for changes, you receive an HTTP POST shortly after each event, so your integration always has the current state of each assignment.

> [!NOTE]
> These webhooks are specific to accounts receivable and are separate from Maventa's general [Webhooks](https://documentation.maventa.com/integration-guide/integration-tools/webhooks/), which cover invoice and network events. They use their own subscription setup and payload, described below.

## Setting up a subscription

Receivables webhook subscriptions are set up by Maventa. To enable them, contact Maventa and provide:

| What we need           | Description                                                        |
| ---------------------- | ----------------------------------------------------------------- |
| Endpoint URL           | The HTTPS URL that receives the POST requests.                    |
| Authentication method  | How Maventa should authenticate to your endpoint (see below).     |
| Authentication secret  | The credential for the chosen method (password, token, or key).   |

Once the subscription is active, your endpoint starts receiving events for the assignments linked to your account. No further setup is required on your side beyond handling the incoming requests.

## Events you can receive

A webhook is sent whenever one of the following events occurs on an assignment. Each event carries an `event_type` you can switch on, plus a `data` object with the details for that event.

| `event_type`                | What it means                                                                 |
| --------------------------- | ----------------------------------------------------------------------------- |
| `paid`                      | The invoice has been fully or partially paid.                                 |
| `credit_note`               | A credit note has been issued against the invoice.                            |
| `credit_loss`               | The amount has been written off as a credit loss.                             |
| `close`                     | The assignment has been closed.                                               |
| `partially_close`           | The assignment has been partially closed (the invoice is settled, but reminder or collection charges remain unpaid by the debtor). |
| `collection_started`        | Debt collection has started on the assignment.                                |
| `reminder_sent`             | A payment reminder has been sent to the debtor.                               |
| `second_reminder_sent`      | A second payment reminder has been sent to the debtor.                        |
| `second_demand_sent`        | A payment demand has been sent for the unpaid invoice.                        |
| `legal_collection_started`  | A summons application has been sent and legal collection has started.         |
| `payment_plan`              | A payment plan has been agreed for the invoice.                               |

## Payload

Every webhook is delivered as an HTTP POST with a JSON body in the following shape:

```json
{
  "delivery_id": "<uuid>",
  "created_at": "<ISO8601-timestamp>",
  "event_data": {
    "assignment_event_id": "<uuid>",
    "assignment_id": "<uuid>",
    "event_type": "<event_type>",
    "party_id": "<uuid>",
    "happened_at": "<ISO8601-timestamp>",
    "data": { }
  }
}
```

| Field                            | Description                                                                       |
| -------------------------------- | --------------------------------------------------------------------------------- |
| `delivery_id`                    | Unique ID for this delivery. Use it to deduplicate (see [Delivery and retries](#delivery-and-retries)). |
| `created_at`                     | When the delivery was created, in ISO 8601 format.                                |
| `event_data.assignment_event_id` | Unique ID of the underlying assignment event.                                    |
| `event_data.assignment_id`       | ID of the assignment the event belongs to.                                        |
| `event_data.event_type`          | The type of event — one of the values in [Events you can receive](#events-you-can-receive). |
| `event_data.party_id`            | ID of the party that created the event.                                           |
| `event_data.happened_at`         | When the event happened, in ISO 8601 format.                                       |
| `event_data.data`                | Event-specific details. The fields depend on `event_type` (see below).            |

### Event `data` fields

The `data` object varies by `event_type`:

| `event_type`                | `data` fields                                                                 |
| --------------------------- | ----------------------------------------------------------------------------- |
| `paid`                      | `sum_paid` (number), `booked_at` (date), `archive_number` (string, optional)  |
| `credit_note`               | `credit_sum` (number), `booked_at` (date), `referenced_document_number` (string, optional) |
| `credit_loss`               | `sum` (number), `booked_at` (date)                                            |
| `close`                     | `reason` (string, optional)                                                   |
| `partially_close`           | `reason` (string, optional)                                                   |
| `collection_started`        | `started_at` (date)                                                           |
| `reminder_sent`             | `sent_at` (date)                                                              |
| `second_reminder_sent`      | `happened_at` (date)                                                          |
| `second_demand_sent`        | `happened_at` (date)                                                          |
| `legal_collection_started`  | `happened_at` (date)                                                          |
| `payment_plan`              | `happened_at` (date)                                                          |

### Example

A payload for a `paid` event:

```json
{
  "delivery_id": "b0f4a5c8-1d2e-4f3a-9b6c-2e7d8f9a0b1c",
  "created_at": "2026-07-20T09:15:03+02:00",
  "event_data": {
    "assignment_event_id": "d726d240-4631-483e-a4e3-61bbefa0e7b7",
    "assignment_id": "53a4e05d-42f0-4e76-acd6-1a2b3c4d5e6f",
    "event_type": "paid",
    "party_id": "9c8b7a6d-5e4f-3a2b-1c0d-e9f8a7b6c5d4",
    "happened_at": "2026-07-20T09:14:58+02:00",
    "data": {
      "sum_paid": 200.50,
      "booked_at": "2026-07-20",
      "archive_number": "12345"
    }
  }
}
```

## Authentication

To confirm that requests to your endpoint come from Maventa, choose one of the following authentication methods when setting up your subscription. Maventa applies it to every request.

### Basic

HTTP Basic authentication. Maventa sends your username and secret in the `Authorization` header as `Basic base64(username:secret)`.

### Bearer

A bearer token. Maventa sends your secret in the `Authorization` header as `Bearer your-secret`.

### Custom header

A secret in a header name of your choice. Maventa sends the secret as the value of the header you specify.

### HMAC

Maventa signs each request with an HMAC-SHA256 signature so you can verify both the sender and that the body was not altered. Two headers are sent:

- `X-Timestamp` — the Unix timestamp of the request.
- `X-Signature` — the signature, in the form `sha256=...`.

The signature is computed as `HMAC_SHA256(secret, "timestamp.body")`, where `timestamp` is the value of the `X-Timestamp` header and `body` is the raw request body, joined with a literal dot.

To verify, recompute the signature on your side using the received `X-Timestamp` and the raw request body, then compare it with the value in `X-Signature`.

> [!WARNING]
> Deliveries are made over TLS 1.2, so your endpoint must accept TLS 1.2 connections.

## Delivery and retries

A delivery is considered successful when your endpoint responds with any `2xx` status code. Any other response, or a timeout, is treated as a failure and retried.

- **Timing.** Deliveries are dispatched by a background job that runs on a schedule, so expect an event to arrive within a few minutes of it occurring rather than instantly.
- **Respond quickly.** Keep your handler lightweight — acknowledge the request and do any heavy processing in the background. Requests that take too long are treated as failures.
- **Retries.** Failed deliveries are retried automatically, up to 10 attempts, before Maventa gives up on that delivery.
- **Deduplicate.** Delivery is at-least-once, so the same event may arrive more than once. Use `delivery_id` to recognise and ignore duplicates.
- **Ordering.** Deliveries for a single assignment are sent in the order the events occurred.

> [!NOTE]
> Because no delivery mechanism is guaranteed to be perfect, use the [Receivables API](https://documentation.maventa.com/api-specification/rest-api/receivables-api/) as a fallback to reconcile assignment state if you suspect an event was missed.
