API Reference
A REST API for creditor systems. JSON in, JSON out. HTTPS only. Credential: short-lived bearer token or long-lived API key (roadmap Q3 2026).
- Versioned at
/api/v1/ - Idempotent on request-id
- HMAC-signed webhooks
- RLS-enforced per creditor
POST /api/v1/creditor/place-account
Authorization: Bearer <token>
Content-Type: application/json
{
"consumer": { "first_name": "Jane", "last_name": "Doe", "email": "jane@example.com" },
"original_creditor": "Sample Federal CU",
"principal_balance": 5247.63,
"charge_off_date": null,
"account_phase": "phase0"
}
Overview
All endpoints live under https://www.debt-digest.com/api/v1/. Request and response bodies are JSON. All writes are idempotent on a request-ID basis.
Versioning. Use /api/v1/<path>. The unversioned /api/<path> form still works as a transitional alias but returns RFC 8594 Deprecation + Sunset + Link headers. Sunset for unversioned: 2027-05-03 (365-day grace). Webhooks, healthcheck, and internal endpoints are exempt. They keep their fixed URLs. Full policy: app/docs/API_VERSIONING.md.
Authentication
Today: session-based. Log in at POST /api/auth/creditor/login, receive a bearer token, send it on every request:
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9...
Tokens expire after 4 hours. Refresh by re-authenticating.
Q3 2026 roadmap: API keys for service-to-service integrations. No password exchange required. Scoped to specific endpoints.
Errors
Standard shape:
{
"error": "Insufficient permissions",
"code": "FORBIDDEN",
"requestId": "01h8k2rjm7c3q4v5w6x7y8z9ab"
}
| Status | Code | Meaning |
|---|---|---|
| 400 | VALIDATION_ERROR | Request body or query failed validation. See details field. |
| 401 | UNAUTHENTICATED | Missing or invalid bearer token. |
| 403 | FORBIDDEN | Authenticated but not permitted. |
| 404 | NOT_FOUND | Resource does not exist or you cannot see it. |
| 409 | CONFLICT | State conflict (e.g., settlement already accepted). |
| 422 | UNPROCESSABLE | Business rule violated (e.g., principal below floor). |
| 429 | RATE_LIMITED | Too many requests. Honor Retry-After header. |
| 500 | INTERNAL | We goofed. requestId is in the response - share it with support. |
Rate limits
- 60 requests/min/IP on general API.
- 5 requests/min/IP on
/api/auth/*endpoints. - 100 requests/min/creditor on list endpoints (coming Q2 2026).
- List-endpoint
limitquery parameter is clamped server-side to 100.
Performance targets
We track and publish response-time percentiles. The health commitments below are SLOs, not SLAs - we use them to decide what to fix first, and share the numbers on request during pilots.
| Metric | Target | What happens if we miss |
|---|---|---|
p50 latency (median) | < 150ms | Logged internally, reviewed weekly |
p95 latency | < 500ms | Flags degraded status on /status |
p99 latency | < 1500ms | Triggers slow-query investigation |
| 5xx error rate | < 0.5% of requests | Email to pilot contact within 24h |
| Uptime | 99.9% monthly | See /status - incidents enumerated there |
Queries running ≥1s are logged automatically with a truncated SQL preview so we can find N+1 offenders before they affect you.
Public REST API (v1)
The /external/v1 surface is the integration API for creditor systems that push accounts to Debt Digest and pull state back into a system of record. It is authenticated with an API key (not a portal session), tenant-scoped to the creditor that owns the key, and rate-limited per key.
Base URL: https://www.debt-digest.com/external/v1/
Mounted separately from the internal portal API. Internal endpoints continue to live under /api/creditor/*. The public surface uses its own /external/v1 prefix so the version-rewrite that aliases /api/v1/* → /api/* for internal clients does not affect external integrations.
API keys
Mint, list, and revoke keys from the Settings tab of the creditor portal. Minting requires the admin role. Each raw key is shown exactly once: store it in your secret manager immediately; it is unrecoverable.
Authorization: Bearer 1a2b3c4d5e6f7890abcdef1234567890abcdef1234567890abcdef1234567890
Rate limit: 100 requests per 15 minutes per API key. Exceeded requests return 429 with a Retry-After: 900 response header.
Tenant isolation: every query is scoped to the creditor the key resolves to. Account IDs that belong to another creditor read as 404, identical to a non-existent ID, so cross-tenant existence cannot be inferred.
Public API endpoints
Identity
Returns the creditor profile owning the key plus the key's own metadata (id, name, prefix, last-used, created-at). Confirms key ownership during setup.
Portfolio metrics
Aggregate counts, total balance, resolution count, resolution rate, and a status histogram across every account.
List accounts
limit is clamped to 100. status is optional and filters to one of the public account statuses.
Get one account
Returns the account row plus every note attached to it.
Import a single account
{
"consumerEmail": "member@example.com",
"firstName": "Jane",
"lastName": "Doe",
"originalCreditor": "Sample Federal CU",
"originalBalance": 5247.63,
"principalBalance": 5247.63,
"chargeOffDate": null,
"phase": "phase1"
}
Runs the same consumer auto-create, FDCPA notice generation, statement-signal extraction, and outreach-profile flow as the CSV importer. phase defaults to phase1; phase0 placements in unlicensed jurisdictions return 403 STATE_NOT_AUTHORIZED.
Update an account
{ "status": "contacted", "currentBalance": 4980.00 }
Partial update: at least one of status or currentBalance is required. Terminal statuses (settled, paid_in_full) and the consumer-only disputed status are workflow-gated and rejected with 400.
Set status only
Equivalent to PATCH with status only; kept for clients that prefer a verb-style RPC shape.
Add a note
Free-text note (≤ 5000 chars) appended to the account audit trail.
List settlement offers for an account
Returns every settlement offer attached to the account across all statuses (pending, countered, accepted, paid, rejected, expired).
List active webhooks
Read-only mirror of the creditor portal webhook list. Signing secrets are never included; manage webhooks (create, test, delete) from the Settings tab.
Schema: the full OpenAPI 3.0 spec is at app/docs/openapi.yaml in the repo. Every /external/v1/* path lives under the Public API v1 tag, secured by the ApiKeyAuth scheme.
Accounts
List accounts
Paginated list. cursor for page-forward, status filter, search matches account ID or consumer last-4 SSN.
Place a single account
{
"consumerEmail": "member@example.com",
"originalBalance": 5280.00,
"principalBalance": 5280.00,
"dpd": 78,
"accountType": "credit_card",
"accountPhase": "intercept",
"last4ssn": "4321",
"creditorReference": "ABC-00123"
}
Returns 201 with accountId and FDCPA §809(a) validation notice metadata.
Bulk upload
Array of up to 1,000 accounts per batch. Returns row-level success / failure report. See CSV schema for column definitions.
Account detail
Add account note
Settlement
Configure settlement matrix
Per-tier discount floors: lump_sum, 12_month, 24_month, 36_month. Values as decimals (0.70 = 70% of principal).
Accept a firm offer
Webhooks
Configure a single URL per creditor to receive events. We POST signed JSON payloads. See the verification guide.
Configure endpoint
Test delivery
Events emitted
account.cured- an account returned to 0 DPD and has stayed current 60+ days.settlement.accepted- a firm offer was accepted and payment terms recorded.settlement.paid- consumer completed settlement payment in full.dispute.filed- consumer filed a dispute; collection paused per FDCPA.charge_off.pending- account within 15 days of regulatory charge-off boundary.
Audit log
View
Export (CSV)
Returns CSV suitable for NCUA exam submission or internal SOC 2 evidence.