# Authentication
Source: https://documentation.debbiecollect.com/api-reference/authentication
Authenticate using bearer token
Authentication with an API key can be done by using a bearer token in the Authorization header. This is done using the following format `Authorization: Bearer {token}`. The API token can both be issued and revoked directly from the platform. Please go to the menu on the right side, click Developers and then API. Name the API token and associate your needed scopes.
```header theme={null}
Authorization: Bearer {token}
```
## Scopes
Every endpoint requires a scope, and a token only reaches the endpoints its scopes cover. A scope is an access level and an area joined by a colon:
```
read:cases
write:case-vouchers
```
The access level follows the HTTP method — `GET` requires `read`, and every other method requires `write`. The area is named on each endpoint under **Required scope**.
Grant a token the narrowest set that covers what it does. A token that only mirrors data into a warehouse needs `read` scopes alone.
### Sub-areas
Some areas have a sub-area, written with a dot:
```
write:interactions.create
```
**A scope grants exactly what it names.** `write:interactions` does not grant `write:interactions.create`, and `write:interactions.create` does not grant `write:interactions`. If a token needs both, give it both.
Because a scope does not cascade, a token that gets a `401` on one endpoint
may work fine on a neighbouring one in the same area. Check the **Required
scope** on the endpoint itself rather than assuming the area is covered.
### Checking a token's scopes
`GET /iam/auth/permissions` returns the scopes the calling token carries. It requires no scope itself, so it is the quickest way to confirm a token was issued with what you expect.
```json theme={null}
{
"scopes": ["read:cases", "read:case-vouchers", "read:updates"]
}
```
### When a scope is missing
A request made with a token that lacks the required scope is rejected with `401 Unauthorized`:
```json theme={null}
{
"statusCode": 401,
"error": "Unauthorized",
"message": "You do not have permission to access this resource",
"requestId": "1a2b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d"
}
```
The scopes on an existing token can be changed under Developers → API in the platform without reissuing it.
# Get deposit distribution
Source: https://documentation.debbiecollect.com/api-reference/endpoints/billing/get
GET /v1/{tenantId}/billings/{billingId}/deposit-distribution
Get deposit distribution in a billing.
**Required scope:** `read:billings`
# Get billing vouchers
Source: https://documentation.debbiecollect.com/api-reference/endpoints/billing/get-billing-vouchers
GET /v1/{tenantId}/billings/{billingId}/billing-vouchers
Get the fees and disbursements the creditor is charged on a billing.
Only the fees that stand on their own are returned. A fee charged on a specific deposit is part of that deposit's distribution and is reported by [Get deposit distribution](/api-reference/endpoints/billing/get) as `collectionCommission` instead, so the two endpoints can be booked together without counting it twice.
**Required scope:** `read:billings`
# Create case group
Source: https://documentation.debbiecollect.com/api-reference/endpoints/case-groups/create
POST /v1/{tenantId}/case-groups
Create a case group on the tenant.
**Required scope:** `write:case-groups`
# Delete case group
Source: https://documentation.debbiecollect.com/api-reference/endpoints/case-groups/delete
DELETE /v1/{tenantId}/case-groups/{caseGroupId}
Delete a case group. Cases in the group are kept and detached from it.
**Required scope:** `write:case-groups`
# Get case groups
Source: https://documentation.debbiecollect.com/api-reference/endpoints/case-groups/get-list
GET /v1/{tenantId}/case-groups
Get a paginated list of the case groups on the tenant. Stop paging when a page comes back with fewer items than pageSize.
**Required scope:** `read:case-groups`
# Update case group
Source: https://documentation.debbiecollect.com/api-reference/endpoints/case-groups/update
PATCH /v1/{tenantId}/case-groups/{caseGroupId}
Update the label or settings of a case group.
**Required scope:** `write:case-groups`
# Register case voucher allocation
Source: https://documentation.debbiecollect.com/api-reference/endpoints/case-vouchers/allocations
POST /v1/{tenantId}/case-vouchers/allocations
Register a payment made directly to the creditor or a credit note against a list of existing case vouchers. Set `voucherTypeId` to deposit or credit note; other types are currently rejected. All created vouchers use source `CREDITOR`.
Each item in `matches` supplies a positive `amount` in minor units and exactly one of `caseVoucherId` and `caseVoucherReferenceId`. References must be unambiguous within the supplied `creditorId`. A target may appear only once, including when supplied by ID and reference in different items. Each amount must fit within the target's remaining fixed-distribution capacity. All targets must have the same currency.
Matches are grouped by case. One allocation voucher is created per case with the sum of that case's match amounts, and one fixed distribution per target on both accounts, using the allocation voucher date. No fixed distribution crosses cases. The response is an array of the created allocation vouchers and their `targetCaseVouchers`, including each `matchedAmount`.
**Required scope:** `write:case-vouchers`
# Add case voucher
Source: https://documentation.debbiecollect.com/api-reference/endpoints/case-vouchers/create
POST /v1/{tenantId}/case-vouchers/{id}
Add case voucher to case
**Required scope:** `write:case-vouchers`
# Get case voucher
Source: https://documentation.debbiecollect.com/api-reference/endpoints/case-vouchers/get
GET /v1/{tenantId}/case-vouchers/{id}
Get a single case voucher by its id.
**Required scope:** `read:case-vouchers`
# Get case vouchers
Source: https://documentation.debbiecollect.com/api-reference/endpoints/case-vouchers/get-list
GET /v1/{tenantId}/case-vouchers
Get a paginated list of case vouchers. Can be filtered by the reference id of the voucher and by a case voucher property (attribute). Property filtering matches the exact value of a text property.
**Required scope:** `read:case-vouchers`
# Create case
Source: https://documentation.debbiecollect.com/api-reference/endpoints/cases/create
POST /v1/{tenantId}/cases
Create new case allows the api consumer to create new cases
**Required scope:** `write:cases`
# Get case
Source: https://documentation.debbiecollect.com/api-reference/endpoints/cases/get
GET /v1/{tenantId}/cases/{id}
Get a case by id
**Required scope:** `read:cases`
# Get cases
Source: https://documentation.debbiecollect.com/api-reference/endpoints/cases/get-list
GET /v1/{tenantId}/cases
Get a list of cases paginated
**Required scope:** `read:cases`
# Patch case
Source: https://documentation.debbiecollect.com/api-reference/endpoints/cases/patch
PATCH /v1/{tenantId}/cases/{id}
Updates attributes of a case given the cases id
**Required scope:** `write:cases`
# Create contact
Source: https://documentation.debbiecollect.com/api-reference/endpoints/contacts/create
POST /v1/{tenantId}/contacts
Create a contact on the tenant. Only administrators can create contacts.
**Required scope:** `write:contacts`
# Delete contact
Source: https://documentation.debbiecollect.com/api-reference/endpoints/contacts/delete
DELETE /v1/{tenantId}/contacts/{contactId}
Delete a contact. Payouts already created to the contact keep their own copy of the bank account. Only administrators can delete contacts.
**Required scope:** `write:contacts`
# Get contact
Source: https://documentation.debbiecollect.com/api-reference/endpoints/contacts/get
GET /v1/{tenantId}/contacts/{contactId}
Get a contact.
**Required scope:** `read:contacts`
# Get contacts
Source: https://documentation.debbiecollect.com/api-reference/endpoints/contacts/get-list
GET /v1/{tenantId}/contacts
Get the contacts on the tenant, sorted by name. A contact is a third party the tenant communicates with or pays out to on behalf of a creditor — for example a locksmith hired during a collection case.
**Required scope:** `read:contacts`
# Update contact
Source: https://documentation.debbiecollect.com/api-reference/endpoints/contacts/update
PATCH /v1/{tenantId}/contacts/{contactId}
Update a contact. Fields left out are unchanged; `email`, `phone`, `registryIdentifier` and `bankAccount` are cleared by sending null. Only administrators can update contacts.
**Required scope:** `write:contacts`
# Create creditor
Source: https://documentation.debbiecollect.com/api-reference/endpoints/creditors/create
POST /v1/{tenantId}/creditors
Create new creditor allows the api consumer to create new creditors
**Required scope:** `write:creditors`
# Get creditor
Source: https://documentation.debbiecollect.com/api-reference/endpoints/creditors/get
GET /v1/{tenantId}/creditors/{creditorId}
Get a creditor
**Required scope:** `read:creditors`
# Patch creditor
Source: https://documentation.debbiecollect.com/api-reference/endpoints/creditors/patch
PATCH /v1/{tenantId}/creditors/{creditorId}
Patch a creditor
**Required scope:** `write:creditors`
# Add case vouchers
Source: https://documentation.debbiecollect.com/api-reference/endpoints/customers/add-case-vouchers
POST /v1/{tenantId}/customers/{customerId}/add-case-vouchers
Add new case vouchers to a customer
**Required scope:** `write:customers`
# Add user on customer
Source: https://documentation.debbiecollect.com/api-reference/endpoints/customers/add-user-on-customer
POST /v1/{tenantId}/customers/{customerId}/users
Add a new user (party) to a customer. Use this to add for example a driver, a representative or another party that should be able to receive communication on the customer's cases.
**Required scope:** `write:customers`
# Create customer
Source: https://documentation.debbiecollect.com/api-reference/endpoints/customers/create
POST /v1/{tenantId}/customers
Create new customer allows the api consumer to create a customer related to a creditor
**Required scope:** `write:customers`
# Delete customer
Source: https://documentation.debbiecollect.com/api-reference/endpoints/customers/delete
DELETE /v1/{tenantId}/customers/{id}
Delete a customer together with its users. Their registry data is no longer kept up to date, and a `customers.delete` webhook is sent along with a `users-on-customers.delete` for each user. The request fails with a conflict error if the customer has one or more cases, including ended ones. Deleting a customer that is already deleted succeeds without sending the webhooks again.
**Required scope:** `write:customers.delete`
# Get customer id
Source: https://documentation.debbiecollect.com/api-reference/endpoints/customers/get
GET /v1/{tenantId}/customers/{id}
Get a customer by customer id
**Required scope:** `read:customers`
# Get customer by reference id
Source: https://documentation.debbiecollect.com/api-reference/endpoints/customers/get-by-reference
GET /v1/{tenantId}/customers/by-reference-id/{referenceId}
Get a customer by customer reference id
**Required scope:** `read:customers`
# Patch user on customer
Source: https://documentation.debbiecollect.com/api-reference/endpoints/customers/patch-user-on-customer
PATCH /v1/{tenantId}/customers/{customerId}/users/{userId}
Patch user information on a user associated with a customer
**Required scope:** `write:customers`
# Add document
Source: https://documentation.debbiecollect.com/api-reference/endpoints/documents/create
POST /v1/{tenantId}/documents
Attach a document to a case or to a creditor. Upload the file first with `POST /v1/{tenantId}/files` and pass the object it returns as `file` — the upload calls the identifier `id`, and it goes in here as `fileId`.
`type` decides what the document means in the collection process: the types other than `OTHER` are what give a debt a legal foundation and decide when it expires.
`minAccessRole` decides who can see it — `debtor` shows it in the debtor self-service portal, `client` to the creditor, `caseworker` only inside the platform.
**Required scope:** `write:documents`
# Create end reason
Source: https://documentation.debbiecollect.com/api-reference/endpoints/end-reasons/create
POST /v1/{tenantId}/end-reasons
Create an end reason on the tenant. The handle is derived from the label when not provided.
**Required scope:** `write:end-reasons`
# Delete end reason
Source: https://documentation.debbiecollect.com/api-reference/endpoints/end-reasons/delete
DELETE /v1/{tenantId}/end-reasons/{endReasonId}
Delete an end reason created on the tenant. The standard end reasons cannot be deleted, and an end reason used by ended cases is rejected with a conflict.
**Required scope:** `write:end-reasons`
# Get end reasons
Source: https://documentation.debbiecollect.com/api-reference/endpoints/end-reasons/get-list
GET /v1/{tenantId}/end-reasons
Get a paginated list of the end reasons available on the tenant — the standard end reasons and the ones the tenant has created — sorted by how often they are used. Stop paging when a page comes back with fewer items than pageSize.
**Required scope:** `read:end-reasons`
# Update end reason
Source: https://documentation.debbiecollect.com/api-reference/endpoints/end-reasons/update
PATCH /v1/{tenantId}/end-reasons/{endReasonId}
Update an end reason created on the tenant. The standard end reasons cannot be edited.
**Required scope:** `write:end-reasons`
# Create file
Source: https://documentation.debbiecollect.com/api-reference/endpoints/files/create
POST /v1/{tenantId}/files
Upload file allows the api consumer to upload files
**Required scope:** `write:files`
# Get file
Source: https://documentation.debbiecollect.com/api-reference/endpoints/files/get
GET /v1/{tenantId}/files/{fileId}/{fileName}
Get file by fileId
**Required scope:** `read:files`
# Create interaction
Source: https://documentation.debbiecollect.com/api-reference/endpoints/interactions/create
POST /v1/{tenantId}/interactions
Create an interaction on a case. Use this to register an incoming message from a debtor or another party, for example a submitted contact form.
**Required scope:** `write:interactions.create`
# Get payment plan
Source: https://documentation.debbiecollect.com/api-reference/endpoints/payment-plans/get
GET /v1/{tenantId}/payment-plans/{paymentPlanId}
Get a single payment plan by its id.
**Required scope:** `read:payment-plans`
# Get payment plans
Source: https://documentation.debbiecollect.com/api-reference/endpoints/payment-plans/get-list
GET /v1/{tenantId}/payment-plans
Get a list of payment plans, paginated. Plans are returned oldest first, so a consumer paging through the whole set is not shifted by plans created while it iterates.
Without caseId the list spans the tenant and is not available to creditor scoped credentials. With caseId it returns the plans on that case.
**Required scope:** `read:payment-plans`
# Get properties
Source: https://documentation.debbiecollect.com/api-reference/endpoints/properties/get
GET /v1/{tenantId}/properties/{refType}/{refId}
Get properties by reference type and id
**Required scope:** `read:properties`
# Create transaction account
Source: https://documentation.debbiecollect.com/api-reference/endpoints/transaction-accounts/create
POST /v1/{tenantId}/transaction-accounts
Create a transaction account — a bank account or a payment service provider account that payments are registered on.
**Required scope:** `write:transaction-accounts`
# Delete transaction account
Source: https://documentation.debbiecollect.com/api-reference/endpoints/transaction-accounts/delete
DELETE /v1/{tenantId}/transaction-accounts/{id}
Delete a transaction account.
**Required scope:** `write:transaction-accounts`
# Get transaction accounts
Source: https://documentation.debbiecollect.com/api-reference/endpoints/transaction-accounts/get
GET /v1/{tenantId}/transaction-accounts
Get the transaction accounts of the tenant.
**Required scope:** `read:transaction-accounts`
# Patch transaction account
Source: https://documentation.debbiecollect.com/api-reference/endpoints/transaction-accounts/patch
PATCH /v1/{tenantId}/transaction-accounts/{id}
Update the name or the reference id of a transaction account.
**Required scope:** `write:transaction-accounts`
# Create update
Source: https://documentation.debbiecollect.com/api-reference/endpoints/updates/create
POST /v1/{tenantId}/updates
Create new update allows the api consumer to create new updates
**Required scope:** `write:updates`
# Get update
Source: https://documentation.debbiecollect.com/api-reference/endpoints/updates/get
GET /v1/{tenantId}/updates/{updateId}
Get a single update by its id. Only updates on cases can be read; any other update answers 404.
**Required scope:** `read:updates`
# Get updates
Source: https://documentation.debbiecollect.com/api-reference/endpoints/updates/get-list
GET /v1/{tenantId}/updates
Get a list of every update on the tenant, paginated. Updates are returned oldest first, so a consumer paging through the whole set is not shifted by updates created while it iterates. Only updates on cases are returned.
This endpoint is tenant wide and is not available to creditor scoped credentials, which read updates through the case they belong to.
**Required scope:** `read:updates`
# Get update types
Source: https://documentation.debbiecollect.com/api-reference/endpoints/updates/get-types
GET /v1/{tenantId}/updates/types
Get a paginated list of the update types available on the tenant.
**Required scope:** `read:updates`
# Patch update
Source: https://documentation.debbiecollect.com/api-reference/endpoints/updates/patch
PATCH /v1/{tenantId}/updates/{updateId}
Patch an existing update
**Required scope:** `write:updates`
# Get voucher types
Source: https://documentation.debbiecollect.com/api-reference/endpoints/voucher-types/get
GET /v1/{tenantId}/voucher-types
Get the voucher types of the tenant, sorted by their order. A creditor key only receives the types the creditor can send vouchers in.
**Required scope:** `read:voucher-types`
# Create webhook
Source: https://documentation.debbiecollect.com/api-reference/endpoints/webhooks/create
POST /v1/{tenantId}/webhooks
Creates a webhook that POSTs the events it is subscribed to. The response carries the verification token sent with every delivery — store it, it is not shown again.
**Required scope:** `write:webhooks`
# Delete webhook
Source: https://documentation.debbiecollect.com/api-reference/endpoints/webhooks/delete
DELETE /v1/{tenantId}/webhooks/{webhookId}
Deletes a webhook. It stops receiving events immediately; deliveries already made are kept.
**Required scope:** `write:webhooks`
# Get webhook
Source: https://documentation.debbiecollect.com/api-reference/endpoints/webhooks/get
GET /v1/{tenantId}/webhooks/{webhookId}
Gets a single webhook.
**Required scope:** `read:webhooks`
# Get webhook items
Source: https://documentation.debbiecollect.com/api-reference/endpoints/webhooks/get-items
GET /v1/{tenantId}/webhooks/items
Get webhook items paginated
**Required scope:** `read:webhooks`
# Get webhooks
Source: https://documentation.debbiecollect.com/api-reference/endpoints/webhooks/get-list
GET /v1/{tenantId}/webhooks
Lists the webhooks that are receiving events, paginated. Stop paging when a page comes back with fewer items than pageSize.
**Required scope:** `read:webhooks`
# Patch webhook item
Source: https://documentation.debbiecollect.com/api-reference/endpoints/webhooks/patch-item
PATCH /v1/{tenantId}/webhooks/items/{itemId}
Patch webhook item
**Required scope:** `write:webhooks`
# Idempotency
Source: https://documentation.debbiecollect.com/api-reference/idempotency
Ensuring safe retries with Idempotency Keys
The Debbie API supports idempotency for non-idempotent requests through the optional `Idempotency-Key` header. This ensures that retrying the same request multiple times will produce the same result, preventing duplicate operations.
## Using Idempotency Keys
* Include an Idempotency-Key header with a unique string (we recommend UUIDs)
* Maximum key length is 64 characters
* Keys are valid for 48 hours
* Responses served from the idempotency cache include an Idempotency-Cached header
## Example
```header theme={null}
Idempotency-Key: 123e4567-e89b-12d3-a456-426614174000
```
## Error Cases
* Invalid key format: 400 Bad Request
* Reusing a key for a different request: 400 Bad Request
## Best practices
* Use a new key for each unique business transaction
* Use the same key when retrying a failed request
* Store keys with request details for debugging
# Introduction
Source: https://documentation.debbiecollect.com/api-reference/introduction
Welcome to the Debbie API
E-mail: [api-support@debbie.dk](mailto:api-support@debbie.dk)
The Debbie API is a RESTful interface, allowing you to programmatically update, add and access your data in the platform. It provides predictable URLs for accessing resources, and uses built-in HTTP features to receive commands and return responses. This makes it easy to communicate with third party systems.
Find out more about Debbie [here](https://debbiecollect.com/).
# Pagination
Source: https://documentation.debbiecollect.com/api-reference/pagination
How list endpoints paginate results
List endpoints in the Debbie API are paginated with the `page` and `pageSize` query parameters.
## Parameters
* `page` — the page to get, starting from `0`. Defaults to `0`.
* `pageSize` — the number of items per page. Each endpoint documents its default and maximum page size.
## Response format
Paginated endpoints return the items of the requested page together with a `meta` object:
```json theme={null}
{
"meta": {
"currentPage": 0,
"pageSize": 250
},
"items": [{ "...": "..." }]
}
```
## Iterating through all pages
The response does not include a total count. To fetch all items, keep requesting the next page until a page contains fewer items than `pageSize`:
```
GET /v1/{tenantId}/updates/types?page=0&pageSize=250
GET /v1/{tenantId}/updates/types?page=1&pageSize=250
...
```
When `items.length < pageSize`, you have reached the last page.
## Best practices
* Use a fixed `pageSize` for all requests in an iteration — changing it between pages will skip or repeat items
* Requesting a page beyond the last one returns an empty `items` array
# Billing created
Source: https://documentation.debbiecollect.com/api-reference/webhooks/billings.create
webhook billings.create
Notifies when a billing has been created.
# Case voucher created
Source: https://documentation.debbiecollect.com/api-reference/webhooks/case-vouchers.create
webhook case-vouchers.create
Notifies when a case voucher has been created.
# Case voucher deleted
Source: https://documentation.debbiecollect.com/api-reference/webhooks/case-vouchers.delete
webhook case-vouchers.delete
Notifies when a case voucher has been deleted.
# Case voucher updated
Source: https://documentation.debbiecollect.com/api-reference/webhooks/case-vouchers.update
webhook case-vouchers.update
Notifies when a case voucher has been updated.
# Case created
Source: https://documentation.debbiecollect.com/api-reference/webhooks/cases.create
webhook cases.create
Notifies when a case is created.
# Case deleted
Source: https://documentation.debbiecollect.com/api-reference/webhooks/cases.delete
webhook cases.delete
Notifies when a case is deleted.
# Case merged
Source: https://documentation.debbiecollect.com/api-reference/webhooks/cases.merge
webhook cases.merge
Notifies when a case is merged into another case.
# Case merge undoed
Source: https://documentation.debbiecollect.com/api-reference/webhooks/cases.undo-merge
webhook cases.undo-merge
Notifies when a case merge is undoed.
# Case updated
Source: https://documentation.debbiecollect.com/api-reference/webhooks/cases.update
webhook cases.update
Notifies when a case is patched. Only the changed fields are sent.
# Creditor created
Source: https://documentation.debbiecollect.com/api-reference/webhooks/creditors.create
webhook creditors.create
Notifies when a creditor has been created.
# Creditor updated
Source: https://documentation.debbiecollect.com/api-reference/webhooks/creditors.update
webhook creditors.update
Notifies when a creditor has been updated.
# Customer created
Source: https://documentation.debbiecollect.com/api-reference/webhooks/customers.create
webhook customers.create
Notifies when a customer has been created.
# Customer deleted
Source: https://documentation.debbiecollect.com/api-reference/webhooks/customers.delete
webhook customers.delete
Notifies when a customer has been deleted.
# Customer updated
Source: https://documentation.debbiecollect.com/api-reference/webhooks/customers.update
webhook customers.update
Notifies when a public field of a customer has changed, including moving it to another creditor.
# Deposit booked
Source: https://documentation.debbiecollect.com/api-reference/webhooks/deposits.booked
webhook deposits.booked
Notifies when a deposit has been booked on a case it was not on before. It does not fire when a deposit moves between cases — that is `deposits.moved`.
# Deposit created
Source: https://documentation.debbiecollect.com/api-reference/webhooks/deposits.created
webhook deposits.created
Notifies when a deposit has been created, with or without a case. A deposit created directly on a case fires `deposits.created` and `deposits.booked`.
# Deposit deleted
Source: https://documentation.debbiecollect.com/api-reference/webhooks/deposits.deleted
webhook deposits.deleted
Notifies when a deposit has been deleted.
# Deposit moved
Source: https://documentation.debbiecollect.com/api-reference/webhooks/deposits.moved
webhook deposits.moved
Notifies when a deposit has been moved from one case to another. `fromCaseId` and `toCaseId` carry the two cases. Creditor-scoped hooks for both the source and destination creditor receive the same event; tenant-wide hooks receive it once. `creditorId` identifies the destination creditor.
# Deposit restored
Source: https://documentation.debbiecollect.com/api-reference/webhooks/deposits.restored
webhook deposits.restored
Notifies when a deleted deposit has been restored.
# Deposit unbooked
Source: https://documentation.debbiecollect.com/api-reference/webhooks/deposits.unbooked
webhook deposits.unbooked
Represents a deposit removed from its case without landing on another. `fromCaseId` carries the case it came off. Unbooking a deposit through the voucher patch API is currently rejected with HTTP 409 because payment-plan settlement and configured workflows cannot be reversed automatically.
# Interaction sent
Source: https://documentation.debbiecollect.com/api-reference/webhooks/interactions.send
webhook interactions.send
Notifies when an interaction has been sent.
# Payment plan created
Source: https://documentation.debbiecollect.com/api-reference/webhooks/payment-plans.create
webhook payment-plans.create
Notifies when a payment plan is created.
# Payment plan deleted
Source: https://documentation.debbiecollect.com/api-reference/webhooks/payment-plans.delete
webhook payment-plans.delete
Notifies when a payment plan is deleted.
# Payment plan updated
Source: https://documentation.debbiecollect.com/api-reference/webhooks/payment-plans.update
webhook payment-plans.update
Notifies when a payment plan is patched. Only the changed fields are sent. Also dispatched when creating a plan on a case that already has one: the existing plan is reshaped instead of a new one being created, and the result is reported here rather than as payment-plans.create.
# Payout created
Source: https://documentation.debbiecollect.com/api-reference/webhooks/payouts.create
webhook payouts.create
Notifies when a payout has been created.
# Update created
Source: https://documentation.debbiecollect.com/api-reference/webhooks/updates.create
webhook updates.create
Notifies when an update has been created.
# Update deleted
Source: https://documentation.debbiecollect.com/api-reference/webhooks/updates.delete
webhook updates.delete
Notifies when an update has been deleted.
# Update updated
Source: https://documentation.debbiecollect.com/api-reference/webhooks/updates.update
webhook updates.update
Notifies when an update has been patched.
# User on customer created
Source: https://documentation.debbiecollect.com/api-reference/webhooks/users-on-customers.create
webhook users-on-customers.create
Notifies when a user has been added to a customer, including the users of a newly created customer. Delivery order is not guaranteed, so this can arrive before the customers.create of a new customer.
# User on customer deleted
Source: https://documentation.debbiecollect.com/api-reference/webhooks/users-on-customers.delete
webhook users-on-customers.delete
Notifies when a user has been removed from a customer, or its customer has been deleted.
# User on customer updated
Source: https://documentation.debbiecollect.com/api-reference/webhooks/users-on-customers.update
webhook users-on-customers.update
Notifies when a public field of a user on a customer has changed. Making a user the contact person also updates the previous contact person.
# Core concepts
Source: https://documentation.debbiecollect.com/core-concepts
Understand core concepts in Debbie
## Data structure
## Concepts
### Creditors
A creditor is the company or private individual to whom money is owed.
Only agencies collecting for others need to define creditors.
### Customers
Represents the end-customer relationship. A customer has a reference ID, which can be the customer number, client ID, membership number, patient ID, or another identifier linked to the customer relationship. Each customer can have multiple contacts.
### Cases
A case represents a specific debt or matter associated with a customer. Each case can have a workflow, allowing it to move through various stages of processing. Each customer can have multiple cases, each potentially in a different workflow stage. A case is always linked to a customer and includes a list of case vouchers, which represent the amount owed. These vouchers reflect the portion of the customer's account that the case relates to.
When integrating with an ERP system, you only need to create the customer and
add case vouchers to the customer. Debbie will automatically determine when to
create a new case or update an existing one.
### Case groups
To help organize your cases, you can create case groups and assign each case to a group. Case groups not only improve structure and clarity but also unlock additional functionality. For example, you can define custom data fields (properties), set default workflows for each case group, and take advantage of other configuration options tailored to your use case.
### Case vouchers
A case voucher is a financial entry linked to a specific case, representing an amount that is either owed or credited. Case vouchers are used to define the financial components of a case and can include various types of transactions such as invoices, credit notes, reminder fees, deposits, or other custom-defined voucher types.
Each case voucher includes key information such as the amount, currency, source, date, and a reference ID (e.g. an invoice number). You can define custom voucher types to match your specific business requirements. Vouchers can also be linked—for instance, one voucher can fulfill or offset others—allowing accurate tracking and settlement of case balances, whether your ERP system uses an open invoice or open balance model.
### Updates
Updates refer to the actions taken on cases and can be either automated or manual. Workflows can trigger automatic actions over time and can also transition a case into a manual task that appears in the to do list. There are countless possibilities for managing tasks, with numerous configuration options designed to save time, enhance debt collection efficiency, and boost customer satisfaction.
# Getting started
Source: https://documentation.debbiecollect.com/getting-started
Get started using the API
Welcome! This guide will help you quickly get up and running with the Debbie API.
## 1. Get your sandbox environment
If you are not already having access to a sandbox environment, please contact the Debbie team. The sandbox allows you to safely explore the API and test your integration without affecting live data.
## 2. Connect to the API
In the Debbie platform, navigate to the Developer section in the menu on the right-hand side. From there, you can create a new API key to authenticate your requests. You can also subscribe to webhooks.
## 3. Understand Debbie core concepts
Before diving into the endpoints, we recommend reading the Core Concepts section to familiarize yourself with how Debbie works and how the different components fit together.
## 4. Read our guides
We’ve put together a set of practical guides covering common use cases and best practices. These will help you build a solid and effective integration.
# Law firm systems
Source: https://documentation.debbiecollect.com/guides/law-firm-systems
Integrating a law firm case management system with Debbie
This guide describes how a law firm case management system integrates with Debbie: collection matters are replicated into Debbie — or picked up from it — handled through a collection workflow, and settled back to the law firm system.
It is built entirely on the RESTful JSON API and webhooks, and it is deliberately small: four endpoints out, a handful of webhooks back.
## At a glance
| Step | What happens | Call |
| - | - | - |
| [1](#1-create-the-creditor) | The client is created as a creditor | `POST /creditors` |
| [2](#2-create-the-customer-and-its-parties) | The debtor and other parties are created as a customer | `POST /customers` |
| [3](#3-create-the-case) | The matter is handed over as a case, and the user continues in Debbie | `POST /cases` |
| [4](#4-register-deposits-paid-to-the-law-firm) | Payments into the client account are pushed to Debbie | `POST /case-vouchers/{caseId}` |
| [5](#5-receive-payments-status-changes-and-settlements) | Payments, status changes and settlements come back | Webhooks + `GET /billings/{id}/deposit-distribution` |
| [6](#6-take-in-cases-that-start-in-debbie) | Matters that started in Debbie are opened in the law firm system | `cases.create` webhook |
Push data synchronously as part of the user's action where you can, but always
make the calls retryable. Every write endpoint accepts an `Idempotency-Key`,
so a failed request can safely be replayed from a queue.
## Who owns what
The law firm system stays the system of record for the matter — the client relationship, the parties, the invoicing of legal work. Debbie becomes the system of record for the collection process — the workflow, letters, interest, fees, payment plans, court steps and the settlement of the client.
**Debbie's *creditor* is the law firm's client** — the party the money is owed
to, who instructed the firm and who is paid out when the case settles. Wherever
this guide says `creditorId`, `read:creditors` or *creditor*, read "client".
**Debbie's *customer* is the other side of the matter** — the debtor and anyone
else involved there, never the firm's client. A matter for client X against
debtor Y becomes creditor X with customer Y.
| Direction | Mechanism | What it carries |
| - | - | - |
| Law firm system → Debbie | REST endpoints | Creditors, customers, cases, and payments into the client account |
| Debbie → law firm system | Webhooks | Cases and parties created in Debbie, payments Debbie collects, status changes, and the settlement of the client |
Three rules decide where a record may come into existence. Agree them before any code is written.
**The client is created only in the law firm system.** The client register — the engagement, the KYC and AML clearance, the invoicing of legal work — belongs there. A creditor created in Debbie would be a client the firm's own register does not know, and would bypass the checks that precede taking a client on. A firm that wants its caseworkers to create creditors anyway has to close the loop from `creditors.create`. The same applies to the other side of the matter: the debtor and any other party pass the firm's conflict-of-interest check before they are created in Debbie.
**Cases start in either system.** They are also imported from spreadsheets, created by the clients through Debbie's API, and created by Debbie's accounting integrations. A push-only integration holds a subset of the matters, so build the return path too — [step 6](#6-take-in-cases-that-start-in-debbie).
**The collection ledger stays in Debbie.** The vouchers that make up the debt are created in Debbie, not pushed from the law firm system, and the balance is read back rather than rebuilt: interest accrues on rules set per client, fees follow the workflow, expiry is recalculated as the case moves, and clients add vouchers of their own. Book money, not vouchers.
## Before you start
1. **Get a sandbox tenant.** Contact the Debbie team. Every endpoint is scoped by `tenantId` in the path, so sandbox and production differ only by that id and the API key.
2. **Create an API key.** In the platform, go to *Developers → API*, name the key and grant the scopes under [Scopes](#scopes). Authenticate with `Authorization: Bearer {token}` — see [Authentication](/api-reference/authentication).
3. **Subscribe to webhooks.** Under *Developers → Webhooks*, register the endpoint that should receive the [events below](#webhooks-back-to-the-law-firm-system).
## Identifiers to store on both sides
Getting this mapping right is the single most important part of the integration. Decide up front which id lives where, and persist it.
| Store in the law firm system | From | Used for |
| - | - | - |
| `creditorId` | `POST /creditors` → `id` | Creating customers and cases for that client |
| `customerId` | `POST /customers` → `customerId` | Creating cases for that party |
| `caseId` (uuid) | `POST /cases` → `id` | Registering deposits and reading the case |
| `caseSeqId` (number) | `POST /cases` → `caseSeqId` | Deep-linking into `https://app.debbiecollect.com/cases/{caseSeqId}` |
| Store in Debbie | Field | Used for |
| - | - | - |
| The firm's case number | `customJournalNumber` on the case | Making the case number identical in both systems |
| The firm's client number | `id` on the creditor | Reconciling the client — returned as `reference` |
| The client's customer number | `referenceId` on the customer | Lookup via `GET /customers/by-reference-id/{referenceId}` |
Always set `customJournalNumber` when you create the case. Without it Debbie
falls back to its own sequential journal number, and the matter is referenced
by two different numbers in the two systems — including in letters and court
documents sent to the debtor.
## 1. Create the creditor
A creditor is the client whose claim you are collecting. One client with several matters is still one creditor; the matters become cases beneath it. Only create the clients that actually have collection cases — check whether the creditor exists before each handover, and store the returned `id` on the client record.
```json POST /v1/{tenantId}/creditors theme={null}
{
"id": "CLIENT-4471",
"name": "Nordisk Byg A/S",
"centralRegisterId": "DK40125949",
"isCompany": true,
"vatRegistered": true,
"address": {
"address": "Havnegade 12",
"zipcode": "1058",
"city": "København K",
"country": "DK"
},
"bankAccountDetails": {
"type": "DANISH",
"registrationNumber": "1234",
"accountNumber": "12345678"
}
}
```
`id` is your own client number, returned as `reference` on subsequent reads. `bankAccountDetails` is what Debbie pays out to when the client is settled, so include it if you hold it.
Creditors are created in Debbie *from* the law firm system, never the other
way around, and only once the client has passed the firm's onboarding checks —
see [KYC, AML and conflicts of interest](#kyc-aml-and-conflicts-of-interest).
See [POST Create creditor](/api-reference/endpoints/creditors/create) for full
details.
## 2. Create the customer and its parties
A case is never created directly on a creditor — it hangs off a *customer*, which holds one or more contacts, called users. Create it with the debtor and any other party you know about before creating the case. The creditor is passed as a query parameter.
Run the debtor and every other party through the firm's conflict-of-interest
check before creating them in Debbie. A conflict can come from the
counterparty rather than the client, so the check does not end with client
onboarding — see [KYC, AML and conflicts of
interest](#kyc-aml-and-conflicts-of-interest).
```json POST /v1/{tenantId}/customers?creditorId={creditorId} theme={null}
{
"isCompany": false,
"referenceId": "CUST-40218",
"users": [
{
"relation": "debtor",
"contact": true,
"lang": "da",
"details": {
"name": "Mette Jensen",
"cpr": "0101801234",
"email": "mette@example.com",
"phone": { "locale": "45", "number": "12345678" },
"address": {
"address": "Søndergade 5, 2. th",
"zipcode": "8000",
"city": "Aarhus C",
"country": "DK"
}
}
}
]
}
```
* `relation` is `debtor` for the party who owes the money, `alternative-contact` for anyone else on that side — a lawyer, a guardian, an administrator.
* `contact: true` marks the user Debbie addresses its communication to.
* `referenceId` is the **client's** id for the debtor, not a party number from the law firm system — the customer number the claim arose under (a telco's subscriber number, a housing association's tenant number). Pass it through rather than inventing one. It only has to be unique per creditor, which is why the lookup is creditor scoped.
Parties discovered later are added with `POST /customers/{customerId}/users`.
See [POST Create customer](/api-reference/endpoints/customers/create) for full
details.
## 3. Create the case
Create the case on the customer, with your own case number. Send it **without** case vouchers — the entries that make up the debt are registered in Debbie, not pushed from the law firm system.
```json POST /v1/{tenantId}/cases theme={null}
{
"customerId": "{customerId}",
"currency": "DKK",
"customJournalNumber": {
"type": "CUSTOM_STRING",
"journalNumber": "2026-00417"
}
}
```
The response gives you both ids to store: `{ "id": "b2b0…", "caseSeqId": 10427 }`.
Then redirect the user into Debbie to register the claim on the new case:
```
https://app.debbiecollect.com/cases/{caseSeqId}
```
The invoices, their interest terms and any attachments are added there, against Debbie's own voucher types and interest rules.
See [POST Create case](/api-reference/endpoints/cases/create) for full
details.
## 4. Register deposits paid to the law firm
Payments the debtor makes directly to the client account must be replicated into Debbie, so reminders, payment plans and court steps work from what has actually been paid.
```json POST /v1/{tenantId}/case-vouchers/{caseId} theme={null}
{
"voucherTypeId": "c51f2f6a-8081-45ef-b52d-5e0569fdf12e",
"amount": 100000,
"currency": "DKK",
"date": "2026-06-04",
"source": "COLLECTOR",
"referenceId": "BANK-2026-06-04-0093",
"transactionAccountId": "{transactionAccountId}"
}
```
* `voucherTypeId` `c51f2f6a-8081-45ef-b52d-5e0569fdf12e` is Debbie's built-in deposit type, the same on every tenant. The full list is at `GET /voucher-types`.
* **Amounts are integers in the minor unit**, and a deposit is positive: `100000` is 1,000.00 DKK.
* **`source` is `COLLECTOR`** — the payment was collected by the law firm on behalf of its client. `CREDITOR` is for money the debtor paid the client directly.
* **`referenceId`** is the payment's own reference — use the bank transaction id, so the deposit can be reconciled against the client account. Guard against a replay double-booking it with an `Idempotency-Key` on the request.
* **`transactionAccountId`** is the account the money landed on. See [Transaction accounts](#transaction-accounts).
By default Debbie distributes the amount using the tenant's distribution rules. To settle specific vouchers instead, send `distribute` as an array of `{ "value": { "amount": 50000, "caseVoucherReferenceId": "F-100241" } }` entries — one per voucher, keyed by the voucher's `referenceId` in Debbie or by `caseVoucherId` — summing to the deposit's `amount`.
See [POST Add case voucher](/api-reference/endpoints/case-vouchers/create) for
full details.
### Transaction accounts
Set `transactionAccountId` on every deposit. Without it the payment is registered on the case but sits outside any account, and a day's payments in Debbie cannot be reconciled against a bank statement.
Create the accounts once, up front:
```json POST /v1/{tenantId}/transaction-accounts theme={null}
{
"name": "Client account — Nordea 2010 1234567890",
"type": "BANK_ACCOUNT",
"referenceId": "2010-1234567890"
}
```
`type` is `BANK_ACCOUNT` for a bank account and `PSP` for a payment service provider account. `referenceId` is your own id for the account — the account number the law firm system knows it by.
There are two ways to model them:
* **One account for the law firm system.** Every payment the integration registers lands on a single account named after the system. Quick, and enough when the reconciliation happens entirely on the law firm side.
* **One account per real client account.** The firm's actual client accounts are modelled one to one. A day's deposits then reconcile directly against the bank statement, and a payment can be traced to the account it arrived on. Prefer this.
`GET /transaction-accounts` lists them paginated, `PATCH /transaction-accounts/{id}` renames one or updates its `referenceId`, and `DELETE /transaction-accounts/{id}` removes one that is no longer in use.
See [GET Get transaction
accounts](/api-reference/endpoints/transaction-accounts/get) for full details.
### Booking the client account
Every payment landing on the client account is booked on the client it belongs to, on the day it arrives. That booking stays in the law firm system — pushing the payment to Debbie keeps the collection process working from a correct balance, it does not do the bookkeeping.
Payments the debtor makes *through* Debbie — card, MobilePay, Swish, Vipps — are the exception. They arrive on `deposits.booked` when the debtor pays, but the acquirer pays out days later, so they are booked by hand when the money does. Use the event to show the payment on the matter, not to trigger a journal entry.
## 5. Receive payments, status changes and settlements
### Payments Debbie collects
A deposit has a life after it arrives — it can be moved to another case, taken off one, deleted or restored — and a law firm booking client funds has to follow all of it, not just the arrival. Each step is its own event, and they all carry the same payload: the deposit as `caseVoucher`, its `creditorId` and `caseId`, plus `fromCaseId` and `toCaseId` where the event moved it.
| Event | Fires when |
| - | - |
| `deposits.created` | The deposit was created, with or without a case |
| `deposits.booked` | It was booked on a case it was not on before |
| `deposits.moved` | It moved from one case to another — `fromCaseId` and `toCaseId` |
| `deposits.unbooked` | It came off its case without landing on another — `fromCaseId` |
| `deposits.deleted` | It was deleted |
| `deposits.restored` | A deleted deposit was restored |
A deposit created directly on a case fires both `deposits.created` and `deposits.booked`, because booking it is also what resolves how it is distributed.
Subscribing to `deposits.booked` alone is not enough. It fires when a deposit
lands on a case, and never again — a later move, unbooking or deletion is a
different event. A law firm system that listens only for `booked` will show
payments on matters they were taken off months earlier.
They fire for *every* deposit, including the ones you pushed in step 4 — keep the `caseVoucherId` those calls returned and skip their events, or the same payment is recorded twice. Deduplicate redeliveries on `caseVoucherEventId`, which is unique per event; `caseVoucherId` is not, since the same deposit produces several.
### What Debbie imposes during collection
`case-vouchers.create` fires for every voucher created in Debbie. `data.source` says which side it came from — `COLLECTOR` for the collector, `CREDITOR` for the client — and `data.category` what it is (`fee`, `courtcost`, `interest`, `disbursement`, `collectioncommission`, …). `case-vouchers.update` and `case-vouchers.delete` follow when a voucher changes or is removed.
Subscribe to these to *see* what happens on the case, but do not rebuild the balance from them — read it back with `GET /v1/{tenantId}/cases/{caseId}`, or deep-link the user into Debbie.
### Case status
`cases.update` reports changes to the case. On a status transition `data.status` carries the new status — `PENDING`, `VERIFIED` or `ENDED` — and on an ended case `data.endReasonId` and `data.handle` say why: paid in full, written off, withdrawn.
`cases.merge` fires when Debbie merges two cases for the same debtor — the event that tells you two of your matters are now handled as one.
### Settlement of the client
When clients are settled, a billing is created and `billings.create` fires with a `billingId`. A settlement has two halves, and both have to be booked in the law firm system.
**The payment distribution** — how the money that came in was split:
```
GET /v1/{tenantId}/billings/{billingId}/deposit-distribution
```
Per deposit: which case and customer it belongs to, which vouchers it was distributed to, how much is `overpayment`, and which vouchers carry `collectionCommission`. This is what tells you the collection revenue and the amount payable to the client.
**The fees and disbursements** — what the client is charged for the work:
```
GET /v1/{tenantId}/billings/{billingId}/billing-vouchers
```
Per entry: the `category` (`fee` for honorarer, `disbursement` for udlæg), the `label` and the `amount` excluding VAT, the `vat` charged on it, and the case and creditor it belongs to. Both categories are returned by default; filter with `?category=["fee"]` or `?category=["disbursement"]` — JSON encoded, as on Debbie's other list filters — when the two are booked in separate runs.
Both are paged as `items` plus `meta`, 25 per page.
The two endpoints do not overlap. A fee charged on a specific deposit belongs
to that deposit's distribution and is reported there as
`collectionCommission`; `billing-vouchers` returns only the entries that stand
on their own. Book both and nothing is counted twice — or missed.
`payouts.create` then reports the actual payouts, with `type` distinguishing a `CREDITOR_RECEIVABLES` settlement, an `OVERPAYMENT` refund to the debtor and a `COURT_FEE`, and `caseId` / `caseSequentialId` linking back to the matter.
## 6. Take in cases that start in Debbie
Unless the firm has closed those routes, cases also arrive in Debbie from spreadsheets, from the clients' own API calls and from Debbie's accounting integrations. Without a return path the firm's register holds only the matters a lawyer opened there.
`cases.create` is the trigger, and carries identifiers only:
```json theme={null}
{
"event": "cases.create",
"time": "2026-06-04T09:12:44.021Z",
"data": {
"caseId": "b2b0…",
"id": 10427,
"referenceId": "…",
"customerId": "…",
"creditorId": "…"
}
}
```
Read the case with `GET /v1/{tenantId}/cases/{caseId}` and the party with `GET /v1/{tenantId}/customers/{customerId}`, then open the matter and store `caseId` and `id` — the sequential case id you would otherwise have got from `POST /cases`.
`creditorId` maps to a client you already have, because clients are only created in the law firm system. If it does not, the case belongs to a creditor created in Debbie after all — alert on that rather than inventing a client.
The case number needs a decision of its own. Such a case carries Debbie's journal number and can start moving before you hear about it: `cases.create` is dispatched before the case is moved to its status, and delivery is asynchronous, so the first letter may already have gone out by the time your receiver runs. Patching quickly does not win that race, so choose one:
* **Adopt Debbie's number.** Store the event's `id` as the matter's case number. It is already on Debbie's letters and court documents, so nothing goes out under a number the other system does not know.
* **Hold the case until your number is on it.** Agree with the Debbie team that these cases land in a workflow stage that sends nothing, then patch `customJournalNumber` with `PATCH /v1/{tenantId}/cases/{caseId}` before releasing them. Use this when the firm's number has to be on the documents.
`customers.create` does the same for a party created in Debbie without a case — worth subscribing to if the law firm system keeps its own party register.
## Webhooks back to the law firm system
| Event | Why you want it |
| - | - |
| `cases.create` | A case was created in Debbie — open the matter, see [step 6](#6-take-in-cases-that-start-in-debbie) |
| `customers.create` | A party was created in Debbie |
| `creditors.create` | A creditor was created in Debbie — only if the firm allows that at all, and then to create the client |
| `deposits.created` | A payment was registered |
| `deposits.booked` | A payment was booked on a case |
| `deposits.moved` | A payment moved to another case |
| `deposits.unbooked` | A payment came off its case |
| `deposits.deleted` | A payment was deleted |
| `deposits.restored` | A deleted payment was restored |
| `case-vouchers.create` | Fees, interest and deposits imposed in Debbie |
| `case-vouchers.update` | A voucher amount or date changed |
| `case-vouchers.delete` | A voucher was removed |
| `cases.update` | The case changed — a status transition carries the new status and, on ended cases, the end reason |
| `cases.merge` | Two cases were merged into one |
| `billings.create` | A settlement run completed — fetch the deposit distribution |
| `payouts.create` | Money was paid out to the client or refunded to the debtor |
| `payment-plans.create` | A payment plan was created |
| `payment-plans.update` | A payment plan changed — activation, completion and cancellation arrive as a `status` field |
### Delivery
Every delivery is a `POST` of `{ "event": …, "time": …, "data": { … } }`.
* Debbie sends `X-Verification-Token` with the token from your subscription. **Verify it on every request** before acting on the payload.
* Any non-2xx counts as a failure. The first delivery is immediate; a failure is retried up to 7 more times with exponential backoff — roughly 1, 3, 8, 21, 55, 149 and 404 minutes after the previous attempt, about eleven hours end to end.
* Acknowledge with 200 as soon as the payload is persisted, and process asynchronously.
* Retries replay an unchanged body, so the handler must be idempotent. There is no single `data.id` across events — key on what each carries: `caseVoucherId` for `case-vouchers.*`, and `caseVoucherEventId` for `deposits.*`; `id` for `billings.create` and `payouts.create`; `caseId` for `cases.create`, and with `status` for `cases.update`; `customerId`, `creditorId` and `paymentPlanId` for their own events; `fromCaseId` and `toCaseId` for `cases.merge`.
List deliveries with `GET /webhooks/items`, filtered by `webhookId` and `state`, to reconcile what you received against what Debbie sent. Deliveries that exhausted their retries can be re-sent from *Developers → Webhooks*.
See [Get webhook items](/api-reference/endpoints/webhooks/get-items) and the
payload of each event under Webhooks in the API reference.
## Scopes
Grant the API key only what the integration uses:
| Scope | Needed for |
| - | - |
| `read:creditors`, `write:creditors` | Step 1 |
| `read:customers`, `write:customers` | Steps 2 and 6 |
| `read:cases`, `write:cases` | Steps 3 and 6 |
| `read:case-vouchers`, `write:case-vouchers` | Steps 3 and 4 |
| `read:voucher-types` | Resolving `voucherTypeId` |
| `read:billings` | Step 5, the deposit distribution and the fees and disbursements |
| `read:transaction-accounts`, `write:transaction-accounts` | Managing the accounts deposits are registered on |
| `read:webhooks`, `write:webhooks` | Inspecting deliveries and re-sending failed ones |
| `read:files`, `write:files` | Attaching invoice PDFs to vouchers |
| `write:documents` | Hanging documents on a case or a creditor |
## Optional extensions
* **Attach documents.** Upload the invoice or contract with `POST /files`, then either reference it as the `appendix` of the case voucher so it follows the case into letters and court documents, or hang it on the case itself with `POST /documents` — which is also how a foundation, a verdict or a settlement is registered, and where `minAccessRole` decides whether the debtor can see it.
* **Enrich with custom fields.** Send `properties` on the case or the voucher to carry law-firm-specific data into Debbie's letter templates.
## Agree per firm
These are settled per law firm and per case management system rather than by the API, and each changes what the integration has to build. Write them down before development starts.
### KYC, AML and conflicts of interest
Money laundering rules follow the client relationship; conflict-of-interest rules follow the parties on both sides of the matter. Both belong to the law firm. Debbie holds neither the onboarding nor its documentation, and nothing in this integration performs, records or evidences a check — what the integration must guarantee is that the checks come first.
* **When the client is cleared.** The creditor is created in Debbie only after the firm's KYC and AML procedure has passed, beneficial owners included, so no client enters the collection flow ahead of its clearance.
* **When the parties are cleared.** The debtor and any other party pass the conflict-of-interest check before the customer is created in Debbie. A conflict can come from the counterparty rather than the client, so this check runs per matter, not once per client.
* **What happens when a check fails or a clearance lapses.** Either handover is blocked in the law firm system, or the case is created and held in a workflow stage until it is resolved.
* **Where the documentation lives, and for how long.** Normally the law firm system, for the statutory retention period, unaffected by a case ending in Debbie.
### Process and accounting
| Decision | What it settles |
| - | - |
| **The payment identifier** | Which system generates the payment reference on the letters to the debtor — the FI code, or its equivalent — and therefore where an incoming payment is matched to exactly one case. Either Debbie's reference is printed and matched in Debbie, or the firm's is printed, matched in the law firm system and pushed as a deposit. Mixing the two leaves payments that match nothing. |
| **The journal format** | Which format and account codes the law firm system expects for payments, fees and disbursements, and whether they arrive as a file import or over its API. Debbie reports amounts and categories; mapping them onto the firm's chart of accounts is part of the integration, not the API. |
| **Time registration and client invoicing** | Where the lawyer's time is registered, and which system invoices the engagement. Debbie settles the collection case; the law firm system invoices the legal work. If time is meant to reach the collection case, agree how before it is registered in two places. |
## Checklist before going live
`creditorId`, `customerId`, `caseId` and `caseSeqId` are persisted, and
`customJournalNumber` is set on every case.
`Idempotency-Key` on every write, `referenceId` carried on every deposit,
and failed calls queued rather than dropped.
`X-Verification-Token` checked, duplicates tolerated, 200 returned before
downstream work.
Client-account payments pushed as `source: "COLLECTOR"` with a
`transactionAccountId`, the whole `deposits.*` lifecycle consumed with your
own deposits skipped, and payments made through Debbie kept out of the daily
booking until the acquirer pays out.
Vouchers, interest and fees are read from Debbie rather than rebuilt.
`cases.create` opens the matter, and the case number question is decided.
KYC and AML completed before the creditor is created, the
conflict-of-interest check run on the parties before the customer is, and
the failed-check case agreed.
On `billings.create`, both halves are fetched — the deposit distribution and
the fees and disbursements — and booked together.
# Settlements
Source: https://documentation.debbiecollect.com/guides/settlements
Read a billing back in full: the payments, how they were split, and what the creditor is charged
A settlement — a *billing* — is the periodic account between a creditor and the
collector. It says how the money collected on the creditor's cases was split,
and what the creditor is charged for the work. It ends either in a payout to the
creditor or in an amount the creditor owes.
Posting one correctly means fetching **both** halves. The payments and their
distribution are one endpoint; the fees and disbursements are another. Take only
the first and the account is half posted.
This guide covers billing settlements between creditor and collector.
[Register case voucher
allocation](/api-reference/endpoints/case-vouchers/allocations) records a
creditor payment or credit note against one or more case vouchers. Its
response lists the created vouchers, one per case, rather than a billing to
post.
## The flow
The webhook carries a `billingId`, the `creditorId` and the currency.
`GET /v1/{tenantId}/billings/{billingId}/deposit-distribution` — every
payment in the settlement and how it was split.
`GET /v1/{tenantId}/billings/{billingId}/billing-vouchers` — the fees
(honorarer) and disbursements (udlæg).
Revenue, commission, fees, disbursements, overpayments and the net amount.
## 1. The webhook
```json theme={null}
{
"event": "billings.create",
"time": "2026-07-01T02:15:03.221Z",
"data": {
"billingId": "9c1f2b3a-4d5e-6f70-8192-a3b4c5d6e7f8",
"id": 40218,
"date": "2026-06-30T22:00:00.000Z",
"billingAppendixId": "869cd519-beb7-4c8c-a854-760df763daad",
"creditorId": "a7fcf07c-74f2-40d9-8ea6-e67b07b14ca4",
"currency": "DKK"
}
}
```
Verify the `X-Verification-Token` header, acknowledge with 200, and do the
fetching asynchronously. `billingId` is what both endpoints below take. Key the
handler on it so a redelivery does not post the settlement twice.
`payouts.create` follows when the money actually moves, with `type` telling you
whether it is a `CREDITOR_RECEIVABLES` settlement, an `OVERPAYMENT` refund to
the debtor, or a `COURT_FEE`.
## 2. The deposit distribution
```
GET /v1/{tenantId}/billings/{billingId}/deposit-distribution
```
One entry per payment in the settlement: which case and customer it belongs to,
which case vouchers it was distributed across, how much of it was an
overpayment, and which of the distributed amounts carry collection commission.
```json theme={null}
{
"meta": { "currentPage": 0, "pageSize": 25 },
"items": [
{
"currency": "DKK",
"isAdjustment": false,
"depositCaseVoucher": {
"caseVoucherId": "1a2b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d",
"id": 118067630,
"amount": 250000,
"source": "COLLECTOR",
"state": "PARTIAL_PAYMENT",
"paymentType": "BANK_TRANSFER",
"transactionAccountId": "6f2a1c8e-9b0d-4e3f-8a71-2c4d5e6f7a8b"
},
"customer": { "referenceId": "CUST-40218" },
"case": {
"caseId": "3f1c2d4e-5a6b-7c8d-9e0f-1a2b3c4d5e6f",
"id": 10427,
"groupId": "0b1a0f3c-6c1d-4b8f-9b6b-6f6a1f2e7a10",
"groupLabel": "Consumer"
},
"caseVouchers": [
{
"caseVoucherId": "7a8b9c0d-1e2f-3a4b-5c6d-7e8f9a0b1c2d",
"referenceId": "D12412347",
"voucherTypeId": "eb41e58e-fccf-419d-a771-cd5027fe6e87",
"amount": 200000,
"source": "CREDITOR",
"collectionCommission": true
},
{
"caseVoucherId": "2d3e4f50-6a7b-8c9d-0e1f-2a3b4c5d6e7f",
"referenceId": null,
"voucherTypeId": "4c3ccbbf-0651-45b2-b37b-4fe736acfd7e",
"amount": 50000,
"source": "COLLECTOR",
"collectionCommission": false
}
],
"overpayment": 0
}
]
}
```
* **`customer.referenceId` and `caseVouchers[].referenceId`** are the creditor's
own identifiers — the customer number and the invoice number that were sent
in. They are what makes the settlement postable in the creditor's system.
* **`depositCaseVoucher.amount` is the payment**; the amounts in `caseVouchers`
plus `overpayment` add up to it.
* **`overpayment`** is owed back to the debtor, not to the creditor.
### `source` says who imposed what
* **`CREDITOR`** — imposed by the creditor: the invoices, reminder and
compensation fees sent at handover, and the payments and credit notes the
creditor registered itself. These already exist in the creditor's own
bookkeeping.
* **`COLLECTOR`** — imposed by the collector during collection: collection fees,
court fees, interest.
The two do not line up. A `CREDITOR` entry can be settled by a payment the
collector received, and a `COLLECTOR` entry by a payment the creditor received
itself. `depositCaseVoucher.source` says who received the money;
`caseVouchers[].source` says who imposed what it paid. Read them separately —
treating one as a proxy for the other is the usual way a settlement fails to
reconcile.
### Registering payments and credit notes
Register payments received directly by the creditor and credit notes through
[Register case voucher
allocation](/api-reference/endpoints/case-vouchers/allocations). Both
create one voucher with source `CREDITOR` per matched case and apply its amount
to the specified case vouchers through fixed distributions on that case.
Set `voucherTypeId` to select the entry:
| Entry | `voucherTypeId` |
| - | - |
| Payment | `c51f2f6a-8081-45ef-b52d-5e0569fdf12e` |
| Credit note | `ef2cdc50-230f-4046-b1af-0f9c498dddd3` |
Supply a `matches` array. Each match contains a positive `amount` in minor
units and exactly one of `caseVoucherId` or `caseVoucherReferenceId`, looked
up within `creditorId`. The identifiers can be mixed in the same request.
Partial amounts are supported, up to each target's remaining fixed-distribution
capacity. Each target may appear only once, and all targets must use the same
currency.
Debbie groups the matches by case, sums their amounts, and creates one payment
or credit note per case. Its fixed distributions only point to vouchers on
that same case. The response is an array containing each new `caseVoucherId`,
its `voucherTypeId`, and its `targetCaseVouchers` with the `matchedAmount` for
each target.
Send one `Idempotency-Key` for the entire request. All matches are registered
in one transaction: if any match fails, no payment or credit note is created.
A credit note reduces the invoice balance without recording cash received.
It already exists in the creditor's own books; do not post its amount again as
a payment or as money paid out by the collector. The billing endpoints describe
the resulting billing and its charges, rather than a complete list of the
credit notes registered by the creditor.
Registering either type requires `write:case-vouchers`.
### Direct payments in the billing
Payments registered with `source: "CREDITOR"` are **not** in the distribution by
default, and the commission charged on them is reported as a separate fee among
the billing vouchers instead. Add `?includeDepositsWithSourceCreditor=true` to
have them reported here with their commission as part of the distribution.
`billing-vouchers` always reports that commission, whatever is passed here. So
when both halves of the settlement are taken — which is what this guide
recommends — leave the parameter off. Turning it on and also reading the
billing vouchers counts the commission on direct payments twice.
See [GET Get deposit distribution](/api-reference/endpoints/billing/get) for
full details.
## 3. The billing vouchers
```
GET /v1/{tenantId}/billings/{billingId}/billing-vouchers
```
The fees and disbursements on the settlement.
Only the ones that stand on their own are returned. A fee charged on a specific
deposit belongs to that deposit's distribution and is reported there as
`collectionCommission`, so booking both endpoints counts nothing twice — and
misses nothing.
```json theme={null}
{
"meta": { "currentPage": 0, "pageSize": 25 },
"items": [
{
"billingVoucherId": "5e6f7a8b-9c0d-1e2f-3a4b-5c6d7e8f9a0b",
"id": 8841,
"billingId": "9c1f2b3a-4d5e-6f70-8192-a3b4c5d6e7f8",
"label": "Retsafgift",
"category": "disbursement",
"voucherTypeId": "6991fa7e-5812-4948-be69-0001d1f7205f",
"amount": 75000,
"currency": "DKK",
"caseId": "3f1c2d4e-5a6b-7c8d-9e0f-1a2b3c4d5e6f",
"caseSequentialId": 10427,
"creditorId": "a7fcf07c-74f2-40d9-8ea6-e67b07b14ca4",
"creditorReferenceId": "CLIENT-4471",
"creditorName": "Nordisk Byg A/S",
"referenceId": null,
"text": null,
"createdAt": "2026-06-14T09:02:11.000Z",
"caseVoucher": null,
"depositCaseVoucher": null
}
]
}
```
* **`category`** is `fee` — the collector's own charge, a honorar — or
`disbursement`, an outlay paid on the creditor's behalf, an udlæg. They
usually go to different accounts, and can be fetched separately with
`?category=["fee"]` or `?category=["disbursement"]` (JSON encoded, as on
Debbie's other list filters). Both are returned when it is omitted.
* **`amount` excludes VAT**, and `vat` carries the VAT charged on the entry.
* **`caseId` and `caseSequentialId`** tie the charge to a case where there is
one; a charge that is not case specific has them null.
* **`depositCaseVoucher`** is the payment that triggered the charge, where there
is one. Commission on a payment made directly to the creditor appears here,
with `depositCaseVoucher.source` set to `CREDITOR`.
Do not derive the fees from the `case-vouchers.*` webhook stream instead. A
voucher event carries no billing reference, so nothing in it says which
settlement a fee ends up on — or whether it has been settled at all — and a
voucher can still be changed or removed after it was reported.
See [GET Get billing
vouchers](/api-reference/endpoints/billing/get-billing-vouchers) for full
details.
## 4. Posting it
| What | Where it comes from |
| - | - |
| Payments against the creditor's own receivables | Distribution entries with `caseVouchers[].source` `CREDITOR` |
| Collection entries settled out of those payments | Distribution entries with `caseVouchers[].source` `COLLECTOR` |
| Commission | `caseVouchers[].collectionCommission` on the distribution, and commission lines among the billing vouchers |
| Fees charged to the creditor | Billing vouchers with `category` `fee` |
| Disbursements charged to the creditor | Billing vouchers with `category` `disbursement` |
| Owed back to the debtor | `overpayment` on the distribution |
What is left is the net, which `payouts.create` reports when it moves.
Reconcile the parts against the settlement total before posting. If they do
not add up, something was missed — most often the billing vouchers, or the
direct payments landing on whichever side of
`includeDepositsWithSourceCreditor` you did not expect.
## Paging and scopes
Both endpoints return `items` plus `meta`, 25 per page by default, with no total
count — page with `page` and `pageSize` until a page returns fewer items than
`pageSize`. See [Pagination](/api-reference/pagination).
Both billing endpoints require `read:billings`.
# Introduction
Source: https://documentation.debbiecollect.com/index
The Debbie API is a RESTful interface, allowing you to programmatically update, add and access your data in the platform. It provides predictable URLs for accessing resources, and uses built-in HTTP features to receive commands and return responses.
## Check out the API Reference
API Reference - authorization, endpoints and webhooks