Royalty & licensing payouts that reconcile the first time.
Catalog changes, late returns, and fractional splits shouldn’t create drift. We release only the proven set—bound to fresh approvals— so statements replay bit-for-bit.

Who this is for
Music, publishing, gaming, media
Millions of plays/sales/events mapped to rights splits across catalogs and territories.
Where pain shows up
Fractional splits & rounding drift, late returns/chargebacks, catalog migrations, heavy audit packs.
Outcome we target
Replayable, penny-exact statements; only ALLOW releases; reason-coded HOLDs when proofs are stale.
What you get (in plain English)
No rounding drift
Late quantization + deterministic carry; fractional splits stay consistent on re-run.
Safer catalog changes
Promote only when digests match; roll back by window if they don’t.
Cleaner audits
Statements and payments tie to a window_id and output_digest for instant proof.
Before → After (at a glance)
Traditional stack (before)
- Data: usage/plays/orders in Snowflake/BigQuery + ETL
- Logic: SQL/Python with FP math; per-item rounding
- Payout: PSP/EBP exports and GL posting
Re-runs “move cents”; late returns mutate prior statements; audits rely on spreadsheets.
Overlay architecture (after)
- Deterministic engine: single-writer partitions; 128-bit integers.
- Late quantization + carry-ledger: one-time rounding in fixed order.
- Acceptance gate: Finance ACK + Compliance/Tax; optional SPV.
- Authorize(window_id): returns ALLOW/HOLD with reason codes; only ALLOW releases.
How it works (60 seconds)
1) Ingest & compute
Normalize usage/sales/returns; accumulate integers; apply splits deterministically.
2) Window close
Close by watermark; fold in canonical order; quantize once; assign carry; seal transcript & digest.
3) Authorize & disburse
Equality + fresh approvals → ALLOW set exports; HOLDs wait with reasons.
Keep your rails—no rip-and-replace.
Fits your stack
Keep what works
Tipalti/Payoneer/EBP for payouts; NetSuite/Oracle for GL. We sit as a pre-release gate.
Add three fields
window_id— identifies the payout windowoutput_digest— ties to the sealed transcriptprovider_batch_id— PSP/EBP batch reference
One pre-release call
Right before you export:
POST /authorize { window_id }
→ ALLOW roster + HOLD roster with reason codesWhere these fields go
- PSP/rails metadata:
window_id,output_digest,provider_batch_id - GL custom fields:
custbody_payout_window_id,custbody_output_digest,custbody_provider_batch_id
Technical details (for software engineers)
View endpoints, contracts & mappings
API surface
// Checks replay digest equality + acceptance matrix (freshness & quorum) → Returns: ALLOW roster + HOLD roster with reason codes
// Push CT/ACK/SPV payloads; we verify signatures & freshness and update decisions
// Sealed transcript + output_digest for replay & audit
Data contracts (minimal)
event_id,ts_occurred,asset_id,rights_holder_id,currency,amount_minor,source_type(play|sale|return)
asset_id,rights_holder_id,split_bps,effective_from,effective_to
// Finance ACK (window-level)
{ "window_id":"2025-09-05/M", "reserves_ok":true, "signer":"fin-ops@...", "expires_at":"2025-09-06T00:00:00Z" }
// Compliance/Tax CT (holder-level)
{ "rights_holder_id":"AUTH-991", "status":"cleared", "expires_at":"2025-09-10T00:00:00Z" }Results teams aim for
Replay equality ≥ 99.99%
Digest(replay) == digest(transcript) across windows.
Disputes ↓ 30–60%
Proof-backed statements lower support load.
Bounded change risk
Canary → equality → promote; roll back by window if needed.
Targets are goals set during a pilot; not guarantees.
Pilot in 30 days
What we’ll ask in discovery
- How often do late returns or catalog changes hit prior windows?
- What rails/GL fields do you use today?
- Where do PSP totals vs GL differ, and by how much?
Next step
Pilot one cohort for two windows; measure equality, reasons, and time-to-release.
