Why this exists

Who made this, why it exists, and what it can and cannot do today. The long answer, because installing something that receives webhooks on your own machine deserves one.

For five years, at every fintech job I've had, part of the work was wiring an application into somebody else's model of money. Payment providers — dLocal, Braintree, checkout.com. Banks directly — Emirates NBD, HSBC. ERPs on the far side of the same ledger — QuickBooks, NetSuite. Different SDKs, different nouns for the same object, different opinions about what a webhook is for, and every time the same short list of things that actually break. The webhook arrives twice. Out of order. Not at all. The provider says captured, your database says pending.

What the sandboxes are for

To be fair to them: provider sandboxes are good at the job they were built for, which is letting you prove your integration works at all. A successful payment is easy to get out of one, and so is a handful of canned failures — a declined card, an expired one. Covering the rest of the failure space, on demand and the same way twice, was never a job they took on.

So that is where the work always went. Sitting down with the team, deciding which corner cases actually mattered, then working out how you'd even reproduce the one that scares you — and every time it ended in some contraption built from scratch just to make the case happen at all. Nothing carried over. Not from the last job, and not from the last provider inside the same job.

Where you start decides what carries over

Every provider builds its testing story out of its own entities — payment intents, charges, sources, sessions. For the problem they're solving that's exactly the right place to begin: you're integrating with them, and their nouns are the thing you have to get right. It just doesn't survive a second provider. Swap one in, or run two at once, and the entities move under you, and everything built on top of them goes in the bin. The hardest day of every integration I've been near was the day two providers had to meet inside a single scenario.

Underneath all of them, though, there's one model, not many. A card was charged. A transfer went through. A refund came back. One concrete event, a small number of concrete states — and each provider ships its own projection of it. What you want to know isn't "does my handler work," it's "this happened, and whoever told me about it, do the same rows end up in my database?" Nobody sells that.

So I started building my own

Finxture starts from the other end. One model of what actually happened. Provider projections sitting on top of it. And on top of those, perturbations — the duplicate, the reordering, the delivery that never lands, the status that disagrees. The perturbation is the part you actually want to test, and it stays the same perturbation no matter who is delivering it. How it's built

My day job is this problem at full size — many providers, many edge cases, all at once, with real money on the other side. Finxture is where I get to try the approach on my own terms first, where being wrong costs me an evening instead of a postmortem.

Stripe is first because it's the lingua franca: if the idea isn't legible on Stripe, it isn't legible anywhere. The list above is what taught me the problem, and it's what comes next.

What it does today

One thing, on purpose. It sends webhooks — the ones you'd otherwise be waiting on a sandbox to produce for you. The same event twice. A pair that arrives out of order, coming soon. It's the fast way to find out whether your handler survives them on its own terms: deduplication, signature verification, idempotency. The scenario list is the current answer to what's covered, and it grows one case at a time.

Everything happens in your browser. Events are generated and signed there, and go to one loopback endpoint you approve at runtime. No cloud, no account, no server of mine anywhere in that path.

What I want it to become

Webhooks on their own only get you halfway. The practice worth having is to treat the webhook as a trigger and read the real status back from the provider's API — so the next step is letting a scenario drive that call too, and the one after it is reconciliation: a run where the provider's view and your rows are supposed to agree, and you find out whether they do. Underneath both, the thing I keep circling back to is making all of it drivable from a test suite rather than a browser tab.

Further out, two halves. The first is a knowledge base — domain expertise written down. You're wiring up your first provider: what do you even need to check? There are refunds. There are chargebacks. There's the webhook that never arrives. Today that baseline lives in the heads of people who've already been burned by it, and the way you get it is by being burned too. The second is a tool sitting on top of it, so you can take any case out of that knowledge base and run it against the provider you actually use.

None of that exists yet, and I'd rather say so here than let the rest of the site imply otherwise.

Who you would be writing to

One person builds this: me, Dmitrii Gritsan on LinkedIn . Fullstack Fintech Manager — an awkward title and the accurate one: a manager who still writes the code. Yandex, inDrive, Tabby, Squads.

If you have a view on what's missing — a provider, a scenario, a failure you have actually hit — add me there and tell me. That is the entire feedback process at the moment, and at this size it works fine.

Add to Chrome Add me on LinkedIn