mock-me ⚡
Instantly generate and run local FastAPI mock servers from JSON schemas — no backend code required.
mock-me start config.json
███╗ ███╗ ██████╗ ██████╗██╗ ██╗ ███╗ ███╗███████╗
████╗ ████║██╔═══██╗██╔════╝██║ ██╔╝ ████╗ ████║██╔════╝
██╔████╔██║██║ ██║██║ █████╔╝ ─── ██╔████╔██║█████╗
██║╚██╔╝██║██║ ██║██║ ██╔═██╗ ██║╚██╔╝██║██╔══╝
██║ ╚═╝ ██║╚██████╔╝╚██████╗██║ ██╗ ██║ ╚═╝ ██║███████╗
╚═╝ ╚═╝ ╚═════╝ ╚═════╝╚═╝ ╚═╝ ╚═╝ ╚═╝╚══════╝
Instant FastAPI mock servers from JSON – no backend required
Features
- JSON-first — one config file defines your entire mock API
- Schema-aware fake data — names, emails, UUIDs, dates, nested objects, arrays
- All HTTP methods — GET, POST, PUT, PATCH, DELETE
- Conditional responses — different responses based on path, query, body, or headers
- Error simulation — probability-based or condition-triggered errors
- Configurable delays — simulate real-world latency
- Pagination — automatic pagination envelope wrapping
- Template strings —
"ORD-{{int}}","{{userId}}"reflect request params - Hot-reload — watches config file and reloads on change
- Auto OpenAPI docs — Swagger UI + ReDoc generated automatically
- Seeded randomness — reproducible fake data across runs
- Export — generate a standalone FastAPI
server.pywith no mock-me dependency - Plugin system — register custom data generators in Python
Quickstart
Install
pip install mock-me
# or from source:
git clone https://github.com/mock-me/mock-me
cd mock-me && pip install -e .
Create a config
mock-me init --out config.json
Start the server
mock-me start config.json
mock-me v1.0.0
─────────────────────────────────────────
My API (dev)
─────────────────────────────────────────
GET /api/users [Users]
POST /api/users [Users]
GET /api/users/{id} [Users]
DELETE /api/users/{id} [Users]
Swagger UI → http://localhost:8000/docs
ReDoc → http://localhost:8000/redoc
Health → http://localhost:8000/__health
Listening on http://0.0.0.0:8000
Options
mock-me start config.json --port 9000 # override port
mock-me start config.json --host 127.0.0.1 # override host
mock-me start config.json --reload # watch config for changes
mock-me start config.json --seed 42 # reproducible data
CLI Commands
| Command | Description |
|---|---|
mock-me start config.json |
Start the mock server |
mock-me validate config.json |
Validate config without starting |
mock-me export config.json --out server.py |
Export a standalone FastAPI server |
mock-me init --out config.json |
Create a starter config file |
Config Reference
Top-Level Options
{
"name": "My API",
"description": "Optional description",
"version": "1.0.0",
"host": "0.0.0.0",
"port": 8000,
"environment": "dev",
"seed": 42,
"globalDelay": 0.1,
"globalHeaders": {
"X-Server": "mock-me"
},
"pagination": { ... },
"plugins": ["./my_plugin.py"],
"endpoints": [ ... ]
}
| Field | Type | Description |
|---|---|---|
name |
string | Server/API name (shown in Swagger) |
port |
int | Port to listen on (default: 8000) |
host |
string | Bind host (default: 0.0.0.0) |
seed |
int | Random seed for reproducible data |
globalDelay |
float | Seconds of delay added to every request |
globalHeaders |
object | Headers added to every response |
plugins |
string[] | Paths to custom generator plugins |
Pagination
"pagination": {
"defaultPageSize": 10,
"maxPageSize": 100,
"pageParam": "page",
"sizeParam": "size",
"totalParam": "total",
"dataParam": "items"
}
When an endpoint has "paginated": true, responses are wrapped:
{
"items": [...],
"total": 143,
"page": 1,
"size": 10,
"pages": 15,
"hasNext": true,
"hasPrev": false
}
Endpoint Config
{
"path": "/api/users/{id}",
"method": "GET",
"description": "Get a user by ID",
"tags": ["Users"],
"delay": 0.2,
"pathParams": { ... },
"queryParams": { ... },
"headerParams": { ... },
"bodySchema": { ... },
"response": { ... },
"conditionalResponses": [ ... ],
"errors": [ ... ]
}
Field Schemas (Response Body)
Every field in response.body uses a schema:
"fieldName": {
"type": "string",
"faker": "email"
}
Supported Types
| Type | Description | Example |
|---|---|---|
string |
String with optional faker rule | {"type":"string","faker":"email"} |
int / integer |
Integer with optional min/max | {"type":"int","min":1,"max":100} |
float / number |
Float with optional min/max | {"type":"float","min":0.5,"max":9.99} |
bool / boolean |
Random true/false | {"type":"bool"} |
uuid |
UUID v4 | {"type":"uuid"} |
date / datetime |
ISO datetime string | {"type":"date"} |
enum |
Random value from list | {"type":"enum","values":["a","b","c"]} |
object |
Nested object | {"type":"object","properties":{...}} |
array |
Array of items | {"type":"array","items":{...},"minItems":2,"maxItems":5} |
Faker Rules
Use a shorthand string or a full rule object:
"email": { "type": "string", "faker": "email" }
"name": { "type": "string", "faker": "name" }
"bio": { "type": "string", "faker": { "type": "paragraph" } }
Available faker types:
name, first_name, last_name, email, username, password, phone
address, street, city, state, country, zip
url, domain, ipv4, ipv6, mac
uuid, word, sentence, paragraph, text, slug
company, job, currency, color, hex_color
image_url, iban, ssn, license_plate, user_agent
mime_type, file_name, file_extension, lorem
Static & Template Values
"status": { "type": "string", "value": "active" }
"orderId": { "type": "string", "template": "ORD-{{int}}" }
"userId": { "type": "string", "template": "{{userId}}" }
Template variables resolve in this order:
- Request path params (e.g.
{{userId}}→abc123) - Query/body/header params
- Faker methods (e.g.
{{name}},{{email}}) - Built-ins:
{{int}},{{float}},{{uuid}}
Nullable Fields
"deletedAt": { "type": "date", "nullable": true }
~10% chance of returning null.
Conditional Responses
Return different responses based on request input. Conditions use dotted paths:
| Key prefix | Matches |
|---|---|
path.userId |
Path parameter userId |
query.status |
Query param ?status=... |
body.email |
Request body field email |
header.x-api-key |
Request header |
"conditionalResponses": [
{
"when": { "path.id": "000" },
"response": {
"status": 404,
"body": {
"error": { "type": "string", "value": "Not found" }
}
}
},
{
"when": { "query.role": "admin", "header.x-api-key": "*" },
"response": {
"status": 200,
"body": { "admin": { "type": "bool", "value": true } }
}
}
]
Use "*" to check presence (any non-null value).
Error Simulation
"errors": [
{
"probability": 0.05,
"response": {
"status": 503,
"body": { "error": { "type": "string", "value": "Service unavailable" } }
}
},
{
"trigger": { "body.email": "locked@example.com" },
"response": {
"status": 403,
"body": { "error": { "type": "string", "value": "Account locked" } }
}
}
]
probability— triggers randomly (0.05 = 5% of requests)trigger— triggers when condition matches (same syntax asconditionalResponses.when)
Delays
{
"globalDelay": 0.05,
"endpoints": [
{
"path": "/api/slow",
"delay": 2.0,
"response": {
"delay": 0.5
}
}
]
}
Precedence: response.delay > endpoint.delay > globalDelay
Plugin System
Create a Python file with a GENERATORS dict:
# my_plugin.py
import random
def _product_sku():
return f"SKU-{random.randint(10000, 99999)}"
def _geo_point():
return {
"lat": round(random.uniform(-90, 90), 6),
"lng": round(random.uniform(-180, 180), 6)
}
GENERATORS = {
"product_sku": _product_sku,
"geo_point": _geo_point,
}
Reference in config:
{
"plugins": ["./my_plugin.py"],
"endpoints": [{
"path": "/products",
"response": {
"body": {
"sku": { "type": "product_sku" },
"location": { "type": "geo_point" }
}
}
}]
}
Export Standalone Server
Generate a self-contained FastAPI server with zero mock-me dependency:
mock-me export config.json --out server.py
# Run it anywhere:
pip install fastapi uvicorn faker
python server.py
Built-in Endpoints
| Path | Description |
|---|---|
/__health |
Health check + server metadata |
/__config |
View the parsed config |
/docs |
Swagger UI |
/redoc |
ReDoc documentation |
/openapi.json |
OpenAPI schema |
Example: Minimal Config
{
"name": "Blog API",
"port": 8000,
"endpoints": [
{
"path": "/posts",
"method": "GET",
"tags": ["Posts"],
"response": {
"status": 200,
"paginated": true,
"body": {
"id": { "type": "uuid" },
"title": { "type": "string", "faker": "sentence" },
"content": { "type": "string", "faker": "paragraph" },
"author": { "type": "string", "faker": "name" },
"published": { "type": "bool" },
"createdAt": { "type": "date" }
}
}
}
]
}
See sample_config.json for a full e-commerce API with 14 endpoints, nested objects, conditionals, errors, and pagination.
Project Structure
mock-me/
├── mock_me/
│ ├── __init__.py # Package metadata
│ ├── models.py # Pydantic config schema (ServerConfig, EndpointConfig, etc.)
│ ├── engine.py # Data engine – fake data generation
│ ├── server.py # FastAPI app builder – dynamic route registration
│ ├── loader.py # JSON config loader + hot-reload watcher
│ ├── exporter.py # Standalone server.py code generator
│ └── cli.py # CLI entry point (start, validate, export, init)
├── sample_config.json # Full e-commerce demo (14 endpoints)
├── minimal_config.json # Beginner example
├── example_plugin.py # Custom generator plugin example
└── pyproject.toml
License
MIT
Metadata
Release files for mock-me 1.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| mock_me-1.0.0.tar.gz | 20.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| mock_me-1.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 40.5 kB
Release files / mock_me-1.0.0.tar.gz
| Download URL | mock_me-1.0.0.tar.gz |
|---|---|
| Size | 20.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
eb852f4c4b037af5151a48541507f00a2ac8d36c17d90dd6bd08b11fbaf47611
|
|
BLAKE2b-256 checksum How to use checksums |
2e3fb9f8592d9be576137b4a9d013406923c1d60be516106c54df132a035c31d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.4
|
Release files / mock_me-1.0.0-py3-none-any.whl
| Download URL | mock_me-1.0.0-py3-none-any.whl |
|---|---|
| Size | 20.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
d113cdf7a7239f528ef4b520152c78e3173c5341b7a9a51afb261c805ccce751
|
|
BLAKE2b-256 checksum How to use checksums |
4b37ba8920f5e2660da3f518678137757ac5899f80d6d2c02a40e6b927fa8ca8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.4
|