At a glance
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.
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.
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
- Get a sandbox tenant. Contact the Debbie team. Every endpoint is scoped by
tenantIdin the path, so sandbox and production differ only by that id and the API key. - Create an API key. In the platform, go to Developers → API, name the key and grant the scopes under Scopes. Authenticate with
Authorization: Bearer {token}— see Authentication. - Subscribe to webhooks. Under Developers → Webhooks, register the endpoint that should receive the events below.
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.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 returnedid on the client record.
POST /v1/{tenantId}/creditors
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.
API reference: Create creditor
See POST Create creditor 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.
POST /v1/{tenantId}/customers?creditorId={creditorId}
relationisdebtorfor the party who owes the money,alternative-contactfor anyone else on that side — a lawyer, a guardian, an administrator.contact: truemarks the user Debbie addresses its communication to.referenceIdis 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.
POST /customers/{customerId}/users.
API reference: Create customer
See POST Create customer 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.POST /v1/{tenantId}/cases
{ "id": "b2b0…", "caseSeqId": 10427 }.
Then redirect the user into Debbie to register the claim on the new case:
API reference: Create case
See POST Create case 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.POST /v1/{tenantId}/case-vouchers/{caseId}
voucherTypeIdc51f2f6a-8081-45ef-b52d-5e0569fdf12eis Debbie’s built-in deposit type, the same on every tenant. The full list is atGET /voucher-types.- Amounts are integers in the minor unit, and a deposit is positive:
100000is 1,000.00 DKK. sourceisCOLLECTOR— the payment was collected by the law firm on behalf of its client.CREDITORis for money the debtor paid the client directly.referenceIdis 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 anIdempotency-Keyon the request.transactionAccountIdis the account the money landed on. See Transaction accounts.
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.
API reference: Add case voucher
See POST Add case voucher for
full details.
Transaction accounts
SettransactionAccountId 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:
POST /v1/{tenantId}/transaction-accounts
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.
API reference: Transaction accounts
See GET Get transaction
accounts 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 ondeposits.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 ascaseVoucher, its creditorId and caseId, plus fromCaseId and toCaseId where the event moved it.
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.
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 andbillings.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:
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:
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:
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
idas 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
customJournalNumberwithPATCH /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
Delivery
Every delivery is aPOST of { "event": …, "time": …, "data": { … } }.
- Debbie sends
X-Verification-Tokenwith 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.idacross events — key on what each carries:caseVoucherIdforcase-vouchers.*, andcaseVoucherEventIdfordeposits.*;idforbillings.createandpayouts.create;caseIdforcases.create, and withstatusforcases.update;customerId,creditorIdandpaymentPlanIdfor their own events;fromCaseIdandtoCaseIdforcases.merge.
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.
API reference: Webhooks
See Get webhook items and the
payload of each event under Webhooks in the API reference.
Scopes
Grant the API key only what the integration uses:Optional extensions
- Attach documents. Upload the invoice or contract with
POST /filesand reference it as theappendixof the case voucher, so it follows the case into letters and court documents. - Enrich with custom fields. Send
propertieson 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
Checklist before going live
1
Identifiers are stored on both sides
creditorId, customerId, caseId and caseSeqId are persisted, and customJournalNumber is set on every case.2
Every write is replayable
Idempotency-Key on every write, referenceId carried on every deposit, and failed calls queued rather than dropped.3
The webhook receiver verifies and is idempotent
X-Verification-Token checked, duplicates tolerated, 200 returned before downstream work.4
Deposits flow both ways
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.5
Nothing Debbie owns is copied back
Vouchers, interest and fees are read from Debbie rather than rebuilt.
6
Cases can arrive from Debbie too
cases.create opens the matter, and the case number question is decided.7
Clients and parties are cleared before they reach Debbie
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.
8
Settlement is booked in full
On
billings.create, both halves are fetched — the deposit distribution and the fees and disbursements — and booked together.