Skip to main content
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

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.
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

  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. Authenticate with Authorization: Bearer {token} — see Authentication.
  3. 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.
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.
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}
  • 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.

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
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:
The invoices, their interest terms and any attachments are added there, against Debbie’s own voucher types and interest rules.

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}
  • 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.
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.

API reference: Add case voucher

See POST Add case voucher 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:
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 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. 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:
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:
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:
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

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.

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 /files and reference it as the appendix of the case voucher, so it follows the case into letters and court documents.
  • 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

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.