Audience: PMs, Finance, Admins
Outcomes: Predictable deposit/payout behavior; clean documents of record
Flow of money
Deposit arrives (card/bank/crypto) → verified webhook →
Order.DepositPaid
Work InProgress; deliverables accepted per milestone
Release triggers payout from escrow (provider-specific or on-chain)
Invoice emitted/updated; SSE notifies both sides
Events: payment.succeeded
, order.status.changed
, milestone.released
, invoice.created/updated
Release API (per milestone)
curl -X POST $API_BASE/api/escrow/release -b cookies.txt \ -H 'Content-Type: application/json' \ -d '{"orderId":"ord_123","milestoneId":"m2","amount":100000}'
Multiple partial releases allowed; never exceed remaining balance
Duplicate requests deduped via release reference (if exposed) or handler logic
Invoices, receipts & tax lines
Download
curl -s $API_BASE/api/invoices/ord_123.pdf -b cookies.txt --output invoice-ord123.pdf
Contents: contract & order numbers, org & counterparty details, line items (deposit/releases), tax/withholding (if configured), refund/credit notes (negative lines), provider references (PI ID, bank ref, tx hash).
Branding: Admin → Settings → Branding.
Edge cases
Release fails: check balance/gas/provider outage; retry idempotently
Refunds generate credit notes tied to original invoice lines
QA checklist
Invoice numbers immutable post-issuance
FX rate/timestamp stored if conversion used (see Article 7)
Runbook: “Release succeeded but invoice missing”
Rebuild invoice from ledger; re-emit
invoice.created/updated
event