Skip to main content

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:

  1. Onboarding is bulk import, not transactional placement. Thousands of claims arrive at once per purchased portfolio, with data of varying quality and age.
  2. The debt has a history the buyer didn't create. Original creditor, original due date, payments made before the sale, prior collection attempts.
  3. Prioritization drives everything. A buyer works a portfolio by expected recovery — scores and segmentation are first-class inputs, not nice-to-haves.
  4. 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 conceptPlatform entity / field
Debtor (from purchased file)Account (one per debtor, may span portfolios)
Purchased portfolioClaim.portfolioReference (one value per purchase/tranche)
Original creditorClaim.creditorReference
Purchased debt (per obligation)Claim (one per original obligation)
Original vs. placed due dateoriginalDueDate vs currentDueDate
Pre-sale payment historyClaim.repaymentsHistory (typed)
Original product/origination contextClaim.origination + embedded Claim.product
Chain of title (charge-off date, prior agency)Claim.meta (context, no business logic)
Recovery prioritizationClaim.scores (EXTERNAL/INTERNAL/COLLECTION/BEHAVIORAL) and set_account_scores
Discounted settlementReceive Instalment Plan and/or credit_claims for the waived part

Field notes, verified against the ClientApi schema:

  • portfolioReference and creditorReference are first-class claim fields — use them, not meta, so reporting and strategy can segment by portfolio and original creditor.
  • scores accepts typed entries (EXTERNAL for bought-in bureau scores, COLLECTION for the buyer's own recovery model); set_account_scores updates account-level scores later without touching claims.
  • origination and repaymentsHistory are first-class claim fields: pre-sale payments go in repaymentsHistory as typed entries (amount, date, dueDate, outstandingAmount) and the original product/service context in origination ({type, name, brand, code}). Only the non-financial chain-of-title data (charge-off date, prior agency) remains in meta.
  • import_claims is 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_claims fails 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:

  • originalDueDate carries the real delinquency age — strategies and statute-of-limitation checks need it; currentDueDate is 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 in meta. 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 portfolioReference values — account-level strategy sees the whole exposure while portfolio reporting stays clean.
  • Re-running a corrected file is safe: import_claims upserts 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 via set_account_scores (account level) or update_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

  1. 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 meta vs. proper fields and whether skip-tracing/enrichment happens before or after import.
  2. Is the balance frozen at purchase, or does the contract allow post-purchase accrual? Frozen → nothing to build. Accruing → reuse the update_claims fee-accrual integration from the personal-loan example.
  3. What are the settlement rules (floor percentage, who approves exceptions, plan length limits)? → Encodes directly into strategy + landing-page offers, and defines when credit_claims write-offs are legitimate.
  4. How do they need to report by portfolio? portfolioReference supports slicing; confirm the tranche granularity (one reference per purchase, per seller, per vintage?) before the first import — it is painful to re-segment afterwards.
  5. Are there regulatory constraints on contacting aged debt (statute of limitations, required disclosures naming the original creditor)? → creditorReference must be populated and correct on every claim; disclosure text becomes part of the communication templates.

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