# API Simulator
<div align="center">
[](https://www.python.org)
[](LICENSE)
[](https://github.com/yourusername/api-simulator)
**Multi-protocol API mocking made simple** • REST • GraphQL • WebSocket • UDP
[Features](#features) • [Quick Start](#quick-start) • [Documentation](#documentation) • [Examples](#examples) • [Contributing](#contributing)
</div>
---
## 🎯 Overview
API Simulator spins up lifelike backends from a single JSON configuration file. Perfect for frontend development, integration testing, and API prototyping without waiting for backend implementation.
### Key Features
- 🚀 **Zero dependencies** - Just Python and a JSON config
- 🔌 **Multi-protocol** - REST, GraphQL, WebSocket, and UDP from one server
- 📝 **Request-aware templating** - Dynamic responses based on headers, query params, and paths
- 🎭 **Realistic behavior** - Rules, delays, errors, and chaos testing
- 📊 **Streaming support** - SSE, NDJSON, and WebSocket broadcasts
- 🔒 **HTTPS/WSS ready** - Built-in TLS support
- 📖 **OpenAPI export** - Auto-generated documentation
## 🚀 Quick Start
### Installation
```bash
pip install -e .
```
### Basic Usage
1. **Create a config file** (`config.json`):
```json
{
"rest": {
"port": 3000,
"path": "/api",
"apis": [
{
"method": "GET",
"path": "/users/{user_id}",
"response": {
"id": "{{ path('user_id') }}",
"name": "Test User",
"created": "{{ timestamp() }}"
}
}
]
}
}
```
2. **Start the simulator**:
```bash
apisim run --config config.json
```
3. **Test your API**:
```bash
curl http://localhost:3000/api/users/123
```
## 📚 Documentation
### Table of Contents
- [CLI Commands](#cli-commands)
- [Configuration](#configuration)
- [Templating](#templating)
- [Protocols](#protocols)
- [REST API](#rest-api)
- [WebSocket](#websocket)
- [GraphQL](#graphql)
- [UDP Streaming](#udp-streaming)
- [Advanced Features](#advanced-features)
## 🛠️ CLI Commands
### Server Management
```bash
# Start server
apisim run --config config.json [options]
--templates templates.json # Template macros
--seed 42 # Deterministic randomness
--log-level INFO # Logging level
--certfile cert.pem # HTTPS/WSS certificate
--keyfile key.pem # HTTPS/WSS key
# Check running servers
apisim status
# Stop servers
apisim stop [--all]
# Validate configuration
apisim validate --config config.json
# Export OpenAPI spec
apisim openapi export --config config.json [--out openapi.json]
```
## ⚙️ Configuration
### REST API
```json
{
"rest": {
"port": 3000,
"path": "/api/v1",
"apis": [
{
"method": "GET",
"path": "/products/{product_id}",
"response": {...}, // JSON response
"text": "plain text", // Text response
"file": "path/to/file", // File response
"binary_b64": "...", // Binary response
"stream": {...}, // NDJSON streaming
"sse": {...}, // Server-Sent Events
"rules": {...} // Conditional behavior
}
]
}
}
```
#### Streaming Responses
**Server-Sent Events (SSE)**:
```json
{
"method": "GET",
"path": "/events",
"sse": {
"interval": 1,
"event": "update",
"template": {"price": "{{ random_float(100,200,2) }}"},
"count": 10 // null for infinite
}
}
```
**NDJSON Streaming**:
```json
{
"method": "GET",
"path": "/stream",
"stream": {
"interval": 0.5,
"template": {"seq": "{{ counter('seq') }}"},
"content_type": "application/x-ndjson"
}
}
```
### WebSocket
```json
{
"websocket": {
"port": 9080,
"path": "/ws",
"apis": [
{
"path": "/events",
"response": {"type": "ack"},
"broadcast": {
"interval": 5,
"response": {"event": "{{ counter('events') }}"}
},
"rules": {
"message.action == 'subscribe'": {
"response": {"subscribed": true}
}
}
}
]
}
}
```
### GraphQL
```json
{
"graphql": {
"port": 3000,
"path": "/graphql",
"queries": [
{
"operationName": "GetUser",
"response": {"user": {"id": "123", "name": "Alice"}}
}
],
"mutations": [
{
"operationName": "CreateUser",
"response": {"success": true, "id": "{{ uuid4() }}"}
}
],
"subscriptions": [
{
"operationName": "UserUpdates",
"interval": 2,
"response": {"user": {"updated": "{{ timestamp() }}"}}
}
]
}
}
```
### UDP Broadcasting
```json
{
"udp": {
"host": "127.0.0.1",
"port": 5001,
"apis": [
{
"name": "telemetry",
"broadcast": {
"interval": 1,
"response": {"temp": "{{ random_float(20,30,1) }}"}
}
}
]
}
}
```
## 🎨 Templating
### Built-in Functions
| Function | Description | Example |
|----------|-------------|---------|
| `{{ timestamp() }}` | ISO 8601 timestamp | `2024-01-15T10:30:00Z` |
| `{{ unix_timestamp() }}` | Unix timestamp | `1705315800` |
| `{{ uuid4() }}` | UUID v4 | `a3bb189e-8bf9-4c90-b8f0-d7d3e7e4d6c1` |
| `{{ random_int(min, max) }}` | Random integer | `{{ random_int(1, 100) }}` |
| `{{ random_float(min, max, decimals) }}` | Random float | `{{ random_float(0, 1, 2) }}` |
| `{{ counter(name, start, step) }}` | Auto-incrementing counter | `{{ counter('order', 1000, 1) }}` |
| `{{ choice([...]) }}` | Random selection | `{{ choice(['A', 'B', 'C']) }}` |
### Request-Aware Templates
Access request data in responses:
```json
{
"response": {
"path_param": "{{ path('user_id') }}",
"query_param": "{{ query('search') }}",
"header": "{{ header('Authorization') }}",
"body_field": "{{ body('email') }}",
"method": "{{ method() }}"
}
}
```
### Custom Macros
Define reusable templates in `templates.json`:
```json
{
"functions": {
"order_id": "counter('order', 1000, 1)",
"product": "choice(['Widget', 'Gadget', 'Tool'])",
"price": "random_float(10.0, 100.0, 2)"
}
}
```
## 🎯 Rules & Conditional Behavior
### Rule Conditions
- **Probability**: `"0.1"` (10% chance)
- **Path equality**: `"path.user_id == '123'"`
- **Query params**: `"query.debug == 'true'"`
- **Headers**: `"header.X-Test == 'yes'"`
- **Body fields**: `"body.amount > 100"`
### Actions
```json
{
"rules": {
"query.test == 'error'": {
"status": 500,
"response": {"error": "Test error"},
"headers": {"X-Error": "true"}
},
"header.X-Slow == 'true'": {
"delay": "2s"
},
"0.05": {
"ignore": true // 5% drop rate
}
}
}
```
## 🧪 Testing
### Running Tests
```bash
# All tests
pytest tests/ -v
# Specific protocols
pytest tests/test_protocols.py::TestRESTProtocol -v
pytest tests/test_e2e_protocols.py -v
# With coverage
pytest tests/ --cov=api_simulator
```
### Test Structure
```
tests/
├── test_cli.py # CLI command tests
├── test_protocols.py # Protocol unit tests
└── test_e2e_protocols.py # End-to-end with lifespan
```
## 📖 Examples
### Complete E-Commerce API
See [`examples/config.json`](examples/config.json) for a full example with:
- Product catalog with search
- Order streaming
- Real-time price updates (SSE)
- WebSocket order events
- GraphQL customer queries
- UDP inventory feeds
### Testing Different Protocols
After starting the server with `apisim run --config examples/config.json`:
**REST API Tests:**
```bash
# Basic GET endpoint
curl http://localhost:3000/api/v1/status
# Path parameters, query strings, and headers
curl "http://localhost:3000/api/v1/products/PROD-123?q=search" \
-H "X-Session-Id: test-session"
# SSE streaming (real-time price updates)
curl -N http://localhost:3000/api/v1/prices/sse
# NDJSON streaming
curl -N http://localhost:3000/api/v1/stream/orders
```
**GraphQL Tests:**
```bash
# Query
curl -X POST http://localhost:3000/graphql \
-H "Content-Type: application/json" \
-d '{"operationName":"GetCustomer"}'
# Mutation
curl -X POST http://localhost:3000/graphql \
-H "Content-Type: application/json" \
-d '{"operationName":"CreateOrder"}'
# List available operations
curl http://localhost:3000/openapi.json | jq '.paths."/graphql"'
```
**WebSocket Tests:**
```bash
# Using wscat (npm install -g wscat)
wscat -c ws://localhost:9080/realtime/events
> {"action":"subscribe"}
# Using Python
python3 -c "
import asyncio, websockets, json
async def test():
async with websockets.connect('ws://localhost:9080/realtime/events') as ws:
await ws.send(json.dumps({'action': 'subscribe'}))
print(await ws.recv())
asyncio.run(test())
"
# GraphQL Subscriptions
python3 -c "
import asyncio, websockets, json
async def test():
async with websockets.connect('ws://localhost:9080/realtime/graphql') as ws:
await ws.send(json.dumps({'type': 'connection_init'}))
print(await ws.recv())
await ws.send(json.dumps({'id': '1', 'type': 'subscribe',
'payload': {'operationName': 'PriceUpdates'}}))
print(await ws.recv())
asyncio.run(test())
"
```
**UDP Listener:**
```bash
python3 -c "
import socket, struct, msgpack
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(('127.0.0.1', 5001))
print('Listening on 127.0.0.1:5001...')
while True:
pkt, _ = s.recvfrom(65536)
magic, ts, n = struct.unpack('>IIH', pkt[:10])
print(f'Magic: 0x{magic:X}, Payload:', msgpack.unpackb(pkt[10:], raw=False))
"
```
## 🔌 API Documentation
When running, access auto-generated API docs at:
- **Swagger UI**: http://localhost:3000/docs
- **ReDoc**: http://localhost:3000/redoc
- **OpenAPI JSON**: http://localhost:3000/openapi.json
## 🐳 Docker
```dockerfile
FROM python:3.11-slim
WORKDIR /app
COPY . .
RUN pip install -e .
CMD ["apisim", "run", "--config", "/config/config.json"]
```
```bash
docker build -t api-simulator .
docker run -p 3000:3000 -p 9080:9080 \
-v $(pwd)/examples:/config \
api-simulator
```
## 🤝 Contributing
We welcome contributions! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
### Development Setup
```bash
# Clone repository
git clone https://github.com/yourusername/api-simulator
cd api-simulator
# Create virtual environment
python -m venv venv
source venv/bin/activate # or `venv\Scripts\activate` on Windows
# Install with dev dependencies
pip install -e ".[test]"
# Run tests
pytest tests/ -v
# Check code style
ruff check src/
```
## 📝 License
MIT License - see [LICENSE](LICENSE) file for details.
## 🙏 Acknowledgments
Built with:
- [FastAPI](https://fastapi.tiangolo.com/) - REST/GraphQL server
- [websockets](https://websockets.readthedocs.io/) - WebSocket support
- [msgpack](https://msgpack.org/) - Binary serialization
- [Pydantic](https://pydantic-docs.helpmanual.io/) - Data validation
## 📮 Support
- 📧 Email: support@example.com
- 💬 Discord: [Join our server](https://discord.gg/example)
- 🐛 Issues: [GitHub Issues](https://github.com/yourusername/api-simulator/issues)
---
<div align="center">
Made with ❤️ by the API Simulator Team
</div>
Raw data
{
"_id": null,
"home_page": null,
"name": "api-simulator",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.9",
"maintainer_email": null,
"keywords": "api, mock, simulator, rest, graphql, websocket, udp, testing, development",
"author": null,
"author_email": "API Simulator Team <support@example.com>",
"download_url": "https://files.pythonhosted.org/packages/c1/bd/abbce2400e5d2e0f68d977075ac41c559c709b4994028a2994619147c2bb/api_simulator-0.3.0.tar.gz",
"platform": null,
"description": "# API Simulator\n\n<div align=\"center\">\n\n[](https://www.python.org)\n[](LICENSE)\n[](https://github.com/yourusername/api-simulator)\n\n**Multi-protocol API mocking made simple** \u2022 REST \u2022 GraphQL \u2022 WebSocket \u2022 UDP\n\n[Features](#features) \u2022 [Quick Start](#quick-start) \u2022 [Documentation](#documentation) \u2022 [Examples](#examples) \u2022 [Contributing](#contributing)\n\n</div>\n\n---\n\n## \ud83c\udfaf Overview\n\nAPI Simulator spins up lifelike backends from a single JSON configuration file. Perfect for frontend development, integration testing, and API prototyping without waiting for backend implementation.\n\n### Key Features\n\n- \ud83d\ude80 **Zero dependencies** - Just Python and a JSON config\n- \ud83d\udd0c **Multi-protocol** - REST, GraphQL, WebSocket, and UDP from one server\n- \ud83d\udcdd **Request-aware templating** - Dynamic responses based on headers, query params, and paths\n- \ud83c\udfad **Realistic behavior** - Rules, delays, errors, and chaos testing\n- \ud83d\udcca **Streaming support** - SSE, NDJSON, and WebSocket broadcasts\n- \ud83d\udd12 **HTTPS/WSS ready** - Built-in TLS support\n- \ud83d\udcd6 **OpenAPI export** - Auto-generated documentation\n\n## \ud83d\ude80 Quick Start\n\n### Installation\n\n```bash\npip install -e .\n```\n\n### Basic Usage\n\n1. **Create a config file** (`config.json`):\n\n```json\n{\n \"rest\": {\n \"port\": 3000,\n \"path\": \"/api\",\n \"apis\": [\n {\n \"method\": \"GET\",\n \"path\": \"/users/{user_id}\",\n \"response\": {\n \"id\": \"{{ path('user_id') }}\",\n \"name\": \"Test User\",\n \"created\": \"{{ timestamp() }}\"\n }\n }\n ]\n }\n}\n```\n\n2. **Start the simulator**:\n\n```bash\napisim run --config config.json\n```\n\n3. **Test your API**:\n\n```bash\ncurl http://localhost:3000/api/users/123\n```\n\n## \ud83d\udcda Documentation\n\n### Table of Contents\n\n- [CLI Commands](#cli-commands)\n- [Configuration](#configuration)\n- [Templating](#templating)\n- [Protocols](#protocols)\n - [REST API](#rest-api)\n - [WebSocket](#websocket)\n - [GraphQL](#graphql)\n - [UDP Streaming](#udp-streaming)\n- [Advanced Features](#advanced-features)\n\n## \ud83d\udee0\ufe0f CLI Commands\n\n### Server Management\n\n```bash\n# Start server\napisim run --config config.json [options]\n --templates templates.json # Template macros\n --seed 42 # Deterministic randomness\n --log-level INFO # Logging level\n --certfile cert.pem # HTTPS/WSS certificate\n --keyfile key.pem # HTTPS/WSS key\n\n# Check running servers\napisim status\n\n# Stop servers\napisim stop [--all]\n\n# Validate configuration\napisim validate --config config.json\n\n# Export OpenAPI spec\napisim openapi export --config config.json [--out openapi.json]\n```\n\n## \u2699\ufe0f Configuration\n\n### REST API\n\n```json\n{\n \"rest\": {\n \"port\": 3000,\n \"path\": \"/api/v1\",\n \"apis\": [\n {\n \"method\": \"GET\",\n \"path\": \"/products/{product_id}\",\n \"response\": {...}, // JSON response\n \"text\": \"plain text\", // Text response\n \"file\": \"path/to/file\", // File response\n \"binary_b64\": \"...\", // Binary response\n \"stream\": {...}, // NDJSON streaming\n \"sse\": {...}, // Server-Sent Events\n \"rules\": {...} // Conditional behavior\n }\n ]\n }\n}\n```\n\n#### Streaming Responses\n\n**Server-Sent Events (SSE)**:\n```json\n{\n \"method\": \"GET\",\n \"path\": \"/events\",\n \"sse\": {\n \"interval\": 1,\n \"event\": \"update\",\n \"template\": {\"price\": \"{{ random_float(100,200,2) }}\"},\n \"count\": 10 // null for infinite\n }\n}\n```\n\n**NDJSON Streaming**:\n```json\n{\n \"method\": \"GET\",\n \"path\": \"/stream\",\n \"stream\": {\n \"interval\": 0.5,\n \"template\": {\"seq\": \"{{ counter('seq') }}\"},\n \"content_type\": \"application/x-ndjson\"\n }\n}\n```\n\n### WebSocket\n\n```json\n{\n \"websocket\": {\n \"port\": 9080,\n \"path\": \"/ws\",\n \"apis\": [\n {\n \"path\": \"/events\",\n \"response\": {\"type\": \"ack\"},\n \"broadcast\": {\n \"interval\": 5,\n \"response\": {\"event\": \"{{ counter('events') }}\"}\n },\n \"rules\": {\n \"message.action == 'subscribe'\": {\n \"response\": {\"subscribed\": true}\n }\n }\n }\n ]\n }\n}\n```\n\n### GraphQL\n\n```json\n{\n \"graphql\": {\n \"port\": 3000,\n \"path\": \"/graphql\",\n \"queries\": [\n {\n \"operationName\": \"GetUser\",\n \"response\": {\"user\": {\"id\": \"123\", \"name\": \"Alice\"}}\n }\n ],\n \"mutations\": [\n {\n \"operationName\": \"CreateUser\",\n \"response\": {\"success\": true, \"id\": \"{{ uuid4() }}\"}\n }\n ],\n \"subscriptions\": [\n {\n \"operationName\": \"UserUpdates\",\n \"interval\": 2,\n \"response\": {\"user\": {\"updated\": \"{{ timestamp() }}\"}}\n }\n ]\n }\n}\n```\n\n### UDP Broadcasting\n\n```json\n{\n \"udp\": {\n \"host\": \"127.0.0.1\",\n \"port\": 5001,\n \"apis\": [\n {\n \"name\": \"telemetry\",\n \"broadcast\": {\n \"interval\": 1,\n \"response\": {\"temp\": \"{{ random_float(20,30,1) }}\"}\n }\n }\n ]\n }\n}\n```\n\n## \ud83c\udfa8 Templating\n\n### Built-in Functions\n\n| Function | Description | Example |\n|----------|-------------|---------|\n| `{{ timestamp() }}` | ISO 8601 timestamp | `2024-01-15T10:30:00Z` |\n| `{{ unix_timestamp() }}` | Unix timestamp | `1705315800` |\n| `{{ uuid4() }}` | UUID v4 | `a3bb189e-8bf9-4c90-b8f0-d7d3e7e4d6c1` |\n| `{{ random_int(min, max) }}` | Random integer | `{{ random_int(1, 100) }}` |\n| `{{ random_float(min, max, decimals) }}` | Random float | `{{ random_float(0, 1, 2) }}` |\n| `{{ counter(name, start, step) }}` | Auto-incrementing counter | `{{ counter('order', 1000, 1) }}` |\n| `{{ choice([...]) }}` | Random selection | `{{ choice(['A', 'B', 'C']) }}` |\n\n### Request-Aware Templates\n\nAccess request data in responses:\n\n```json\n{\n \"response\": {\n \"path_param\": \"{{ path('user_id') }}\",\n \"query_param\": \"{{ query('search') }}\",\n \"header\": \"{{ header('Authorization') }}\",\n \"body_field\": \"{{ body('email') }}\",\n \"method\": \"{{ method() }}\"\n }\n}\n```\n\n### Custom Macros\n\nDefine reusable templates in `templates.json`:\n\n```json\n{\n \"functions\": {\n \"order_id\": \"counter('order', 1000, 1)\",\n \"product\": \"choice(['Widget', 'Gadget', 'Tool'])\",\n \"price\": \"random_float(10.0, 100.0, 2)\"\n }\n}\n```\n\n## \ud83c\udfaf Rules & Conditional Behavior\n\n### Rule Conditions\n\n- **Probability**: `\"0.1\"` (10% chance)\n- **Path equality**: `\"path.user_id == '123'\"`\n- **Query params**: `\"query.debug == 'true'\"`\n- **Headers**: `\"header.X-Test == 'yes'\"`\n- **Body fields**: `\"body.amount > 100\"`\n\n### Actions\n\n```json\n{\n \"rules\": {\n \"query.test == 'error'\": {\n \"status\": 500,\n \"response\": {\"error\": \"Test error\"},\n \"headers\": {\"X-Error\": \"true\"}\n },\n \"header.X-Slow == 'true'\": {\n \"delay\": \"2s\"\n },\n \"0.05\": {\n \"ignore\": true // 5% drop rate\n }\n }\n}\n```\n\n## \ud83e\uddea Testing\n\n### Running Tests\n\n```bash\n# All tests\npytest tests/ -v\n\n# Specific protocols\npytest tests/test_protocols.py::TestRESTProtocol -v\npytest tests/test_e2e_protocols.py -v\n\n# With coverage\npytest tests/ --cov=api_simulator\n```\n\n### Test Structure\n\n```\ntests/\n\u251c\u2500\u2500 test_cli.py # CLI command tests\n\u251c\u2500\u2500 test_protocols.py # Protocol unit tests\n\u2514\u2500\u2500 test_e2e_protocols.py # End-to-end with lifespan\n```\n\n## \ud83d\udcd6 Examples\n\n### Complete E-Commerce API\n\nSee [`examples/config.json`](examples/config.json) for a full example with:\n- Product catalog with search\n- Order streaming\n- Real-time price updates (SSE)\n- WebSocket order events\n- GraphQL customer queries\n- UDP inventory feeds\n\n### Testing Different Protocols\n\nAfter starting the server with `apisim run --config examples/config.json`:\n\n**REST API Tests:**\n```bash\n# Basic GET endpoint\ncurl http://localhost:3000/api/v1/status\n\n# Path parameters, query strings, and headers\ncurl \"http://localhost:3000/api/v1/products/PROD-123?q=search\" \\\n -H \"X-Session-Id: test-session\"\n\n# SSE streaming (real-time price updates)\ncurl -N http://localhost:3000/api/v1/prices/sse\n\n# NDJSON streaming \ncurl -N http://localhost:3000/api/v1/stream/orders\n```\n\n**GraphQL Tests:**\n```bash\n# Query\ncurl -X POST http://localhost:3000/graphql \\\n -H \"Content-Type: application/json\" \\\n -d '{\"operationName\":\"GetCustomer\"}'\n\n# Mutation\ncurl -X POST http://localhost:3000/graphql \\\n -H \"Content-Type: application/json\" \\\n -d '{\"operationName\":\"CreateOrder\"}'\n\n# List available operations\ncurl http://localhost:3000/openapi.json | jq '.paths.\"/graphql\"'\n```\n\n**WebSocket Tests:**\n```bash\n# Using wscat (npm install -g wscat)\nwscat -c ws://localhost:9080/realtime/events\n> {\"action\":\"subscribe\"}\n\n# Using Python\npython3 -c \"\nimport asyncio, websockets, json\nasync def test():\n async with websockets.connect('ws://localhost:9080/realtime/events') as ws:\n await ws.send(json.dumps({'action': 'subscribe'}))\n print(await ws.recv())\nasyncio.run(test())\n\"\n\n# GraphQL Subscriptions\npython3 -c \"\nimport asyncio, websockets, json\nasync def test():\n async with websockets.connect('ws://localhost:9080/realtime/graphql') as ws:\n await ws.send(json.dumps({'type': 'connection_init'}))\n print(await ws.recv())\n await ws.send(json.dumps({'id': '1', 'type': 'subscribe', \n 'payload': {'operationName': 'PriceUpdates'}}))\n print(await ws.recv())\nasyncio.run(test())\n\"\n```\n\n**UDP Listener:**\n```bash\npython3 -c \"\nimport socket, struct, msgpack\ns = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)\ns.bind(('127.0.0.1', 5001))\nprint('Listening on 127.0.0.1:5001...')\nwhile True:\n pkt, _ = s.recvfrom(65536)\n magic, ts, n = struct.unpack('>IIH', pkt[:10])\n print(f'Magic: 0x{magic:X}, Payload:', msgpack.unpackb(pkt[10:], raw=False))\n\"\n```\n\n## \ud83d\udd0c API Documentation\n\nWhen running, access auto-generated API docs at:\n\n- **Swagger UI**: http://localhost:3000/docs\n- **ReDoc**: http://localhost:3000/redoc\n- **OpenAPI JSON**: http://localhost:3000/openapi.json\n\n## \ud83d\udc33 Docker\n\n```dockerfile\nFROM python:3.11-slim\nWORKDIR /app\nCOPY . .\nRUN pip install -e .\nCMD [\"apisim\", \"run\", \"--config\", \"/config/config.json\"]\n```\n\n```bash\ndocker build -t api-simulator .\ndocker run -p 3000:3000 -p 9080:9080 \\\n -v $(pwd)/examples:/config \\\n api-simulator\n```\n\n## \ud83e\udd1d Contributing\n\nWe welcome contributions! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.\n\n### Development Setup\n\n```bash\n# Clone repository\ngit clone https://github.com/yourusername/api-simulator\ncd api-simulator\n\n# Create virtual environment\npython -m venv venv\nsource venv/bin/activate # or `venv\\Scripts\\activate` on Windows\n\n# Install with dev dependencies\npip install -e \".[test]\"\n\n# Run tests\npytest tests/ -v\n\n# Check code style\nruff check src/\n```\n\n## \ud83d\udcdd License\n\nMIT License - see [LICENSE](LICENSE) file for details.\n\n## \ud83d\ude4f Acknowledgments\n\nBuilt with:\n- [FastAPI](https://fastapi.tiangolo.com/) - REST/GraphQL server\n- [websockets](https://websockets.readthedocs.io/) - WebSocket support\n- [msgpack](https://msgpack.org/) - Binary serialization\n- [Pydantic](https://pydantic-docs.helpmanual.io/) - Data validation\n\n## \ud83d\udcee Support\n\n- \ud83d\udce7 Email: support@example.com\n- \ud83d\udcac Discord: [Join our server](https://discord.gg/example)\n- \ud83d\udc1b Issues: [GitHub Issues](https://github.com/yourusername/api-simulator/issues)\n\n---\n\n<div align=\"center\">\nMade with \u2764\ufe0f by the API Simulator Team\n</div>\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Multi-protocol API mocking made simple - REST, GraphQL, WebSocket, UDP from a single JSON config",
"version": "0.3.0",
"project_urls": {
"Documentation": "https://github.com/yourusername/api-simulator#documentation",
"Homepage": "https://github.com/yourusername/api-simulator",
"Issues": "https://github.com/yourusername/api-simulator/issues",
"Repository": "https://github.com/yourusername/api-simulator.git"
},
"split_keywords": [
"api",
" mock",
" simulator",
" rest",
" graphql",
" websocket",
" udp",
" testing",
" development"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "09ea2c0e208f3684596b5de2a501e9860fdbae46b6159f04dc48d626b92a0e9b",
"md5": "f1a7e61f6918f5434777a1aa0a914e7f",
"sha256": "035e4c6c02b6ccfcd461e4dda40094252f05dfc0a5220600ad0692d7cb47dbe0"
},
"downloads": -1,
"filename": "api_simulator-0.3.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "f1a7e61f6918f5434777a1aa0a914e7f",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.9",
"size": 23229,
"upload_time": "2025-08-16T01:24:36",
"upload_time_iso_8601": "2025-08-16T01:24:36.272634Z",
"url": "https://files.pythonhosted.org/packages/09/ea/2c0e208f3684596b5de2a501e9860fdbae46b6159f04dc48d626b92a0e9b/api_simulator-0.3.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "c1bdabbce2400e5d2e0f68d977075ac41c559c709b4994028a2994619147c2bb",
"md5": "0e6f8c170374aa496f62a1463445ab96",
"sha256": "1e8f6ab4a80a37891a19a19e0d56992be93ea889a81571b9d8866c2655b31997"
},
"downloads": -1,
"filename": "api_simulator-0.3.0.tar.gz",
"has_sig": false,
"md5_digest": "0e6f8c170374aa496f62a1463445ab96",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.9",
"size": 33090,
"upload_time": "2025-08-16T01:24:37",
"upload_time_iso_8601": "2025-08-16T01:24:37.279923Z",
"url": "https://files.pythonhosted.org/packages/c1/bd/abbce2400e5d2e0f68d977075ac41c559c709b4994028a2994619147c2bb/api_simulator-0.3.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-08-16 01:24:37",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "yourusername",
"github_project": "api-simulator#documentation",
"github_not_found": true,
"lcname": "api-simulator"
}