Test against real APIs without the real accounts.
Run your test suite against mock APIs that behave like the real ones — stateful, offline, zero bills. No accounts, no rate limits, no network. A local stunt double for 91+ public APIs.
$ go install stuntapi.com/stunt/cmd/stunt@latest$ brew install --cask stuntapi/tap/stunt$ irm https://raw.githubusercontent.com/stuntapi/winget/main/install.ps1 | iexor download the binary for any platform
You just want to write a feature. The API has other plans.
Create a developer account. Verify your domain. Wait for sandbox approval. Add a credit card. Hit the rate limit at 2am. Discover the test mode doesn't fire webhooks. Your test now depends on a service you can't control, can't reset, and that bills you.
- ✗ account-gated sandboxes
- ✗ rate limits & quotas
- ✗ flaky CI hitting prod
- ✗ no clean state reset
- ✗ surprise bills
One manifest. One command. Local, stateful, real-shaped.
Describe your services
services:
stripe:
adapter: embedded:stripe-stylePoint a service at a bundled adapter — or write inline rules.Run it
$ stunt up stripe -> http://127.0.0.1:8000State persists across requests. Webhooks fire to a local sink.
Point your code at it
STRIPE_API_BASE_URL=\ http://127.0.0.1:8000Run your suite. It behaves against the real-shaped response — offline.
Mock servers that do more than return 200.
Mocks that remember
Create a charge, list it, capture it, watch the webhook fire. State persists across requests, so your tests can assert real sequences — not just one-off stubs.
Safe to install anyone's mock
Adapter logic runs sandboxed in a Starlark VM — no filesystem, no network, no load(). A stranger's mock can't touch your machine.
Every API shape you call
Mock REST, gRPC (unary + streaming), WebSocket, and GraphQL from one tool — each adapter mirrors the real API's shape, not a toy.
Fake data, by construction
stunt adapter lint rejects real-looking secrets — tokens, card numbers, PII — before they ship. Your mock can't leak what it was never given.
Real TLS, locally
Optional subdomain mode serves https://api.localhost with a local CA + reverse proxy. Test TLS-dependent code with no self-signed warnings.
Scriptable & agent-friendly
--json on catalog/plan/doctor, plus an AGENTS.md + stunt llm reference, so your editor and CI agents drive mock servers unaided.
The stand-in, not the stub.
| stunt | hand-rolled mocks | cloud sandboxes | |
|---|---|---|---|
| no remote account | ✓ | ✓ | ✗ |
| stateful + resettable | ✓ | sometimes | ✓ |
| offline / air-gapped CI | ✓ | ✓ | ✗ |
| sandboxed 3rd-party mocks | ✓ (Starlark) | ✗ | — |
| cost | $0 | time | $ + risk |
91+ adapters, ready to run.
Before you ask.
Does it match my API's real responses?
Each adapter is built from the provider's real schema and routes — shapes, fields, and status codes line up. It's a high-fidelity stand-in, not the live service, so model the edge cases you care about rather than trusting it blindly.
Is the mock data safe to commit?
Yes. Adapter lint rejects real-looking secrets — tokens, card numbers, PII — at build time, and everything in the catalog is synthetic by construction.
Can I trust a third-party adapter?
Adapters run sandboxed in a Starlark VM — no filesystem, no network, no load(). A stranger's mock can't reach your machine.
What if my API isn't in the 91+?
Write inline rules right in the manifest, or scaffold a new adapter with stunt adapter new. Adapters are just YAML + Starlark.
Does it run in CI / air-gapped?
Yes — a single static binary, pure-Go (no CGO), zero outbound network by default.
Run your suite against a stunt double.
No account. No network. No bill.
go install stuntapi.com/stunt/cmd/stunt@latestget started →