A local Stripe emulator for development and testing
Documentation • Getting Started • Resources • SDK Usage • Dashboard • Demo • Docker • API Reference
Strimulator is a drop-in local replacement for the Stripe API. It runs as a single process, stores everything in SQLite, and is compatible with the official stripe Node SDK. Use it to develop and test payment flows entirely offline — no Stripe account or network access required.
Think of it as LocalStack, but for Stripe.
- Offline development — No internet, no Stripe test mode, no rate limits
- Fast feedback — Instant responses, no network latency
- Full control — Trigger payment failures, advance subscriptions, simulate edge cases from the dashboard
- SDK-compatible — Point the official
stripepackage at localhost and it just works - Docker-ready — Drop it into your docker-compose alongside Postgres, Redis, Firebase emulator, etc.
- 3,500+ tests — Strict fidelity to Stripe's API shapes, state machines, and error formats
- Bun v1.0+
git clone https://github.com/codeforge-tech/strimulator.git
cd strimulator
bun install
bun run devStrimulator is now running:
- API: http://localhost:12111/v1/
- Dashboard: http://localhost:12111/dashboard
# Create a customer
curl -X POST http://localhost:12111/v1/customers \
-H "Authorization: Bearer sk_test_123" \
-d "email=hello@example.com"
# Create a product and price
curl -X POST http://localhost:12111/v1/products \
-H "Authorization: Bearer sk_test_123" \
-d "name=Pro Plan"
# List customers
curl http://localhost:12111/v1/customers \
-H "Authorization: Bearer sk_test_123"Point the official Stripe SDK at Strimulator — no code changes needed beyond the configuration:
import Stripe from "stripe";
const stripe = new Stripe("sk_test_strimulator", {
host: "localhost",
port: 12111,
protocol: "http",
});
// Use exactly like real Stripe
const customer = await stripe.customers.create({ email: "dev@example.com" });
const product = await stripe.products.create({ name: "Pro Plan" });
const price = await stripe.prices.create({
product: product.id,
unit_amount: 2000,
currency: "usd",
recurring: { interval: "month" },
});
const subscription = await stripe.subscriptions.create({
customer: customer.id,
items: [{ price: price.id }],
});
console.log(subscription.status); // "active"If your app reads STRIPE_SECRET_KEY, you can switch to Strimulator without touching code:
STRIPE_SECRET_KEY=sk_test_strimulator \
STRIPE_API_BASE=http://localhost:12111 \
npm run dev| Resource | Endpoints | State Machine |
|---|---|---|
| Customers | CRUD + list + search | |
| Products | CRUD + list + search | |
| Prices | create, retrieve, update, list | |
| Payment Methods | create, retrieve, attach, detach, list | |
| Payment Intents | create, retrieve, confirm, capture, cancel, list, search | requires_payment_method → requires_confirmation → succeeded |
| Setup Intents | create, retrieve, confirm, cancel, list | requires_payment_method → requires_confirmation → succeeded |
| Charges | retrieve, list | |
| Refunds | create, retrieve, list | |
| Subscriptions | create, retrieve, cancel, list, search | active / trialing / canceled / past_due |
| Invoices | create, retrieve, finalize, pay, void, list, search | draft → open → paid / void |
| Events | retrieve, list | |
| Webhook Endpoints | CRUD + list | |
| Test Clocks | create, retrieve, advance, delete, list |
- Webhook delivery — Registers endpoints via the API, delivers events with
Stripe-SignatureHMAC-SHA256 headers (compatible withstripe.webhooks.constructEvent()), retries on failure - Search API —
/v1/customers/search,/v1/payment_intents/search, etc. with Stripe's query language (email:"foo@bar.com",status:"active",metadata["key"]:"value") - expand[] — One-level and nested expansion (
expand[]=customer,expand[]=latest_invoice.payment_intent) - Idempotency-Key — POST requests with the same key return cached responses
- 3D Secure simulation —
tok_threeDSecureRequiredtriggersrequires_actionon confirm, re-confirm completes the challenge;tok_threeDSecureOptionalalso supported - Magic test tokens —
tok_visa,tok_mastercard,tok_amex,tok_visa_debit,tok_chargeDeclined,tok_threeDSecureRequired,tok_threeDSecureOptional— all produce deterministic card details
Open http://localhost:12111/dashboard for a real-time debug interface:
Live stream of all API requests — method, path, status code, timing.
Browse all stored objects by type. Click any object to view its full JSON representation.
Trigger simulated scenarios without writing code:
| Action | Description |
|---|---|
| Fail Next Payment | Force the next PaymentIntent confirmation to fail (card_declined, insufficient_funds, expired_card) |
| Advance Test Clock | Move a test clock forward in time, triggering subscription transitions |
| Retry Webhook | Re-deliver an event to a webhook endpoint |
| Expire Payment Intent | Force a PaymentIntent into canceled state |
| Cycle Subscription | Advance a subscription to the next billing period |
An Astro SSR demo shop is included in demo/ to showcase the full payment flow — product listing, checkout with card selection, 3D Secure challenge, and success page. It uses the official Stripe Node SDK pointed at Strimulator.
# Start both Strimulator and the demo app with one command
bun run demo- Demo shop: http://localhost:4321
- Strimulator dashboard: http://localhost:12111/dashboard
Published to GitHub Container Registry on every version tag.
docker pull ghcr.io/codeforge-tech/strimulator:latestAdd to your project's docker-compose.yml:
services:
strimulator:
image: ghcr.io/codeforge-tech/strimulator:0.1.0
ports:
- "12111:12111"
volumes:
- strimulator-data:/data
your-app:
build: .
environment:
STRIPE_SECRET_KEY: sk_test_strimulator
STRIPE_API_BASE: http://strimulator:12111
depends_on:
- strimulator
volumes:
strimulator-data:docker build -t strimulator .
docker run -p 12111:12111 strimulator| Environment Variable | Default | Description |
|---|---|---|
STRIMULATOR_PORT |
12111 |
Server port |
STRIMULATOR_DB_PATH |
:memory: |
SQLite file path. Use :memory: for ephemeral storage or a file path for persistence across restarts |
STRIMULATOR_LOG_LEVEL |
info |
Log verbosity |
STRIMULATOR_API_VERSION |
2024-12-18 |
Stripe API version returned in responses |
All endpoints live under /v1/ and follow Stripe's exact URL structure:
POST /v1/customers
GET /v1/customers/:id
POST /v1/customers/:id
DELETE /v1/customers/:id
GET /v1/customers
GET /v1/customers/search?query=email:"foo@bar.com"
All /v1/ requests require a bearer token starting with sk_test_:
Authorization: Bearer sk_test_anything
The actual key value doesn't matter — Strimulator accepts any sk_test_* key.
Like real Stripe, requests use application/x-www-form-urlencoded (not JSON):
curl -X POST http://localhost:12111/v1/customers \
-H "Authorization: Bearer sk_test_123" \
-d "email=test@example.com" \
-d "metadata[plan]=pro"Errors match Stripe's exact shape:
{
"error": {
"type": "invalid_request_error",
"message": "No such customer: 'cus_nonexistent'",
"param": "id",
"code": "resource_missing"
}
}# Install dependencies
bun install
# Run in development mode (auto-reload)
bun run dev
# Run tests
bun test
# Run specific test file
bun test tests/sdk/payment-flow.test.tssrc/
routes/ # ElysiaJS route plugins (one per Stripe resource)
services/ # Business logic and state machines
db/schema/ # Drizzle ORM table definitions
middleware/ # Auth, idempotency, form parsing, request logging
dashboard/ # Debug dashboard (API + Preact SPA)
lib/ # Shared utilities (IDs, pagination, expand, search)
errors/ # Stripe-compatible error factory
tests/
unit/ # Service-layer tests
integration/ # HTTP request/response tests
sdk/ # Tests using the official stripe npm package
demo/ # Astro SSR demo e-commerce app
scripts/ # Orchestration scripts (demo launcher)
docs/ # Fumadocs documentation site (Next.js)
Full documentation is available in the docs/ directory. To run it locally:
cd docs
bun install
bun run devThen open http://localhost:3000 for the docs site with Getting Started guides, API reference, and architecture documentation.
- Runtime: Bun
- Framework: ElysiaJS
- Database: SQLite via Drizzle ORM + bun:sqlite
- Types: Imported from the
stripenpm package - Dashboard: Preact + HTM (loaded from CDN)
- Testing: bun:test (3,500+ tests)
- Documentation: Fumadocs + OpenAPI
MIT