Your systems keep the money. Ours keeps the arithmetic.
The platform is a computation and a record. It receives what happened in your systems, works out what is owed, and sends back instructions. It never sits in the money path.
A published spec, and two clients written against it.
An OpenAPI document in the repository, a TypeScript client and a Dart client. Your engineer can read the surface before anyone books a call.
OpenAPI
api/openapi.yaml
TypeScript client
sdk/typescript
Dart client
sdk/dart
Events you can trust to arrive.
Eleven event types, enqueued in the same transaction as the state change that produced them.
- 01
A transactional outbox, not a fire-and-forget POST
An event is written in the transaction that caused it and dispatched afterwards from a leased queue. There is no window in which your system was told about something the ledger then rolled back, and no window in which the ledger committed and nobody was told.internal/outbox
- 02
Signed, with a rotatable key id
Every delivery carries an HMAC-SHA256 signature with a key id and a timestamp. Rotation overlaps: the old key stays valid while you cut over, so rotating a secret is not an outage you have to schedule.internal/outbox/sign.go
- 03
Settlement events go first
The claim instruction is not queued behind a backlog of notifications. Delivery classes are separate lanes, and settlement is the one that carries a money instruction.internal/events
- 04
Deterministic ids, so a re-drive is a no-op
Re-driving a handler re-enqueues the same event id, which the outbox dedupes. At-least-once delivery you can actually retry, rather than at-least-once delivery you have to be careful with.internal/events · internal/outbox
- 05
An egress guard on your URL
The destination is operator-configured, which makes it an SSRF vector by construction. The dispatcher checks the URL before the request and blocks the addresses you would expect it to block.internal/outbox/ssrf.go
- 06
Backoff, parking and a reconciler
Failures back off and eventually park rather than hammering a destination that is down. A cross-system reconciler catches a genuinely lost event rather than trusting the queue to be perfect.internal/outbox · internal/reconciler
Commands that run exactly once, keyed on your record ids.
You tell the platform a purchase happened, a refund happened, a member was verified. Retrying is free, because the key is yours.
Every inbound command is idempotent per workspace and reference, and the response is cached. Send the same purchase twice and the second call returns the first call's answer — it does not create a second purchase, and it does not pay a second round of commissions on the first.
The error contract is explicit, because “retry or not” is the question a client integration actually has to answer. A returned error releases the receipt and you may retry. A rejection with a 4xx code is terminal and cached: the command was refused on its merits and retrying it will refuse it again.
internal/commands · internal/command
Settle however you already settle.
The platform reserves the exact ledger lines and instructs. What executes the payment is yours.
If you have a settlement host, it receives the claim instruction as a settlement-class event and calls back to settle or fail. If you have not, the payouts console lists what is owed, you pay from your own wallet, and you record the executed price and your own transaction reference. A payment recorded with no reference is refused — it could never be reconciled against your wallet, so accepting it would only mean the reconciliation failed later and further away.
internal/claims · internal/httpapi/payouts.go
Your own domain, proved before it is provisioned.
Claim the hostname, publish the TXT record the platform generates, and provisioning happens once it resolves.
The order matters and it is the whole point. Binding a hostname — or adding a domain to the identity provider's authorised list — before proof of control would let whoever actually owns that name receive sign-ins meant for you. So nothing is provisioned, and nothing is added to the sign-in allow-list, until the record resolves. A background provisioner picks it up within the minute.
internal/domains
Take a sandbox and point it at a staging system.
Free on every plan, with the same API surface, the same events and the same signatures as production.