Instantly generate and run local FastAPI mock servers from JSON schemas
Project description
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
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mock_me-1.0.0.tar.gz.
File metadata
- Download URL: mock_me-1.0.0.tar.gz
- Upload date:
- Size: 20.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
eb852f4c4b037af5151a48541507f00a2ac8d36c17d90dd6bd08b11fbaf47611
|
|
| MD5 |
355cb9c16abaa1e6559f428ba426bbca
|
|
| BLAKE2b-256 |
2e3fb9f8592d9be576137b4a9d013406923c1d60be516106c54df132a035c31d
|
File details
Details for the file mock_me-1.0.0-py3-none-any.whl.
File metadata
- Download URL: mock_me-1.0.0-py3-none-any.whl
- Upload date:
- Size: 20.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d113cdf7a7239f528ef4b520152c78e3173c5341b7a9a51afb261c805ccce751
|
|
| MD5 |
148fa274f82289d85a00eec6ddd46544
|
|
| BLAKE2b-256 |
4b37ba8920f5e2660da3f518678137757ac5899f80d6d2c02a40e6b927fa8ca8
|