Skip to main content
The Stripe fake answers the part of the Stripe API that Fonoster’s billing uses, so billing code and its tests run with no Stripe account and no network. It lives in mods/stripe-fake. Its answers follow Stripe’s own OpenAPI schema at a pinned version (API 2026-09-30.endive, stripe npm 23), and its tests check every response against that schema. It covers customers and payment methods, products and prices, billing meters and meter events, credit grants, subscriptions and invoices under test clocks, payment intents and refunds, Customer Portal sessions, events, and signed webhooks.
The fake is for development and tests only. It keeps everything in memory and accepts any sk_test_ key.

Run it

With Docker Compose, the fake is a service on the fakes profile:
It listens on port 12111 (set RB_STRIPE_FAKE_PORT to change the host port). From source:

Watch it

Open http://localhost:12111 for the viewer: what Stripe would see, updated live as your code or tests call the fake.
  • Customers: the credit balance (1 credit = $0.01), plan and top-up credits, meter totals and recent webhooks.
  • Meters: each meter and its recent events, accepted or rejected.
  • Credit grants, Invoices (with line items) and Webhooks (each delivery’s attempts, payload and a Replay button).
The top bar moves the test clock a month ahead and switches between light and dark. The sidebar can make the next payment fail or reset everything. To work on the viewer itself, run a fake on 12111 and then:
It serves on 12112 and sends API calls to the fake (STRIPE_FAKE_URL to change it).

Point the Stripe SDK at it

Requests need a sk_test_ or rk_test_ key. A Stripe-Version header, when sent, must be the pinned version. Unknown parameters and paths are refused with Stripe’s error shape, and Idempotency-Key replays work as in Stripe. Stripe’s test payment methods work: pm_card_visa, pm_card_mastercard, pm_card_chargeDeclined, pm_card_chargeDeclinedInsufficientFunds and pm_card_authenticationRequired.

Move time

Create a test clock and attach customers to it, as in Stripe. Advancing the clock runs the billing cycle: renewals, invoices finalized after the grace period (one hour by default), credit grants applied to metered lines, payment, and retries after 3, 5 and 7 days.

Webhooks

Create endpoints with stripe.webhookEndpoints.create, or at start with STRIPE_FAKE_WEBHOOKS: a URL and its signing secret joined by |, with commas between endpoints.
Deliveries are signed like Stripe’s, so stripe.webhooks.constructEvent verifies them. A delivery that doesn’t get a 2xx is retried with backoff. Meter event errors arrive as thin v2.core.event events; read the full event at GET /v2/core/events/{id}.

Control API

Tests set the fake’s state through /_fake, which is not part of Stripe’s API. Bodies are JSON. /_fake/ws is a WebSocket that sends a message on every change, for watching the fake live.

Run its tests

The tests drive the fake through the official Stripe SDK. To refresh the schema after moving to a new Stripe API version, change OPENAPI_RELEASE in scripts/extract-openapi.ts and run npm run extract:openapi -w mods/stripe-fake.