Source: https://docs.debitura.com/api/customer-api/webhooks

# Webhooks — Customer API

Manage webhook subscriptions and inspect the delivery event log. Create subscriptions to receive real-time notifications for case lifecycle events, payments, and chats. Use GET /webhooks/events to verify deliveries and POST /webhooks/events/{id}/replay to re-deliver a specific event.

Base URL: `https://customer-api.debitura.com`

Authentication: `XApiKey` API key; see [authentication](https://docs.debitura.com/developer-concepts/authentication.md).

Generated from [OpenAPI](https://docs.debitura.com/openapi/customer-api.json). Examples are schema illustrations, not observed responses. Complete schemas, including recursive types, are in OpenAPI.

<a id="list-all-webhook-subscriptions-for-the-authenticated-creditor"></a>

## List all webhook subscriptions for the authenticated creditor.

`GET /webhooks`

Returns all webhook subscriptions for the authenticated creditor. Secrets are never returned in list operations.

### Response 200

List of webhook subscriptions

- `id` (uuid): 
- `url` (string, nullable): 
- `events` (array of strings, nullable): 
- `isActive` (boolean): 
- `createdUtc` (datetime): 
- `updatedUtc` (datetime): 
- `disabledReason` (string, nullable): 
- `secret` (string, nullable): 
- `isTestMode` (boolean): 

```json
[
  {
    "id": "3f2b6c1e-8a4d-4b7f-9c2e-5d1a0b9e7f31",
    "url": "https://app.debitura.com/…",
    "events": [
      "string"
    ],
    "isActive": true,
    "createdUtc": "2026-10-01T14:05:00Z",
    "updatedUtc": "2026-10-01T14:05:00Z",
    "disabledReason": null,
    "secret": "string",
    "isTestMode": true
  }
]
```

<a id="create-a-new-webhook-subscription"></a>

## Create a new webhook subscription.

`POST /webhooks`

Creates a new webhook subscription for receiving real-time event notifications.

**Available Events:**
- `case.created` - New collection case created
- `case.updated` - Case lifecycle changed (e.g., Active → Paused). Does not cover engagement phase
  changes (Pre-legal/Legal/Enforcement) — poll `GET /cases/{id}` or `GET /cases/{id}/timeline` for
  the current phase; there is no phase-change event today.
- `case.closed` - Case closed
- `payment.created` - Payment registered on case
- `payment.deleted` - Payment reversed (deleted) on case
- `chat.created` - Chat message created on case

**Validation Rules:**
- URL must be HTTPS
- events array must contain only valid event types
- URL must be publicly reachable
- Private IP addresses are blocked (SSRF protection)

**Returns:**
- Webhook subscription details
- Secret key for HMAC-SHA256 signature verification (shown only once)

**IMPORTANT**: Save the secret immediately - it cannot be retrieved later.

**Webhook Payload Structure:**
Every webhook delivery will contain these headers:
- X-Debitura-Signature: HMAC-SHA256 signature (format: t={timestamp},v1={signature})
- X-Debitura-Timestamp: Unix timestamp of the event
- X-Debitura-Event: Event type (e.g., 'case.created')

**Signature Verification (HMAC-SHA256):**
1. Extract timestamp (t) and signature (v1) from X-Debitura-Signature header
2. Construct signed payload: {timestamp}.{json_body}
3. Compute HMAC-SHA256 using your webhook secret (Base64 decoded)
4. Compare computed signature with v1 value (use constant-time comparison)
5. Verify timestamp is within 5 minutes to prevent replay attacks

**Example Payload:**
```json
{
  "id": "bfa8af05-4bd1-4fd5-8f80-a6357f99dc59",
  "specVersion": "1.0",
  "event": "case.created",
  "timestamp": "2024-01-15T10:30:00Z",
  "data": {
    "caseId": "72d427c1-c38c-48db-b369-6f4a2e9cad3f",
    "reference": "Q8OAXF3W",
    "lifecycle": "Pending Verification Internal"
  },
  "links": {
    "self": "https://customer-api.debitura.com/Cases/72d427c1-c38c-48db-b369-6f4a2e9cad3f"
  }
}
```

### Request body (application/json)

- `url` (string, required): 
  Max 800 characters; URL.
- `events` (array of strings, required): 
- `isTestMode` (boolean): 

```json
{
  "url": "https://example.com/webhooks/debitura",
  "events": [
    "string"
  ]
}
```

### Response 201

Webhook created successfully

- `id` (uuid): 
- `url` (string, nullable): 
- `events` (array of strings, nullable): 
- `isActive` (boolean): 
- `createdUtc` (datetime): 
- `updatedUtc` (datetime): 
- `disabledReason` (string, nullable): 
- `secret` (string, nullable): 
- `isTestMode` (boolean): 

```json
{
  "id": "3f2b6c1e-8a4d-4b7f-9c2e-5d1a0b9e7f31",
  "url": "https://app.debitura.com/…",
  "events": [
    "string"
  ],
  "isActive": true,
  "createdUtc": "2026-10-01T14:05:00Z",
  "updatedUtc": "2026-10-01T14:05:00Z",
  "disabledReason": null,
  "secret": "string",
  "isTestMode": true
}
```

### Response 400

Invalid request

- `error` (string, nullable): Short human-readable error label (legacy field — preserved for backward compatibility).
- `message` (string, nullable): Human-readable error description (legacy field — preserved for backward compatibility).
- `businessErrors` (array of objects, nullable): Canonical structured error array. Consumers should migrate to reading this field.
- `businessErrors[].type` (string, nullable): The type of business error (e.g., "MissingDebtCollectionContract", "MissingPowerOfAttorney", "NoPartnerAvailable").
- `businessErrors[].message` (string, nullable): A human-readable description of the error.
- `businessErrors[].solutionUrl` (string, nullable): A URL where the user can resolve this <i>specific</i> error (e.g., sign a contract).
            

Partners who want a <b>single URL</b> that walks the user through every pending
signing in one chain — instead of forwarding one URL per
`BusinessErrorApiDTO` — should use
SigningHandoff's `CombinedSigningUrl`.
The two are complementary: `SolutionUrl` is granular per-error;
`CombinedSigningUrl` is the chain-walking alternative for signing-related errors.

```json
{
  "error": null,
  "message": "Payment plan agreed with the debtor.",
  "businessErrors": [
    {
      "type": "string",
      "message": "Payment plan agreed with the debtor.",
      "solutionUrl": "https://app.debitura.com/…"
    }
  ]
}
```

### Response 422

Business rule violation

- `error` (string, nullable): Short human-readable error label (legacy field — preserved for backward compatibility).
- `message` (string, nullable): Human-readable error description (legacy field — preserved for backward compatibility).
- `businessErrors` (array of objects, nullable): Canonical structured error array. Consumers should migrate to reading this field.
- `businessErrors[].type` (string, nullable): The type of business error (e.g., "MissingDebtCollectionContract", "MissingPowerOfAttorney", "NoPartnerAvailable").
- `businessErrors[].message` (string, nullable): A human-readable description of the error.
- `businessErrors[].solutionUrl` (string, nullable): A URL where the user can resolve this <i>specific</i> error (e.g., sign a contract).
            

Partners who want a <b>single URL</b> that walks the user through every pending
signing in one chain — instead of forwarding one URL per
`BusinessErrorApiDTO` — should use
SigningHandoff's `CombinedSigningUrl`.
The two are complementary: `SolutionUrl` is granular per-error;
`CombinedSigningUrl` is the chain-walking alternative for signing-related errors.

```json
{
  "error": null,
  "message": "Payment plan agreed with the debtor.",
  "businessErrors": [
    {
      "type": "string",
      "message": "Payment plan agreed with the debtor.",
      "solutionUrl": "https://app.debitura.com/…"
    }
  ]
}
```

<a id="get-a-single-webhook-subscription-by-id"></a>

## Get a single webhook subscription by ID.

`GET /webhooks/{id}`

Returns details of a specific webhook subscription. Secret is never returned in this operation.

### Path parameters

- `id` (uuid, required): 

### Response 200

Webhook subscription found

- `id` (uuid): 
- `url` (string, nullable): 
- `events` (array of strings, nullable): 
- `isActive` (boolean): 
- `createdUtc` (datetime): 
- `updatedUtc` (datetime): 
- `disabledReason` (string, nullable): 
- `secret` (string, nullable): 
- `isTestMode` (boolean): 

```json
{
  "id": "3f2b6c1e-8a4d-4b7f-9c2e-5d1a0b9e7f31",
  "url": "https://app.debitura.com/…",
  "events": [
    "string"
  ],
  "isActive": true,
  "createdUtc": "2026-10-01T14:05:00Z",
  "updatedUtc": "2026-10-01T14:05:00Z",
  "disabledReason": null,
  "secret": "string",
  "isTestMode": true
}
```

### Response 404

Webhook not found

- `error` (string, nullable): Short human-readable error label (legacy field — preserved for backward compatibility).
- `message` (string, nullable): Human-readable error description (legacy field — preserved for backward compatibility).
- `businessErrors` (array of objects, nullable): Canonical structured error array. Consumers should migrate to reading this field.
- `businessErrors[].type` (string, nullable): The type of business error (e.g., "MissingDebtCollectionContract", "MissingPowerOfAttorney", "NoPartnerAvailable").
- `businessErrors[].message` (string, nullable): A human-readable description of the error.
- `businessErrors[].solutionUrl` (string, nullable): A URL where the user can resolve this <i>specific</i> error (e.g., sign a contract).
            

Partners who want a <b>single URL</b> that walks the user through every pending
signing in one chain — instead of forwarding one URL per
`BusinessErrorApiDTO` — should use
SigningHandoff's `CombinedSigningUrl`.
The two are complementary: `SolutionUrl` is granular per-error;
`CombinedSigningUrl` is the chain-walking alternative for signing-related errors.

```json
{
  "error": null,
  "message": "Payment plan agreed with the debtor.",
  "businessErrors": [
    {
      "type": "string",
      "message": "Payment plan agreed with the debtor.",
      "solutionUrl": "https://app.debitura.com/…"
    }
  ]
}
```

<a id="update-an-existing-webhook-subscription"></a>

## Update an existing webhook subscription.

`PATCH /webhooks/{id}`

Partially updates an existing webhook subscription using HTTP PATCH.

Supported Updates:
- Change the webhook URL
- Enable or disable the subscription
- Regenerate the secret key

Note: Event types cannot be changed after creation. To update event types, delete and recreate the subscription.

### Path parameters

- `id` (uuid, required): 

### Request body (application/json)

- `url` (string, nullable): 
  Max 800 characters; URL.
- `events` (array of strings, nullable): 
- `isActive` (boolean, nullable): 
- `regenerateSecret` (boolean): 
- `isTestMode` (boolean, nullable): 

```json
{}
```

### Response 200

Webhook updated successfully

- `id` (uuid): 
- `url` (string, nullable): 
- `events` (array of strings, nullable): 
- `isActive` (boolean): 
- `createdUtc` (datetime): 
- `updatedUtc` (datetime): 
- `disabledReason` (string, nullable): 
- `secret` (string, nullable): 
- `isTestMode` (boolean): 

```json
{
  "id": "3f2b6c1e-8a4d-4b7f-9c2e-5d1a0b9e7f31",
  "url": "https://app.debitura.com/…",
  "events": [
    "string"
  ],
  "isActive": true,
  "createdUtc": "2026-10-01T14:05:00Z",
  "updatedUtc": "2026-10-01T14:05:00Z",
  "disabledReason": null,
  "secret": "string",
  "isTestMode": true
}
```

### Response 400

Invalid request

- `error` (string, nullable): Short human-readable error label (legacy field — preserved for backward compatibility).
- `message` (string, nullable): Human-readable error description (legacy field — preserved for backward compatibility).
- `businessErrors` (array of objects, nullable): Canonical structured error array. Consumers should migrate to reading this field.
- `businessErrors[].type` (string, nullable): The type of business error (e.g., "MissingDebtCollectionContract", "MissingPowerOfAttorney", "NoPartnerAvailable").
- `businessErrors[].message` (string, nullable): A human-readable description of the error.
- `businessErrors[].solutionUrl` (string, nullable): A URL where the user can resolve this <i>specific</i> error (e.g., sign a contract).
            

Partners who want a <b>single URL</b> that walks the user through every pending
signing in one chain — instead of forwarding one URL per
`BusinessErrorApiDTO` — should use
SigningHandoff's `CombinedSigningUrl`.
The two are complementary: `SolutionUrl` is granular per-error;
`CombinedSigningUrl` is the chain-walking alternative for signing-related errors.

```json
{
  "error": null,
  "message": "Payment plan agreed with the debtor.",
  "businessErrors": [
    {
      "type": "string",
      "message": "Payment plan agreed with the debtor.",
      "solutionUrl": "https://app.debitura.com/…"
    }
  ]
}
```

### Response 404

Webhook not found

- `error` (string, nullable): Short human-readable error label (legacy field — preserved for backward compatibility).
- `message` (string, nullable): Human-readable error description (legacy field — preserved for backward compatibility).
- `businessErrors` (array of objects, nullable): Canonical structured error array. Consumers should migrate to reading this field.
- `businessErrors[].type` (string, nullable): The type of business error (e.g., "MissingDebtCollectionContract", "MissingPowerOfAttorney", "NoPartnerAvailable").
- `businessErrors[].message` (string, nullable): A human-readable description of the error.
- `businessErrors[].solutionUrl` (string, nullable): A URL where the user can resolve this <i>specific</i> error (e.g., sign a contract).
            

Partners who want a <b>single URL</b> that walks the user through every pending
signing in one chain — instead of forwarding one URL per
`BusinessErrorApiDTO` — should use
SigningHandoff's `CombinedSigningUrl`.
The two are complementary: `SolutionUrl` is granular per-error;
`CombinedSigningUrl` is the chain-walking alternative for signing-related errors.

```json
{
  "error": null,
  "message": "Payment plan agreed with the debtor.",
  "businessErrors": [
    {
      "type": "string",
      "message": "Payment plan agreed with the debtor.",
      "solutionUrl": "https://app.debitura.com/…"
    }
  ]
}
```

<a id="delete-a-webhook-subscription"></a>

## Delete a webhook subscription.

`DELETE /webhooks/{id}`

Deletes a webhook subscription. This operation is permanent.

### Path parameters

- `id` (uuid, required): 

### Response 204

Webhook deleted successfully

### Response 404

Webhook not found

- `error` (string, nullable): Short human-readable error label (legacy field — preserved for backward compatibility).
- `message` (string, nullable): Human-readable error description (legacy field — preserved for backward compatibility).
- `businessErrors` (array of objects, nullable): Canonical structured error array. Consumers should migrate to reading this field.
- `businessErrors[].type` (string, nullable): The type of business error (e.g., "MissingDebtCollectionContract", "MissingPowerOfAttorney", "NoPartnerAvailable").
- `businessErrors[].message` (string, nullable): A human-readable description of the error.
- `businessErrors[].solutionUrl` (string, nullable): A URL where the user can resolve this <i>specific</i> error (e.g., sign a contract).
            

Partners who want a <b>single URL</b> that walks the user through every pending
signing in one chain — instead of forwarding one URL per
`BusinessErrorApiDTO` — should use
SigningHandoff's `CombinedSigningUrl`.
The two are complementary: `SolutionUrl` is granular per-error;
`CombinedSigningUrl` is the chain-walking alternative for signing-related errors.

```json
{
  "error": null,
  "message": "Payment plan agreed with the debtor.",
  "businessErrors": [
    {
      "type": "string",
      "message": "Payment plan agreed with the debtor.",
      "solutionUrl": "https://app.debitura.com/…"
    }
  ]
}
```

<a id="send-a-test-event-to-the-webhook-endpoint"></a>

## Send a test event to the webhook endpoint.

`POST /webhooks/{id}/test`

Sends a synthetic case.created test event to the webhook endpoint.

This is useful for:
- Verifying the webhook URL is reachable
- Testing your webhook endpoint implementation
- Validating signature verification

The test payload will be a realistic case.created event with synthetic data.

### Path parameters

- `id` (uuid, required): 

### Response 200

Test completed

- `success` (boolean): Whether the test delivery was successful.
- `httpStatusCode` (integer, nullable): HTTP status code returned by the webhook endpoint.
- `durationMs` (integer, nullable): Duration of the HTTP request in milliseconds.
- `errorMessage` (string, nullable): Error message if the delivery failed.
- `errorCategory` (string, nullable): Category of the error (TimeoutError, NetworkError, SslError, HttpError, UnknownError).
- `testPayload` (any, nullable): The test event payload that was sent.

```json
{
  "success": true,
  "httpStatusCode": 3,
  "durationMs": 3,
  "errorMessage": null,
  "errorCategory": null,
  "testPayload": null
}
```

### Response 404

Webhook not found

- `error` (string, nullable): Short human-readable error label (legacy field — preserved for backward compatibility).
- `message` (string, nullable): Human-readable error description (legacy field — preserved for backward compatibility).
- `businessErrors` (array of objects, nullable): Canonical structured error array. Consumers should migrate to reading this field.
- `businessErrors[].type` (string, nullable): The type of business error (e.g., "MissingDebtCollectionContract", "MissingPowerOfAttorney", "NoPartnerAvailable").
- `businessErrors[].message` (string, nullable): A human-readable description of the error.
- `businessErrors[].solutionUrl` (string, nullable): A URL where the user can resolve this <i>specific</i> error (e.g., sign a contract).
            

Partners who want a <b>single URL</b> that walks the user through every pending
signing in one chain — instead of forwarding one URL per
`BusinessErrorApiDTO` — should use
SigningHandoff's `CombinedSigningUrl`.
The two are complementary: `SolutionUrl` is granular per-error;
`CombinedSigningUrl` is the chain-walking alternative for signing-related errors.

```json
{
  "error": null,
  "message": "Payment plan agreed with the debtor.",
  "businessErrors": [
    {
      "type": "string",
      "message": "Payment plan agreed with the debtor.",
      "solutionUrl": "https://app.debitura.com/…"
    }
  ]
}
```

<a id="send-a-test-event-to-the-webhook-endpoint-2"></a>

## Send a test event to the webhook endpoint.

`POST /webhooks/{id}:test`

Sends a synthetic case.created test event to the webhook endpoint.

This is useful for:
- Verifying the webhook URL is reachable
- Testing your webhook endpoint implementation
- Validating signature verification

The test payload will be a realistic case.created event with synthetic data.

### Path parameters

- `id` (uuid, required): 

### Response 200

Test completed

- `success` (boolean): Whether the test delivery was successful.
- `httpStatusCode` (integer, nullable): HTTP status code returned by the webhook endpoint.
- `durationMs` (integer, nullable): Duration of the HTTP request in milliseconds.
- `errorMessage` (string, nullable): Error message if the delivery failed.
- `errorCategory` (string, nullable): Category of the error (TimeoutError, NetworkError, SslError, HttpError, UnknownError).
- `testPayload` (any, nullable): The test event payload that was sent.

```json
{
  "success": true,
  "httpStatusCode": 3,
  "durationMs": 3,
  "errorMessage": null,
  "errorCategory": null,
  "testPayload": null
}
```

### Response 404

Webhook not found

- `error` (string, nullable): Short human-readable error label (legacy field — preserved for backward compatibility).
- `message` (string, nullable): Human-readable error description (legacy field — preserved for backward compatibility).
- `businessErrors` (array of objects, nullable): Canonical structured error array. Consumers should migrate to reading this field.
- `businessErrors[].type` (string, nullable): The type of business error (e.g., "MissingDebtCollectionContract", "MissingPowerOfAttorney", "NoPartnerAvailable").
- `businessErrors[].message` (string, nullable): A human-readable description of the error.
- `businessErrors[].solutionUrl` (string, nullable): A URL where the user can resolve this <i>specific</i> error (e.g., sign a contract).
            

Partners who want a <b>single URL</b> that walks the user through every pending
signing in one chain — instead of forwarding one URL per
`BusinessErrorApiDTO` — should use
SigningHandoff's `CombinedSigningUrl`.
The two are complementary: `SolutionUrl` is granular per-error;
`CombinedSigningUrl` is the chain-walking alternative for signing-related errors.

```json
{
  "error": null,
  "message": "Payment plan agreed with the debtor.",
  "businessErrors": [
    {
      "type": "string",
      "message": "Payment plan agreed with the debtor.",
      "solutionUrl": "https://app.debitura.com/…"
    }
  ]
}
```

<a id="this-endpoint-is-misnamed-and-does-not-actually-replay-events-us"></a>

## This endpoint is misnamed and does not actually replay events.
Use `GET /webhooks/events?caseId={id}` to inspect delivery history,
then `POST /webhooks/events/{eventId}/replay` to re-deliver a specific event.

`POST /webhooks/{id}/replay`

**Deprecated.** Retained for existing integrations.

This endpoint was never fully implemented — it counts cases created
since `sinceUtc` and returns the count as `eventsReplayed`, but does not
re-enqueue or redeliver any events. The name "replay" collides with the real
`POST /webhooks/events/{eventId}/replay` endpoint which actually re-delivers.
            
This endpoint is kept for backward compatibility (additive-only rule) but is deprecated.
Integrators should migrate to the event-log + replay-by-id pattern described above.

### Path parameters

- `id` (uuid, required): 

### Request body (application/json)

- `sinceUtc` (datetime, required): Replay all case.created events since this timestamp (UTC).

```json
{
  "sinceUtc": "2026-10-01T14:05:00Z"
}
```

### Response 200

Count of cases since sinceUtc (not events replayed)

- `eventsReplayed` (integer): Number of events that were re-enqueued for delivery.

```json
{
  "eventsReplayed": 3
}
```

### Response 400

Invalid request

- `error` (string, nullable): Short human-readable error label (legacy field — preserved for backward compatibility).
- `message` (string, nullable): Human-readable error description (legacy field — preserved for backward compatibility).
- `businessErrors` (array of objects, nullable): Canonical structured error array. Consumers should migrate to reading this field.
- `businessErrors[].type` (string, nullable): The type of business error (e.g., "MissingDebtCollectionContract", "MissingPowerOfAttorney", "NoPartnerAvailable").
- `businessErrors[].message` (string, nullable): A human-readable description of the error.
- `businessErrors[].solutionUrl` (string, nullable): A URL where the user can resolve this <i>specific</i> error (e.g., sign a contract).
            

Partners who want a <b>single URL</b> that walks the user through every pending
signing in one chain — instead of forwarding one URL per
`BusinessErrorApiDTO` — should use
SigningHandoff's `CombinedSigningUrl`.
The two are complementary: `SolutionUrl` is granular per-error;
`CombinedSigningUrl` is the chain-walking alternative for signing-related errors.

```json
{
  "error": null,
  "message": "Payment plan agreed with the debtor.",
  "businessErrors": [
    {
      "type": "string",
      "message": "Payment plan agreed with the debtor.",
      "solutionUrl": "https://app.debitura.com/…"
    }
  ]
}
```

### Response 404

Webhook not found

- `error` (string, nullable): Short human-readable error label (legacy field — preserved for backward compatibility).
- `message` (string, nullable): Human-readable error description (legacy field — preserved for backward compatibility).
- `businessErrors` (array of objects, nullable): Canonical structured error array. Consumers should migrate to reading this field.
- `businessErrors[].type` (string, nullable): The type of business error (e.g., "MissingDebtCollectionContract", "MissingPowerOfAttorney", "NoPartnerAvailable").
- `businessErrors[].message` (string, nullable): A human-readable description of the error.
- `businessErrors[].solutionUrl` (string, nullable): A URL where the user can resolve this <i>specific</i> error (e.g., sign a contract).
            

Partners who want a <b>single URL</b> that walks the user through every pending
signing in one chain — instead of forwarding one URL per
`BusinessErrorApiDTO` — should use
SigningHandoff's `CombinedSigningUrl`.
The two are complementary: `SolutionUrl` is granular per-error;
`CombinedSigningUrl` is the chain-walking alternative for signing-related errors.

```json
{
  "error": null,
  "message": "Payment plan agreed with the debtor.",
  "businessErrors": [
    {
      "type": "string",
      "message": "Payment plan agreed with the debtor.",
      "solutionUrl": "https://app.debitura.com/…"
    }
  ]
}
```

<a id="this-endpoint-is-misnamed-and-does-not-actually-replay-events-us-2"></a>

## This endpoint is misnamed and does not actually replay events.
Use `GET /webhooks/events?caseId={id}` to inspect delivery history,
then `POST /webhooks/events/{eventId}/replay` to re-deliver a specific event.

`POST /webhooks/{id}:replay`

**Deprecated.** Retained for existing integrations.

This endpoint was never fully implemented — it counts cases created
since `sinceUtc` and returns the count as `eventsReplayed`, but does not
re-enqueue or redeliver any events. The name "replay" collides with the real
`POST /webhooks/events/{eventId}/replay` endpoint which actually re-delivers.
            
This endpoint is kept for backward compatibility (additive-only rule) but is deprecated.
Integrators should migrate to the event-log + replay-by-id pattern described above.

### Path parameters

- `id` (uuid, required): 

### Request body (application/json)

- `sinceUtc` (datetime, required): Replay all case.created events since this timestamp (UTC).

```json
{
  "sinceUtc": "2026-10-01T14:05:00Z"
}
```

### Response 200

Count of cases since sinceUtc (not events replayed)

- `eventsReplayed` (integer): Number of events that were re-enqueued for delivery.

```json
{
  "eventsReplayed": 3
}
```

### Response 400

Invalid request

- `error` (string, nullable): Short human-readable error label (legacy field — preserved for backward compatibility).
- `message` (string, nullable): Human-readable error description (legacy field — preserved for backward compatibility).
- `businessErrors` (array of objects, nullable): Canonical structured error array. Consumers should migrate to reading this field.
- `businessErrors[].type` (string, nullable): The type of business error (e.g., "MissingDebtCollectionContract", "MissingPowerOfAttorney", "NoPartnerAvailable").
- `businessErrors[].message` (string, nullable): A human-readable description of the error.
- `businessErrors[].solutionUrl` (string, nullable): A URL where the user can resolve this <i>specific</i> error (e.g., sign a contract).
            

Partners who want a <b>single URL</b> that walks the user through every pending
signing in one chain — instead of forwarding one URL per
`BusinessErrorApiDTO` — should use
SigningHandoff's `CombinedSigningUrl`.
The two are complementary: `SolutionUrl` is granular per-error;
`CombinedSigningUrl` is the chain-walking alternative for signing-related errors.

```json
{
  "error": null,
  "message": "Payment plan agreed with the debtor.",
  "businessErrors": [
    {
      "type": "string",
      "message": "Payment plan agreed with the debtor.",
      "solutionUrl": "https://app.debitura.com/…"
    }
  ]
}
```

### Response 404

Webhook not found

- `error` (string, nullable): Short human-readable error label (legacy field — preserved for backward compatibility).
- `message` (string, nullable): Human-readable error description (legacy field — preserved for backward compatibility).
- `businessErrors` (array of objects, nullable): Canonical structured error array. Consumers should migrate to reading this field.
- `businessErrors[].type` (string, nullable): The type of business error (e.g., "MissingDebtCollectionContract", "MissingPowerOfAttorney", "NoPartnerAvailable").
- `businessErrors[].message` (string, nullable): A human-readable description of the error.
- `businessErrors[].solutionUrl` (string, nullable): A URL where the user can resolve this <i>specific</i> error (e.g., sign a contract).
            

Partners who want a <b>single URL</b> that walks the user through every pending
signing in one chain — instead of forwarding one URL per
`BusinessErrorApiDTO` — should use
SigningHandoff's `CombinedSigningUrl`.
The two are complementary: `SolutionUrl` is granular per-error;
`CombinedSigningUrl` is the chain-walking alternative for signing-related errors.

```json
{
  "error": null,
  "message": "Payment plan agreed with the debtor.",
  "businessErrors": [
    {
      "type": "string",
      "message": "Payment plan agreed with the debtor.",
      "solutionUrl": "https://app.debitura.com/…"
    }
  ]
}
```
