Modelling Example: Debt Buyer
This document shows how to map a debt purchaser — a company that buys charged-off portfolios from originators and collects on its own behalf — onto the platform. The client described here ("CobraMax") is fictional. Companion examples: BNPL, Personal Loan, and Recurring Invoices.
The previous examples model the originator collecting its own fresh debt. A debt buyer is the inverse case, and it stresses different parts of the model:
- Onboarding is bulk import, not transactional placement. Thousands of claims arrive at once per purchased portfolio, with data of varying quality and age.
- The debt has a history the buyer didn't create. Original creditor, original due date, payments made before the sale, prior collection attempts.
- Prioritization drives everything. A buyer works a portfolio by expected recovery — scores and segmentation are first-class inputs, not nice-to-haves.
- There is no ongoing relationship and no new debt. No ledger, no recurring invoices, no acceleration mechanics — the balance was fixed at charge-off (plus whatever accrual the purchase contract allows).
Entity mapping
| Debt-buying concept | Platform entity / field |
|---|---|
| Debtor (from purchased file) | Account (one per debtor, may span portfolios) |
| Purchased portfolio | Claim.portfolioReference (one value per purchase/tranche) |
| Original creditor | Claim.creditorReference |
| Purchased debt (per obligation) | Claim (one per original obligation) |
| Original vs. placed due date | originalDueDate vs currentDueDate |
| Pre-sale payment history | Claim.repaymentsHistory (typed) |
| Original product/origination context | Claim.origination + embedded Claim.product |
| Chain of title (charge-off date, prior agency) | Claim.meta (context, no business logic) |
| Recovery prioritization | Claim.scores (EXTERNAL/INTERNAL/COLLECTION/BEHAVIORAL) and set_account_scores |
| Discounted settlement | Receive Instalment Plan and/or credit_claims for the waived part |
Field notes, verified against the ClientApi schema:
portfolioReferenceandcreditorReferenceare first-class claim fields — use them, notmeta, so reporting and strategy can segment by portfolio and original creditor.scoresaccepts typed entries (EXTERNALfor bought-in bureau scores,COLLECTIONfor the buyer's own recovery model);set_account_scoresupdates account-level scores later without touching claims.originationandrepaymentsHistoryare first-class claim fields: pre-sale payments go inrepaymentsHistoryas typed entries (amount,date,dueDate,outstandingAmount) and the original product/service context inorigination({type, name, brand, code}). Only the non-financial chain-of-title data (charge-off date, prior agency) remains inmeta.import_claimsis the right endpoint: it upserts (creates or updates from a full payload), which is exactly the semantics of loading a portfolio file and re-running it after corrections.create_claimsfails on duplicates; portfolio loads are idempotent re-runs.
Fictional client: "CobraMax"
Assumed policies:
- Buys charged-off consumer portfolios (telco, e-commerce, consumer loans) at a discount.
- Balances are frozen at purchase — no further interest accrual (keeps the example simple; if the purchase contract allows accrual, borrow the accrual section from the personal-loan example).
- Works portfolios by score: high-recovery segments get calls and generous settlement offers, low-recovery segments get low-cost digital-only journeys.
- Standard offer: settle for 70% via lump sum, or 100% via a 12-month instalment plan.
Worked example: importing the "NORTE-2026-Q1" portfolio
CobraMax buys 8,000 telco and loan debts from Telefónica del Norte. One file, one (batched)
import_claims load:
// POST /v1/{clientId}/import_claims (batched; ~100s of entries per call)
{
"TN-778812": {
"amount": 48000, // cents — the purchased balance, frozen
"currency": "EUR",
"originalDueDate": "2024-08-15", // when the debt originally fell due
"currentDueDate": "2026-02-01", // placement under CobraMax
"portfolioReference": "NORTE-2026-Q1",
"creditorReference": "TELEFONICA-NORTE",
"primaryDebtor": {
"debtorReference": "TN-DEB-4471",
"firstName": "Miguel",
"lastName": "Soto",
"contactInformation": {
/* last known contact data from the file */
},
},
"product": {
"productReference": "TN-CONTRACT-99231",
"type": "MOBILE_CONTRACT",
"name": "Plan Norte 30GB",
},
"scores": [
{ "type": "EXTERNAL", "value": "620" }, // bureau score bought with the file
{ "type": "COLLECTION", "value": "B" }, // CobraMax's own recovery model
],
"origination": {
"type": "service",
"name": "Mobile contract",
"brand": "Telefonica del Norte",
},
"repaymentsHistory": [
{ "date": "2025-03-10", "amount": 2000, "outstandingAmount": 46000 },
],
"meta": {
"purchaseDate": "2026-01-20",
"chargeOffDate": "2025-06-30",
"priorAgency": "AgenciaSur",
},
},
// ... more entries
}
Points worth copying:
originalDueDatecarries the real delinquency age — strategies and statute-of-limitation checks need it;currentDueDateis just the placement under the buyer.- Pre-sale payments and origination are typed fields (
repaymentsHistory,origination); only the remaining chain-of-title context (charge-off date, prior agency) lives inmeta. Many jurisdictions require producing this on request, so import it with the claim rather than keeping it only in the buyer's warehouse. - The same debtor across two portfolios resolves to one Account (same debtor reference),
with claims carrying different
portfolioReferencevalues — account-level strategy sees the whole exposure while portfolio reporting stays clean. - Re-running a corrected file is safe:
import_claimsupserts by claim reference.
Working the portfolio
- Segmented journeys: strategy branches on
scores— segment B gets the digital journey with a settlement offer on the landing page; segment D gets a minimal compliance-only journey. Scores can be refreshed later viaset_account_scores(account level) orupdate_claims(claim level) without reimporting. - Settlement at 70%: Miguel accepts €336 against his €480 debt. The lump sum is collected;
the remaining €144 is written off with
credit_claims(a credit resolves the claim when it zeroes the balance). Record the settlement terms in the credit's context/meta — that is the audit trail that the discount was contractual, not a data error. - Payment plan at 100%: alternatively the landing page offers a Receive Instalment Plan over the full balance — same mechanics as the other examples (internal compound claim, invalidation on a missed payment reinstates the full claim).
- Settlement breached after the claim was resolved: place a new claim for the remainder
with a typed relation
relatedClaims: [{ "type": "REINSTATES", "claimReference": <original> }]— preserves the delinquency lineage that statute-of-limitation checks and journey configuration need. - Statute of limitations: claims nearing the limitation date (computed from data imported
in
meta/originalDueDate) move to a restricted journey — this is client policy encoded in strategy, not a platform feature; flag it explicitly during discovery.
Discovery questions for a real debt buyer
- What data actually comes with the file? Contact data quality, chain of title,
pre-sale payment history, bureau scores. This decides how much lands in
metavs. proper fields and whether skip-tracing/enrichment happens before or after import. - Is the balance frozen at purchase, or does the contract allow post-purchase accrual?
Frozen → nothing to build. Accruing → reuse the
update_claimsfee-accrual integration from the personal-loan example. - What are the settlement rules (floor percentage, who approves exceptions, plan length
limits)? → Encodes directly into strategy + landing-page offers, and defines when
credit_claimswrite-offs are legitimate. - How do they need to report by portfolio?
portfolioReferencesupports slicing; confirm the tranche granularity (one reference per purchase, per seller, per vintage?) before the first import — it is painful to re-segment afterwards. - Are there regulatory constraints on contacting aged debt (statute of limitations,
required disclosures naming the original creditor)? →
creditorReferencemust be populated and correct on every claim; disclosure text becomes part of the communication templates.
Related use cases
This example focuses on what to model; the step-by-step mechanics of each API call are covered by the generic use cases:
- Authentication — obtaining the access token every request needs
- Create Claims — the mechanics of placing claims (single and batched)
- Update Claims — partial updates to existing claims (fees, due dates, balances)
- Register Payments — crediting claims for payments received on your side
- Resolve Claims — closing claims with the correct resolution reason
- Get Account Claims — reading claims (including their relations) back from the platform