# 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. Hero Light Hero Dark ## Check out the API Reference API Reference - authorization, endpoints and webhooks