The public plugin shelf for api-emulator.
Use this repo like an app store of local API emulators. Pick a provider, load it into api-emulator, then test your app against a fake API on localhost instead of hitting production, sandboxes, or someone else's server.
Clone the shelf next to your app:
git clone https://github.com/jsj/api-emulator-plugins.gitRun one plugin:
npx -p api-emulator api \
--plugin ./api-emulator-plugins/@posthog/api-emulator.mjs \
--service posthogLoad more than one plugin with a comma-separated list:
npx -p api-emulator api \
--plugin ./api-emulator-plugins/@github/api-emulator.mjs,./api-emulator-plugins/@apple/api-emulator.mjs \
--service github,appleGenerate seed config for a plugin:
npx -p api-emulator api init \
--plugin ./api-emulator-plugins/@alpaca/trading-emulator/src/index.ts \
--service alpacaYour app
↓
api-emulator on localhost
↓
GitHub, PostHog, Cloudflare, OpenAI, and other plugin backed fake APIs
api-emulator stays the runtime spine. This repo keeps provider behavior in separate plugins so public, private, and internal emulators can evolve independently.
OpenAI and Anthropic record chat/message request and response pairs into the runtime fixture store. Export a fixture after a useful run, then restore it later to replay the same response for the same request.
const fixture = openai.exportFixture({ metadata: { name: "happy-path-chat" } })
openai.resetToFixture(fixture)| Plugin | Path | Scope |
|---|---|---|
| Alpaca | @alpaca/trading-emulator/src/index.ts |
Trading account, orders, positions, clock, market data snapshots and bars |
| Anthropic | @anthropic/api-emulator.mjs |
Messages API |
| Apple | @apple/api-emulator.mjs |
AMS auth, APNS, App Store Connect apps, builds, uploads, review submissions |
| Cloudflare | @cloudflare/api-emulator/src/index.ts |
Workers-style bindings, D1, KV, R2, queues, durable objects, service bindings |
| fal | @fal/api-emulator.mjs |
Seedance queue text-to-video flow |
| Gemini | @gemini/api-emulator.mjs |
generateContent |
| GitHub | @github/api-emulator.mjs |
Apps, repos, refs, contents, issues, PRs, Actions, checks |
| Kubernetes | @kubernetes/api-emulator/index.mjs |
Namespaces, nodes, pods, logs, events, deployments, K8sGPT results |
| OpenAI | @openai/api-emulator.mjs |
Images, edits, chat completions |
| OpenRouter | @openrouter/api-emulator.mjs |
Chat completions |
| PostHog | @posthog/api-emulator.mjs |
Capture, batch, persons, groups, identify, alias, feature flags, decide, experiments |
| Replicate | @replicate/api-emulator.mjs |
Model predictions |
The main api-emulator repo has runnable examples for common integration flows:
Use this repo when those examples need providers outside the default catalog, or when you want to share a provider plugin independently from the runtime.
A plugin exports a plugin object that satisfies the ServicePlugin interface from @api-emulator/core.
export const plugin = {
name: "posthog",
register(app, store, webhooks, baseUrl) {
app.post("/capture", async (c) => {
const body = await c.req.json();
return c.json({ ok: true, received: body });
});
},
};
export const label = "PostHog API emulator";
export const endpoints = "capture, batch, decide, feature flags";
export const initConfig = {
posthog: {
apiKeys: ["posthog-emulator-key"],
},
};Optional exports:
label: display name fornpx -p api-emulator api listendpoints: short endpoint summary forlistinitConfig: starter config emitted bynpx -p api-emulator api initseedFromConfig(store, baseUrl, config, webhooks): load config into emulator statedefaultFallback(config): default auth fallback for token-protected providers
Simple plugins can be a single file:
@posthog/
api-emulator.mjs
smoke.mjs
Larger plugins can be small packages:
@cloudflare/
api-emulator/
package.json
src/index.ts
smoke.ts
Some plugins include a smoke script. Run all repository-level smoke tests with:
bun run smokeYou can also run an individual smoke test directly:
node ./@posthog/smoke.mjsMIT. See LICENSE.