> ## Documentation Index
> Fetch the complete documentation index at: https://docs.paywise.de/llms.txt
> Use this file to discover all available pages before exploring further.

# Webhooks

> Configure Partner-owned subscriptions, select connected companies, and look up company and user lifecycle events.

Register one Partner-owned webhook to receive updates across your connected
companies. Select the event types you need; for Case and Mahnservice events,
set `companies: "*"` to include all managed companies and future connections.
Each event identifies its company, so one receiver can route updates to the
right client.

Use the [shared webhook guide](/api-docs/essentials/webhooks) for testing,
signature verification, duplicate handling, retries, and delivery
troubleshooting. Follow
[Consume Partner webhooks](/api-docs/partner-api/workflows/consume-webhooks)
for a complete API example.

## Subscription ownership

Manage subscriptions with your Partner key through
[POST `/partner/v2/webhooks/`](/api-docs/partner-api/reference/webhooks/create-webhook).
Subscriptions belong to the Partner; creating a Partner-managed company does
not create a company webhook.

A Partner key with `X-On-Behalf-Of-Company` may **read** a managed company's
`/v2/webhooks/` and `/v2/webhook-deliveries/`, but every write there — create,
update, delete, rotate-secret, test, redeliver — answers `403` with code
`use_partner_webhooks`, before any `If-Match` or query-parameter check.
Partners subscribe to Case events through `/partner/v2/webhooks/` with a
`companies` selector, as described below.

Partner subscription commands follow the shared rules: `rotate-secret` and
`redeliver` take no request body (`400 unexpected_body`); a `PATCH` that
repeats the stored values is a `200` no-op and leaves `updated_at` and the
`ETag` unchanged; and `POST /partner/v2/webhook-deliveries/{id}/redeliver/`
accepts settled deliveries only — a `pending`, `retrying`, or `delivering`
delivery answers `409 delivery_in_progress`.

Partner subscriptions expose writable `max_consecutive_failures` (a JSON
integer from 1 to 1000, default 50). It sets how many consecutive terminal
delivery failures switch the subscription off. An automatically disabled
subscription reads back with `enabled: false` and `auto_disabled: true`; fix
the destination and set `enabled: true` to reset the failure counter.
A test event on a disabled subscription answers `409 conflict`
(`Webhook is disabled; enable it before sending a test event.`). A test event
whose type is not in the subscription answers `400`
(`Webhook is not subscribed to event type: <type>.`).

## Receive Case and Mahnservice events

A Partner-owned subscription may include
[Case event types](/api-docs/case-management-api/concepts/webhook-events)
and [Mahnservice event types](/api-docs/mahnservice-api/concepts/invoice-lifecycle#webhook-events)
from the company catalog. It then needs a
`companies` selector saying whose events it receives: the literal `"*"` for
every managed company, or a non-empty list of company UUIDs. A Partner
subscription whose `events` contain a Case event but no `companies` is
rejected with `400` and code `required_for_case_events` on `companies`; a
UUID the Partner has no available Case access to answers `400`
`company_not_accessible`; anything else answers `400` `invalid`. Lifecycle-only
subscriptions leave `companies` as `null`. The wildcard `events: ["*"]`
without `companies` stays lifecycle-only and never widens into Case events.

Access is re-checked at delivery time, not only when the event is queued: a
company that declines, is released, or is otherwise no longer available stops
producing deliveries to the Partner's subscriptions, and resumes when access
is restored. A delivery that was already queued for such a company is closed
as `failed` with `error_message: partner_access_unavailable` — no HTTP call
is made and the attempt does not count against the endpoint's health. The
check runs right before each send without holding up the disconnect, so an
attempt already past it can still arrive just after access ends. Every later
attempt, retry, and manual redelivery is suppressed. Only
`company.access.revoked` itself still goes out, as the final event of that
connection. Such a delivery is no longer visible to you, so redelivering it
answers `404`. A Case event delivered to a Partner subscription is
byte-identical to the delivery the company's own subscription receives, same
`id` included, so a receiver fed by both deduplicates naturally.

The [Partner event feed](/api-docs/partner-api/reference/events/list-events)
includes only events available to your integration. Use it to reconcile
company, Case, and Mahnservice changes.

## Partner lifecycle events

The Partner OpenAPI schema publishes `PartnerWebhookEvent` for deliveries and
`PartnerEventFeedEvent` for the event feed. Both dispatch on `type`, with the
company event families above and these Partner lifecycle families:

| Partner family | Events | `data` |
| - | - | - |
| `CompanyCreatedWebhookEvent` | `company.created` | `company_id`, `company_url`, `customer_number` (nullable), `case_submission_ready` |
| `CompanyReadinessChangedWebhookEvent` | `company.case_submission_readiness.changed` | `company_id`, `company_url`, `case_submission_ready` |
| `CompanyAccessWebhookEvent` | `company.access.confirmed`, `company.access.restored` | `company_id`, `company_url`, `authorization_version` |
| `CompanyAccessRevokedWebhookEvent` | `company.access.revoked` | `company_id`, `company_url`, `authorization_version`; optional `reason: "partner_released"` |
| `CompanyUserWebhookEvent` | `company.user.added`, `company.user.revoked`, `company.user.activated`, `company.user.invite_expired` | `company_id`, `company_url`, `membership_id` |

### When events are sent

`company.created` is emitted once after the company and inline users commit,
before the `company.user.added` event of each inline user. Readiness emits only
when its boolean changes and never reveals private issue details. Confirmation
emits once per authorization version without user PII. Revocation is the last
event authorized by the previous state; restoration resumes future events
without replaying missed ones.

`company.user.added` also emits when a cancelled pending membership is
re-added or a revoked membership is reactivated. `company.user.revoked` emits
after an active membership is soft-revoked and contains the company and
membership UUIDs, never the user's email, name, or the operator-supplied
reason. `company.user.activated` emits when a pending membership becomes
`active` — the person accepted the invite, by signing in or by setting a
password. Completing password setup activates only the membership of the
company whose invitation it was, so `company.user.activated` fires for that
company only. `company.user.invite_expired` emits from a daily sweep for every
pending membership whose setup invite has lapsed unaccepted; the membership
stays `pending_setup` and a resend issues a fresh invite. Both carry the
company and membership UUIDs only. Resend, role correction, and pending
cancellation do not emit user lifecycle events. A release by the Partner
emits `company.access.revoked` with `reason: "partner_released"` in `data`;
a client-side decline keeps its existing shape.

## Diagnose missing company events

Check that the subscription includes the event type and, for a company event,
an appropriate `companies` selector. `events: ["*"]` without `companies`
receives Partner lifecycle events only. Check the company's current access:
disconnection stops its deliveries, and restoration resumes future events
without replaying the gap. Fetch current data or use the
[Partner event feed](/api-docs/partner-api/reference/events/list-events)
to reconcile what is available.

Inspect [delivery history](/api-docs/partner-api/reference/webhook-deliveries/list-webhook-deliveries)
for failed attempts and use the
[shared troubleshooting table](/api-docs/essentials/webhooks#troubleshooting)
for receiver and signature problems.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.