API reference
Base URL: https://tranching-production.up.railway.app
No authentication on read endpoints. All amounts are strings of base units, and
every response carries the assetDecimals you need to convert them. Errors are
{ "error": "..." } with the matching HTTP status.
This API indexes the chain. It never decides anything: if it disagrees with a contract, the contract is right and the index has a bug.
Registry
GET /api/deals
Every deal with its classes. phase is read live from the contract on each call.
curl -s $BASE/api/deals
| Field | Type | Meaning |
|---|---|---|
id | number | Registry id, used in other paths |
name | string | Deal name |
dealContractId | string | The abs-deal contract |
payingAgentContractId | string | The paying-agent contract |
periodDays | number | Length of a period |
phase | string | FUNDING, AMORTIZING, ENFORCED, MATURED |
tranches[] | array | The classes, senior first |
GET /api/tranches
Every class across every deal, each with a stats block (see below).
GET /api/tranches/:id
One class. 404 if the id is unknown.
The stats block:
| Field | Meaning |
|---|---|
phase | Lifecycle phase of the deal |
originalFace | Face value at issuance, base units |
outstanding | Face value still outstanding, base units |
noteFactorPct | outstanding / originalFace as a percentage |
coupon.allInPct | Current all-in rate, percent |
coupon.pricing | How that rate is built, in words |
accrued.days | Days accrued in the current period |
accrued.interest | Interest accrued so far this period, base units |
cumulative.interestPaid | Interest paid since closing, base units |
cumulative.principalPaid | Principal repaid since closing, base units |
lastDistribution | { ts, period } of the last waterfall run |
nextPayment | { dueAt, estimatedInterest } |
stats is null during FUNDING: nothing is outstanding before closing.
POST /api/deals
Register a deal. Body:
{
"name": "CARA7 Demo Series 3",
"description": "optional",
"dealContractId": "C...",
"payingAgentContractId": "C...",
"periodDays": 3
}
201 with the created deal, 409 if the name exists, 400 on a bad contract
id (must match ^C[A-Z2-7]{55}$).
POST /api/deals/:id/tranches
Register a class under a deal. Body:
{
"name": "Class A Notes",
"seniority": "SENIOR",
"contractId": "C...",
"originalFace": "1000000000000",
"couponBps": 281
}
seniority is SENIOR, MEZZANINE or JUNIOR. originalFace is a string of
base units. 409 if that contract is already registered.
Notes
Paths take the note token contract id, not the registry id.
GET /notes/:contractId/stats
The same stats block as above, at the top level.
GET /notes/:contractId/history
Time series for the charts: outstanding and note factor per snapshot.
GET /notes/:contractId/holders
Every holder of the class, with what they have been paid.
| Field | Meaning |
|---|---|
address | Stellar account |
units | Notes held, whole numbers |
sharePct | Share of the class |
interestReceived | Interest received to date, base units |
principalReceived | Principal received to date, base units |
GET /notes/:contractId/events
Decoded contract events, newest first: issues, transfers, interest and principal payments.
Positions
GET /users/:address/positions
Every position of one Stellar account across all classes: units held, outstanding claim, cost basis if they subscribed at issuance, and cash received split between interest and principal.
GET /users/:address/notes/:contractId/history
Time series of one account's position in one class: remaining claim and cumulative cash received.
Distributions
GET /api/deals/:id/distributions
Every waterfall run, newest first, one object per period.
{
"period": 3,
"ts": "2026-08-03T19:15:33.000Z",
"ledger": 3952923,
"collections": "99000000000",
"reserveReleased": "50000000000",
"carryIn": "1800",
"ada": "149000001800",
"fees": "500000000",
"reserveRefunded": "50000000000",
"carryOut": "1700",
"residual": "0",
"perClass": [
{ "class": 0, "tranche": "C...", "interest": "188126000", "principal": "98197291000", "shortfall": "0" }
],
"payments": { "C...": "98385417000" }
}
ada is the available distribution amount: collections plus the whole reserve
released plus the carry. perClass is in seniority order, class 0 being senior.
payments maps each note token to the total handed to the paying agent for it.
Other
GET /health
{ "ok": true }.
GET /api/stats
Totals across the registry: deals, classes, holders, cumulative amounts paid.
GET /prices/:symbol
Latest recorded price for an asset symbol, used for display only. It plays no part in the waterfall.