How to pay creators at scale with Stripe Connect · CollabPal
All posts
Engineering9 min read

How to pay creators without becoming a payments company

Paying a hundred creators in a dozen countries sounds like a finance project. With Stripe Connect it is mostly a configuration problem. Here is the shape of it.

By Leo · @leojr94_

The moment a creator program works, it develops a payments problem. Twenty creators in eight countries, each expecting money in their own currency, and none of them wanting to hear that your finance team runs payouts on the last Friday of the month.

You do not need to build a payments company to solve this, but you do need to understand roughly four things about Stripe Connect. This is what they are and where the sharp edges sit.

Creators get an Express account, not an invoice

Each creator onboards once to a Stripe Express account. Stripe collects their identity details, tax information and bank account directly. That data never touches your servers, which is the entire point: know-your-customer obligations and bank details stay with the party equipped to handle them.

Onboarding is not instant and it is not always successful. Stripe returns a list of outstanding requirements, and a creator can sit in a half-finished state for days. Your interface has to show that honestly rather than pretending everyone is ready to be paid.

Destination charges keep the money in one hop

The pattern worth using is a destination charge. You create a payment intent against the workspace's saved card or bank account, and set the creator's connected account as the transfer destination. One charge, one transfer, one Stripe object to reconcile.

The alternative, holding a balance and paying out from it, turns you into a money transmitter in several jurisdictions. Unless that is your business, avoid it.

Idempotency is not optional

The failure that costs real money is the double charge. A request times out, the operator clicks again, and the same creator gets paid twice. Every payment intent needs an idempotency key derived from something stable, such as the payout batch and the creator.

There is a subtlety. If a payment genuinely fails, say a declined card, the operator needs to be able to retry after fixing the problem. A key that never changes blocks that legitimate retry. The key has to be stable within an attempt and fresh across deliberate ones.

Webhooks are the source of truth

A card payment that succeeds synchronously is the easy case. Bank debits are not: they can take days and can fail after appearing to succeed. Treat your database as a mirror of Stripe rather than an authority.

  • payment_intent.succeeded marks the earning paid and notifies the creator
  • payment_intent.processing covers the in-flight bank debit window
  • payment_intent.payment_failed records the reason so it can be retried
  • charge.refunded and charge.dispute.created flag money that came back

Those last two matter more than they first appear. A refunded payout is not simply unpaid; it is paid and then reversed, which is a different state with different consequences for your ledger and for the creator's expectations.

Return an error, not a lie

Paying twenty creators means twenty payment intents, and some will fail while others succeed. The tempting design is a single success or failure for the batch. The honest design reports per creator: paid, skipped because they have not finished onboarding, failed with a reason.

Skipping a creator who has not completed Stripe onboarding is correct behaviour, but only if you say so clearly. Silence there produces a support conversation a week later about money that was never sent.

Where the human belongs

Almost everything in a creator program can be automated safely. Sending money is the exception worth keeping a person in front of, not because software cannot do it but because the cost of a wrong decision is asymmetric. Approving work and releasing funds are two separate actions in our product for exactly that reason.

#stripe#payouts#engineering#creator payments