capability_unavailable until marketplace_live is enabled here. Nothing on this page promises when.The family is in the contract and not switched on here yet — endpoints answer not_enabled until it is.
What it is
Direct financing between verified members. A borrower lists a verified receivable with its own ask; a lender — another verified member — offers at the ask or counters; the borrower accepts one. From there the financing runs as documents on the two parties' own connection, and repayment is linked to the settlement of the pledged invoice. Rivet is the interface and attestor: it records the terms the parties state, does the arithmetic (fee amount, owed = principal + fee), witnesses every step in the verified history, and signs an attestation of the agreement. It sets no terms, recommends nothing, holds no funds, and is never the counterparty to the financing.
The three-document model
Accepting an offer creates, all or nothing, on the lender↔borrower connection:
- Agreement (FIN-) — the structured terms and both acceptances. The lender reads it as "Financing provided", the borrower as "Financing received". Attested (signed) once it exists.
- Disbursement (DSB-) — a payable issued by the borrower to the lender for the principal. The lender pays it on the ordinary payment seam (
POST /v1/documents/{id}/pay, a pay release, a checkout); its settlement is principal delivered, and the agreement moves tofunded. - Repayment (RPY-) — a payable issued by the lender to the borrower for principal + fee, active once funded, due on the pledged invoice's due date plus the grace days. The one document where a settlement may be partial: each one lands in its payments and the balance recomputes; it is paid only at zero.
All three ride GET /v1/documents like any other document — with verified history, lineage (the agreement is spawned from the invoice it finances; the payables from the agreement), attachments and webhooks.
The lifecycle
- List.
POST /v1/finance/listingswithask_termsin loan terms:principal,fee_mode(flatorbps),fee_value,grace_days. The listing is pseudonymous; the rail is fixed from the invoice's expected settlement. - Offer.
POST /v1/finance/listings/{id}/offers— at the ask (at_ask: true) or a counter onprincipaland/orfee. One pending offer per lender per listing. Grace days are the borrower's. - Accept. Read the offer (
GET /v1/finance/offers/{id}) — the borrower's read carries the standing authorization, verbatim, with its digest — thenPOST /v1/finance/offers/{id}/acceptechoingauthorization_digest. Every other pending offer closes; the listing closes. - Fund. The lender pays the disbursement.
funded; the repayment activates with its due date. - Settle and sweep. When the pledged invoice settles through Rivet, the sweep runs (below). A partial sweep leaves the agreement
repaying. - Close. The repayment reaches zero →
closed. Before funding, either party may withdraw (POST /v1/finance/agreements/{id}/withdraw) — both payables void. - Flagged / delinquent. A disputed or cancelled pledged invoice flags the agreement — no automatic action, both parties told. A balance past the due date and grace is marked
delinquent: informational. Rivet collects nothing.
The sweep — what Rivet initiates, and nothing else
min(settled proceeds, remaining owed), same rail. Rivet initiates nothing else — not a penny beyond those proceeds, not on any other account, not on any timer. Everything else (invoice paid off-Rivet, shortfall, early repayment) is the borrower paying the Repayment doc like any bill.Each sweep is idempotent per settlement, attributed "via Finance sweep (agreement FIN-…)" in the repayment's verified history, and carries the authorization's digest on the payment order. A settlement on a different rail sweeps nothing and notifies; an invoice recorded as paid outside Rivet sweeps nothing and tasks the borrower. GET /v1/finance/agreements/{id}/repayment lists every sweep and why one did not run.
No custody, no FBO, no pooling, no netting
Every leg is one org's account to another's on the same regulated rails and custodians (bank via the fiat rail; Coinbase for USDC). Rivet never holds, nets, or routes through itself; the platform fee is metered through billing, never deducted from any leg. The accounts are named by each organization under GET/PUT /v1/finance/setup: a settlement account to borrow (where the pledged invoice lands; the sweep draws from it), a funding account to lend (what principal is paid from; the sweep lands in it).
Prerequisites, at the gates
- To list or accept (borrower): verified · settling on Rivet rails · a settlement account named on the rail · the payer a verified member (the Grade-B floor).
- To offer or be accepted (lender): verified · on Rivet rails · a funding account named on the rail.
- Both sides are re-checked at acceptance; a refusal names every failed check. The rail must equal the pledged invoice's expected settlement rail; one lender per agreement, one agreement per invoice, whole obligation.
USDC is a second rail on the same code path, behind the deployment's switch; fiat is proven end to end. Rivet converts nothing, ever.
Webhook events
finance.offer.received (the borrower; the lender pseudonymous) · finance.agreement.accepted · funded · repaid (with data.settlement: amount and what remains) · closed · flagged. Each carries the agreement as your side reads it. The documents themselves also emit document.status_changed and, on the payables, payment.settled / payment.failed.
Try the loop
In your sandbox: read GET /v1/finance/setup (a sandbox pair is born ready on both rails), opt in, list an eligible invoice with your ask, then have the demo lender offer at the ask through the simulator (POST /v1/sandbox/counterparty/advance with listing_id), accept with the authorization digest, advance the disbursement (the lender pays), and advance the pledged invoice (the buyer pays) — the sweep fires and the agreement closes. The scopes are finance:read / finance:write, plus documents:write and payments:write to pay a repayment.