Drop JSON files into a folder and your API immediately exists.
apimock-rs is an HTTP(S) mock server built in Rust: point it at a folder of JSON files and it serves them as a REST API, zero configuration required. An optional TOML rule set adds conditional matching, Rhai scripting, and response strategies when you need more.
- ❄️ Zero-config start.
- 🌬️ Fast to boot, light on memory.
- 🪄 File-based and rule-based matching. Scripting supported.
- The backend is not ready yet.
- You need stable API responses for UI testing.
- You want offline development.
- CI tests require a predictable API.
- Your mock data is becoming large.
# via npm, into your app project
npm install -D apimock-rs && npx apimock# or via cargo, as a standalone binary
cargo install apimock && apimock# or download a prebuilt binary — no Node or Rust toolchain needed
# https://github.com/apimokka/apimock-rs/releases/latest
tar xzf 'apimock@Linux-x64-gnu-<version>.tar.gz'
cd 'apimock@Linux-x64-gnu-<version>' && ./apimockPrebuilt binaries are published for Linux (x64 gnu, x64 musl, aarch64
musl), macOS (aarch64) and Windows (x64). Linux archives are .tar.gz,
macOS and Windows are .zip. Each one also ships an apimock.toml,
apimock-rule-set.toml and apimock-middleware.rhai, picked up
automatically when you run from that directory — so a downloaded build
answers curl http://localhost:3001/health straight away, with no setup
step at all.
# just use folders and JSON
mkdir -p api/v1/
echo '{"hello": "world"}' > api/v1/hello.json
npx apimock # (or `apimock` / `./apimock`, depending on how you installed it)
# response
curl http://localhost:3001/api/v1/hello
# --> {"hello":"world"}You now have a running REST endpoint (the commands below assume npx;
drop it for cargo install, or use ./apimock for a downloaded
binary).
| command | result |
|---|---|
npx apimock |
Run with all default parameters. |
npx apimock -p 4000 |
Run with custom port. |
npx apimock -d tests/apimock-dyn-route |
Run with custom root dir on server response. |
npx apimock -c ./apimock.toml |
Run with config file giving rich features. Running npx apimock --init beforehand is required. Note the ./ — a bare relative path such as -c apimock.toml does not resolve. |
| command | result |
|---|---|
npx apimock --init |
Interactive setup. Prompts for port / IP / fallback dir / whether to scaffold a rule-set file, middleware file, and TLS section, then writes apimock.toml (and optionally apimock-rule-set.toml / apimock-middleware.rhai) customised to your answers. |
npx apimock --init --yes |
Non-interactive setup: skip every prompt and write the default config (127.0.0.1:3001, rule-set file included, TLS commented out). Useful in CI or Docker builds. |
npx apimock --init --middleware |
Also scaffold apimock-middleware.rhai. Combines with --yes. |
When stdin is not a TTY (piped, CI, Docker build), --init silently
falls back to the same defaults even without --yes — so
non-interactive usage in scripts and CI keeps working unchanged.
Run Vite and apimock-rs together with concurrently (parallel processes) and cross-env (colored output across platforms):
npm install -D concurrently cross-env "scripts": {
"apimock": "npx apimock",
"dev": "cross-env CLICOLOR_FORCE=1 concurrently \"vite\" \"npm run apimock\""
}npm run devRead-on-demand, not preloaded. No response is read at startup — each is read from disk only when a matching request arrives, off the async runtime's request-handling threads via a dedicated blocking-I/O thread pool. Startup time and memory use stay flat regardless of dataset size, and behaviour stays stable under repeated requests.
Middleware, then rules, then the file tree. Every configured middleware script gets first refusal; unhandled requests then go through the rule sets in order; anything still unmatched falls back to serving a file directly by URL path. Zero-config mode is just that fallback path with nothing else configured.
Body matching uses a dotted-path mini-syntax, not JSONPath.
"customer.tier" or "items.0.sku" — keys joined by ., numeric
segments index arrays. It resembles JSONPath but isn't one; a
"$.foo.bar"-style path will not match anything.
apimock validate and apimock match-test check a config, or
dry-run a rule match, without starting a server — useful in CI. See
the docs.
For more details — including the complete configuration reference — 🧭 check out our full documentation.
This project is lovingly built and maintained by volunteers.
We hope it helps streamline your API development.
Please understand that the project has its own direction — while we welcome feedback, it might not fit every edge case 🌱
Depends on tokio / hyper / hyper-util / http-body-util / rustls / tokio-rustls / rhai / toml / json5 / csv / regex / globset / ignore / uuid / console / indexmap / log / serde / serde_json / thiserror / anyhow / tempfile. In addition, mdbook (as to workflows).
