Programmatic API
Use emulators as libraries in your tests and scripts. There are two approaches: the api-emulator CLI package (which wraps all services) and the individual @api-emulator/* scoped packages.
CLI package
The api-emulator package provides a createEmulator helper that starts any service by name.
npm install api-emulator
import { createEmulator } from "api-emulator";
const github = await createEmulator({ service: "github", port: 4001 });
const vercel = await createEmulator({ service: "vercel", port: 4002 });
github.url; // 'http://localhost:4001'
vercel.url; // 'http://localhost:4002'
await github.close();
await vercel.close();
Vitest / Jest setup
// vitest.setup.ts
import { createEmulator, type Emulator } from "api-emulator";
let github: Emulator;
let vercel: Emulator;
beforeAll(async () => {
[github, vercel] = await Promise.all([
createEmulator({ service: "github", port: 4001 }),
createEmulator({ service: "vercel", port: 4002 }),
]);
process.env.GITHUB_EMULATOR_URL = github.url;
process.env.VERCEL_EMULATOR_URL = vercel.url;
});
afterEach(() => {
github.reset();
vercel.reset();
});
afterAll(() => Promise.all([github.close(), vercel.close()]));
createEmulator options
| Option | Default | Description |
|---|---|---|
service | (required) | Service name: |
port | 4000 | Port for the HTTP server |
seed | none | Inline seed data (same shape as YAML config) |
grpcPort | HTTP port + 10000 | Native gRPC port for a gRPC-capable plugin |
baseUrl | none | Override the advertised base URL (used in OAuth redirects, webhook URLs, etc.). Per-service |
latencyMs | 0 | Delay each HTTP response by this many milliseconds. |
Instance methods
| Method | Description |
|---|---|
url | Base URL of the running server |
grpcUrl | Native gRPC address when the plugin declares gRPC services |
snapshot() | Capture a detached store snapshot |
restore(fixture) | Restore a store snapshot or exported fixture |
exportFixture(options?) | Export a fixture envelope with store state and recorded interactions |
resetToFixture(fixture) | Reset state to a captured fixture |
reset() | Reset runtime state and replay seed data |
close() | Shut down the HTTP server, returns a Promise |
Fixtures
Use fixtures to stabilize a stochastic or stateful run:
const fixture = github.exportFixture({ metadata: { name: "pull-request-flow" } });
github.resetToFixture(fixture);
reset() clears store data, issued tokens, rate-limit counters, webhook deliveries, and subscriptions added during the run, then reapplies registration defaults and seed data. Pending webhook deliveries are cancelled; requests already received by an external webhook target cannot be undone. Wait for application requests to finish before resetting.
Snapshots are detached copies of store data. resetToFixture(fixture) resets runtime state and then restores the fixture's store data; restore(fixture) replaces only store data. Fixtures do not capture issued tokens or webhook subscriptions from the run.
Store snapshots support nested plain objects, arrays, Maps, Sets, Dates, undefined, and JSON primitives with finite numbers. Cycles, functions, and other unsupported values throw instead of being silently dropped. Keep provider state in the store so reset and fixtures can manage it.
Scoped packages
Each emulator is published as its own @api-emulator/* package. Install only the ones you need:
npm install @api-emulator/github @api-emulator/google @api-emulator/stripe
Available packages
| Package | Service |
|---|---|
@api-emulator/vercel | Vercel API |
@api-emulator/github | GitHub API |
@api-emulator/google | Google OAuth, Gmail, Calendar, Drive |
@api-emulator/slack | Slack Web API, OAuth v2, webhooks |
@api-emulator/apple | Apple Sign In / OIDC |
@api-emulator/microsoft | Microsoft Entra ID, Graph API |
@api-emulator/aws | AWS S3, SQS, IAM, STS |
@api-emulator/okta | Okta identity provider / OIDC |
@api-emulator/mongoatlas | MongoDB Atlas Admin API + Data API |
@api-emulator/resend | Resend email API |
@api-emulator/stripe | Stripe billing and payments API |
@api-emulator/core | Shared store, middleware, and utilities |
@api-emulator/adapter-next | Next.js App Router integration |
Direct usage
Each scoped package exports its Hono app and seed function, so you can compose emulators however you like:
import * as github from "@api-emulator/github";
import * as stripe from "@api-emulator/stripe";
These are the same modules used internally by the CLI and the Next.js adapter. See the Next.js Integration page for a full example of using scoped packages with createApiEmulatorHandler.