Stripe clone

Stateful Stripe simulation — customers, payments, subscriptions, webhooks, and a virtual billing clock.

Stripe clone

Run checkout, subscriptions, invoices, and webhook-driven billing against a stateful Stripe twin — real error shapes, HMAC webhook signing, idempotency keys, and a virtual billing clock. No live card network; use test PANs only.

Clone ID: stripe · Binary: clones-stripe · SDK: stripe · Dashboard: Stripe explorer

Start here

QuestionAnswer
Best forPayment intents, subscriptions, invoices, checkout sessions, disputes, and webhook assertions
Connect with@molar/clones SDK, STRIPE_API_BASE pointed at the clone, REST at {clone.url}/t/{runId}/v1/..., route mode for api.stripe.com, or MCP
Known limitsCompact vertical slice — unimplemented paths return 501; webhooks in-process only; org concurrent sandbox quota on hosted cloud
SeedsStart empty, use control-plane empty / smoke / demo, or call seedData() with JSON (see below)

Quick start

import { stripe } from "@molar/clones";

const clone = await stripe.start({ seed: "checkout-v1", runId: "run-stripe-01" });

await clone.seedData({
  customers: [{ id: "cus_jane", email: "jane@example.com" }],
  payment_methods: [{ pan: "4242424242424242", customer: "cus_jane" }],
});

const pi = await clone.createPaymentIntent({
  amount: 2000, currency: "usd", customer: "cus_jane", payment_method: "pm_...", confirm: true,
});

await clone.advanceClock("30d");
await clone.expectWebhookFired("invoice.paid");
await clone.stop();

MCP tools

Use MCP for clock control, webhook assertions, and control-plane spawn. Use REST or the SDK for full Stripe resource CRUD.

ToolDescription
molar_clone_spawnSpawn a Stripe session (kind: "stripe", optional seed)
molar_clone_seedApply seed JSON to an existing run
molar_clone_advance_clockAdvance virtual time on any clone admin endpoint
stripe_advance_clockAdvance the Stripe billing clock (adminUrl, duration e.g. 30d)
stripe_expect_webhookPoll admin logs until an event type appears (eventType, timeout)
molar_clone_snapshot / molar_clone_restoreSave or restore gzip snapshot bytes (base64)
molar_clone_inject_errorInject HTTP errors on a path for chaos testing

Shared clone tools (molar_clone_list, molar_clone_route, world_snapshot, world_restore) work across vendors — see MCP server.

REST API coverage

The clone handles Stripe-compatible REST at {base}/t/{runId}/v1/... with Authorization: Bearer sk_test_stripe_{runId}.

ResourceOperations
/v1/customersCreate, list, get, update, delete
/v1/payment_methodsCreate, list, get, attach, detach
/v1/payment_intentsCreate, list, get, confirm, capture, cancel (incl. deterministic 3DS on 4000002500003155)
/v1/chargesList, get
/v1/refundsCreate, list, get
/v1/subscriptionsCreate, list, get, update, cancel
/v1/invoicesCreate, list, get, finalize, pay, void
/v1/checkout/sessionsCreate, get (hosted checkout stub)
/v1/webhook_endpointsCreate, list, delete
/v1/disputesList, get, close; force via POST /_clone/stripe/dispute

Idempotency keys on POST are cached for 24h (replay and mismatch behave like Stripe).

If your app uses the official Stripe SDK, point STRIPE_API_BASE at the clone URL (see API & SDK).

Seeds and initial state

Molar does not ship named Stripe fixture files like billing-v1. You have three ways to set starting state:

ApproachWhen to use
Empty tenantDefault — no customers or products
Control-plane seedsHosted spawn with empty, smoke, or demo (generic placeholder resources for smoke tests)
seedData() JSONFull control — customers and payment methods before your test runs
await clone.seedData({
  customers: [{ email: "alice@example.com", name: "Alice" }],
  payment_methods: [{ pan: "4242424242424242", customer: "cus_..." }],
});

The seed string on start() still matters: it drives deterministic IDs and webhook secrets via HKDF. Dashboard presets (for example Checkout Stripe + Receipt) use seed names like checkout-world as labels — pair them with seedData() or scenario setup steps.

Reset a tenant: POST /_clone/reset/{runId} on the admin URL, or spawn a fresh runId.

Test cards

PANBehavior
4242424242424242Succeeds
4000000000000002card_declined
4000002500003155requires_action (deterministic 3DS redirect)

Limits

LimitDetail
Concurrent clonesOrg quota enforced by Molar API (429 when exceeded)
Webhook deliveryIn-process only — no outbound internet; use expectWebhookFired or admin poll
Clock advanceSubscription renewals and invoice finalization fire on current_period_end
Chaos presetscard_declined, rate_limit, idempotency_conflict, webhook_delay (dashboard + injectError)

Authentication

Authorization: Bearer sk_test_stripe_<runId>
{clone.url}/t/{runId}/v1/...

Use clone.testKey and clone.publishableKey from the SDK.

Environment variables

MOLAR_CLONE_STRIPE_URL, MOLAR_CLONE_STRIPE_ADMIN_URL, STRIPE_SECRET_KEY, STRIPE_API_BASE

See Troubleshooting for 501 gaps and connection errors.