Pay marketplace partners without overpays or drift.
Stop overpays on late cancels. End rounding drift on surge/tips. Release only the proven set—tied to fresh Finance/Compliance approvals.

Who this is for
Rides / last-mile delivery platforms
Hundreds of thousands to millions of drivers/couriers daily or weekly; surge, bonuses, tips; multi-currency.
Where pain shows up
Rounding drift on surge/tips, re-runs that change cents, refunds after payout → clawbacks, PSP/GL mismatches.
Compliance & audit pressure
Need provable equality and approvals tied to the exact outputs—no ad-hoc evidence packs.
What you get (in plain English)
No rounding drift
Deterministic carry with late quantization—surge/tips stop “moving” on re-run.
Fewer clawbacks
Late cancels/refunds do not mutate prior windows; they land in the next window with reasons.
Cleaner recon
PSP/GL rows tie to window_id + output_digest; auditors verify by replay.
Before → After (at a glance)
Traditional stack & flow (before)
- Data/compute: Kafka/Kinesis → Spark/Databricks or Snowflake/BigQuery with Airflow/dbt.
- Logic: SQL/Python aggregates; per-ride rounding; surge/tips modeled ad hoc.
- Payout rails: Stripe Connect / Adyen for Platforms; ACH/SEPA files.
- Back office: NetSuite/Oracle; close/recs via BlackLine/Trintech.
Batches release when the “job finished” — not when replay equals the sealed transcript with fresh approvals.
Overlay architecture (after)
- Deterministic engine: single-writer partitions, fixed fold order, 128-bit integers.
- Late quantization + carry-ledger: one-time rounding; documented ≤½-unit bound per allocation.
- Transcript + digest: content-addressed, replayable evidence of equality.
- Acceptance gate: Finance ACK + CT (+ optional SPV) with freshness & quorum → only ALLOW releases.
How it works (60 seconds)
1) Ingest & compute
Order into single-writer logs; accumulate integers (no FP drift); surge/tips at native precision.
2) Window close
Close under a monotone watermark; fold in a fixed, published order; quantize once; assign carry deterministically.
3) Authorize & disburse
Replay equals transcript digest + approvals fresh/in quorum → ALLOW set releases; HOLDs are reason-coded.
Keep your rails—no rip-and-replace.
Hourly cadence (example)
- T+0–55m: Ingest & compute deterministically
- T+55m: Window close (watermark, fold, quantize, carry)
- T+56m: Authorize(window_id) — equality + acceptance
- T+57m: Disburse ALLOW; HOLDs reason-coded
- Next window: Late cancels/refunds land here
Acceptance policy (example)
Required proofs
- ACK (Finance reserves) — window-level
- CT (KYC/OFAC/Tax) — principal/cohort-level
- SPV (optional) — provider receipt/headers
Freshness & quorum
- Freshness: ACK ≤ 60m; CT ≤ 24h; SPV ≤ 60m
- Quorum: 2 of 3 (Finance, Compliance, Ops)
If unmet
- HOLD with reason:
STALE_PROOF,INSUFFICIENT_QUORUM,RIGHTS_MISMATCH - Owners alerted; re-check without mutating outputs
Fits your stack
Keep what works
Stripe Connect / Adyen for Platforms for payouts; ACH/SEPA rails; NetSuite/Oracle for GL. We run as a pre-release gate.
Add three fields
window_id— identifies the payout windowoutput_digest— ties to the sealed transcript (replay equality)provider_batch_id— PSP/EBP batch reference
One pre-release call
Right before you create the PSP batch:
POST /authorize { window_id }
→ ALLOW roster + HOLD roster with reason codesPath A — Pay via PSP (fastest)
- Create PSP batch from the ALLOW set
- Record Vendor Bills (one per driver per window) in ERP
- Tag rows with
window_idandoutput_digest
Path B — Pay from ERP (EBP)
- Use ALLOW set to build EBP payment file
- Include
window_idin memo; capture EBP batch asprovider_batch_id - Gate release via
Authorize(window_id)before export
Data intake options: S3/GCS/SFTP, read-only DB view, Kafka/Webhook — adapters provided.
Where these fields go
- PSP/rails batch metadata:
window_id,output_digest,provider_batch_id - GL (NetSuite/Oracle) custom fields:
custbody_payout_window_id,custbody_output_digest,custbody_provider_batch_id
Technical details (for software engineers)
View endpoints, data contracts & mappings
API surface
Gate release and fetch evidence:
// 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
// Content-addressed transcript + output_digest for replay & audit
Data contracts (minimal)
event_id,ts_occurred,principal_id(currency),amount_minor,source_type
// source_type ∈ { fare | surge | tip | refund | adjustment }// Finance ACK (window-level)
{ "window_id":"2025-09-05/17:00", "reserves_ok":true, "signer":"fin-ops@...", "expires_at":"2025-09-05T18:00:00Z" }
// CT (driver/cohort-level)
{ "principal_id":"DRV-18472", "status":"cleared", "expires_at":"2025-09-06T00:00:00Z" }
// SPV (optional, window-level)
{ "window_id":"2025-09-05/17:00", "provider_batch_id":"ADY-88919", "totals_minor": "123456789", "headers_hash":"0x..." }// Add to PSP batch metadata & GL: window_id, output_digest, provider_batch_id
Results teams aim for
Replay equality ≥ 99.99%
Windows where digest(replay) == digest(transcript).
Time-to-release (p95)
Minutes from watermark close to authorized payout (not hours).
Disputes ↓ 30–60%
Transcript-based proofs reduce escalations and chargebacks.
Change MTTR (bounded)
Rollback & recovery bounded to a window via canary → equality → promote.
No rounding drift
Deterministic carry with ≤½-ULP bound; surge/tips stay consistent.
Targets are set together during a pilot; they are goals, not guarantees.
Risks & mitigations
See risks & how we handle them
- Late/missing proofs → auto-HOLD; re-check without mutating outputs.
- Policy/migration defects → digest mismatch; canary + rollback before release.
- Hot partitions → versioned shard function; promote only on digest equality.
FAQ
What about late cancels and refunds?
They never mutate prior windows. We record them as new events in the next window with reason codes. Audit stays clean; no clawback chaos.
Do we change payout rails?
No. You keep Stripe/Adyen/ACH/SEPA and your ERP. We add a pre-release gate before funds move.
Will surge/tips still round strangely?
No. We quantize once per window and assign sub-cents in a fixed, documented order (carry-ledger). Replays match bit-for-bit.
Pilot in 30 days
What we’ll ask in discovery
- What must be true before you release a payout file today? Who signs off?
- How often do you see clawbacks from refunds after payout?
- Where do PSP totals vs GL differ today, and by how much?
Next step
Gate one cohort for two windows; measure equality, reasons, and time-to-release.
