Semblance
Schema-driven REST API simulation with FastAPI, Pydantic, and Polyfactory.
Define API behavior declaratively using schemas and dependency metadata—no endpoint logic required. Semblance is built for contract testing, prototyping, frontend development, and integration testing against realistic API simulators.
Features
- Zero endpoint logic — Schemas and link metadata define responses
- FastAPI-native — Full OpenAPI, validation, async
- Deterministic — Seeded generation for reproducible tests
- Extensible — Custom link types via plugins
- Production-ready — Error simulation, latency, rate limiting, pagination, stateful mode, optional response validation
Requirements
- Python 3.10+
- FastAPI, Pydantic, Polyfactory, Uvicorn (installed with semblance)
Installation
pip install semblance
Optional unofficial adapters (separate packages):
pip install semblance-foundry
pip install semblance-databricks
From source (development):
git clone https://github.com/eddiethedean/semblance.git
cd semblance
pip install -e ".[dev]"
Quick Start
from datetime import date, datetime
from typing import Annotated
from pydantic import BaseModel
from semblance import DateRangeFrom, FromInput, SemblanceAPI
class UserQuery(BaseModel):
name: str = "alice"
start_date: date = date(2020, 1, 1)
end_date: date = date(2025, 12, 31)
class User(BaseModel):
name: Annotated[str, FromInput("name")]
created_at: Annotated[
datetime,
DateRangeFrom("start_date", "end_date"),
]
api = SemblanceAPI(seed=42)
@api.get("/users", input=UserQuery, output=list[User], list_count=2)
def users():
pass
app = api.as_fastapi()
You can register PUT, PATCH, and DELETE endpoints the same way (@api.put(...), @api.patch(...), @api.delete(..., output=None) for 204).
Run:
semblance run app:api --port 8000
# or
uvicorn app:app --reload
Try:
curl "http://127.0.0.1:8000/users?name=alice&start_date=2024-01-01&end_date=2024-12-31"
Example output (with SemblanceAPI(seed=42) and list_count=2 for reproducibility):
[
{"name": "alice", "created_at": "2024-08-21T09:22:43.516168"},
{"name": "alice", "created_at": "2024-01-10T03:05:39.176702"}
]
Responses are generated from your output model: name comes from the query, created_at is in the date range.
Use Cases
| Use Case | Description |
|---|---|
| Contract testing | Validate client behavior against a schema-accurate mock |
| Frontend development | Run a mock API for UI work without a backend |
| Prototyping | Ship realistic API shapes before implementation |
| Integration tests | Deterministic, isolated API simulators in CI |
CLI
# Scaffold a minimal app (app.py and optional semblance.yaml)
semblance init [-c] [--force]
# Validate routes and link bindings without starting a server (CI-friendly)
semblance validate module:attr
# Run a Semblance app (module:attr or just module when unambiguous)
semblance run app:api [--host HOST] [--port PORT] [--reload]
# Export OpenAPI schema (optionally with response examples)
semblance export openapi app:api [-o FILE] [--examples]
# Export OpenAPI + JSON fixtures per endpoint (GET, POST, PUT, PATCH, DELETE)
semblance export fixtures app:api [-o DIR]
Examples
Runnable examples in examples/:
semblance run examples.basic.app:api --port 8000
semblance run examples.pagination.app:api --port 8000
semblance run examples.nested.app:api --port 8000
semblance run examples.stateful.app:api --port 8000
semblance run examples.advanced.app:api --port 8000
semblance run examples.error_simulation.app:api --port 8000
semblance run examples.plugins.app:api --port 8000
semblance run examples.put_patch_delete.app:api --port 8000
semblance run examples.stateful_crud.app:api --port 8000
semblance run examples.request_links.app:api --port 8000
| Example | Description |
|---|---|
| basic | Minimal GET list with FromInput, DateRangeFrom |
| pagination | PageParams, PaginatedResponse |
| nested | Nested model linking |
| stateful | POST stores items, GET returns stored list |
| advanced | WhenInput, ComputedFrom, filter_by |
| error_simulation | error_rate, error_codes |
| plugins | Custom link (FromEnv) |
| put_patch_delete | PUT, PATCH, DELETE (non-stateful) |
| stateful_crud | Full stateful CRUD: GET by id, PUT, PATCH, DELETE |
| request_links | FromHeader, FromCookie |
Testing
Use the same api from Quick Start (with app = api.as_fastapi()). With the test client you get deterministic responses without starting a server:
from semblance import SemblanceAPI, test_client
# api and app from Quick Start above
client = test_client(app)
r = client.get("/users?name=testuser")
assert r.status_code == 200
data = r.json()
assert all(u["name"] == "testuser" for u in data)
# data is a list of User dicts, e.g. [{"name": "testuser", "created_at": "..."}, ...]
Deterministic seeding for reproducible tests:
api = SemblanceAPI(seed=42)
# or per-endpoint: seed_from="seed" with a query param
Plugins
Register custom link types:
from semblance import register_link, SemblanceAPI
from typing import Annotated
class FromEnv:
def __init__(self, env_var: str):
self.env_var = env_var
def resolve(self, input_data, rng):
import os
return os.environ.get(self.env_var)
register_link(FromEnv)
class User(BaseModel):
name: Annotated[str, FromEnv("USER_NAME")]
API Overview
| Feature | Description |
|---|---|
| SemblanceAPI | GET, POST, PUT, PATCH, DELETE endpoints with input/output models |
| Links | FromInput, DateRangeFrom, WhenInput, ComputedFrom |
| Pagination | PageParams, PaginatedResponse[T] |
| Seeding | SemblanceAPI(seed=42) or seed_from="seed" |
| Error simulation | error_rate, error_codes |
| Latency | latency_ms, jitter_ms |
| Rate limiting | rate_limit=N — 429 when exceeded (per endpoint, sliding window) |
| Filtering | filter_by for list endpoints |
| Stateful mode | SemblanceAPI(stateful=True) — POST stores; GET (list + by-id), PUT/PATCH/DELETE by id use store |
| Response validation | SemblanceAPI(validate_responses=True) — verify output conforms to model |
| OpenAPI | summary, description, tags on endpoints |
| Property-based testing | semblance.property_testing: strategy_for_input_model(), test_endpoint() (Hypothesis) |
Competitors & Alternatives
| Feature | Semblance | fastapi-mock | Prism | json-server | Schemathesis | Mockoon |
|---|---|---|---|---|---|---|
| Mock API server | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ |
| Python / FastAPI native | ✅ | ✅ | ❌ | ❌ | ✅ | ❌ |
| Zero endpoint logic | ✅ | ❌ | ✅ | ✅ | ❌ | ✅ |
| Realistic example generation | ✅ | 🟡 | ✅ | ❌ | ❌ | 🟡 |
| Input→output binding | ✅ | ❌ | ❌ | ❌ | ❌ | 🟡 |
| Deterministic seeding | ✅ | ❌ | ✅ | ❌ | ✅ | 🟡 |
| Pagination helpers | ✅ | ❌ | 🟡 | ✅ | ❌ | 🟡 |
| Error simulation | ✅ | ❌ | 🟡 | ❌ | ❌ | 🟡 |
| Stateful mode | ✅ | ❌ | ❌ | ✅ | ❌ | 🟡 |
| Extensible (plugins) | ✅ | 🟡 | ❌ | ❌ | ✅ | 🟡 |
| OpenAPI schema | ✅ | ✅ | ✅ | ❌ | ✅ | 🟡 |
| CI / pytest integration | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ |
| Property-based testing | ✅ | ❌ | ❌ | ❌ | ✅ | ❌ |
🟡 = partial or configurable
Documentation
Full documentation: semblance.readthedocs.io
- Getting Started
- Concepts
- Input and Output Binding
- Advanced Links
- Pagination
- Simulation Options
- Stateful Mode
- CLI
- Plugins
- Request Links
- Testing
- Troubleshooting
- Cookbook
- Foundry adapter
- Databricks adapter
- Roadmap
- API Reference
Development
See CONTRIBUTING.md for setup and contribution guidelines.
git clone https://github.com/eddiethedean/semblance.git
cd semblance
pip install -e ".[dev]"
pip install -e packages/semblance-foundry[dev]
pip install -e packages/semblance-databricks[dev]
pytest tests/ -v -m "not sdk"
pytest packages/semblance-foundry/tests -v -m "not sdk"
pytest packages/semblance-databricks/tests -v -m "not sdk"
License
MIT License.
Metadata
Release files for semblance 0.9.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 | |
|---|---|---|---|
| semblance-0.9.0.tar.gz | 56.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| semblance-0.9.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 96.0 kB
Release files / semblance-0.9.0.tar.gz
| Download URL | semblance-0.9.0.tar.gz |
|---|---|
| Size | 56.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
bad42288a4e2cf688b24a143acd90872978b214ac4a7580def5d97a9e3eca05c
|
|
BLAKE2b-256 checksum How to use checksums |
51cf407bcd60f1043f7d1421310bb3ecead6c723b93a2943bdc9b391163177b4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / semblance-0.9.0-py3-none-any.whl
| Download URL | semblance-0.9.0-py3-none-any.whl |
|---|---|
| Size | 39.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e341f43619d294677216b13a34091ae4e3632c053976762557e0412f6761329d
|
|
BLAKE2b-256 checksum How to use checksums |
19c5f5a9ae4f17be35bf17bb93163114ac40c71c3440ad1a5dd925b1f70df96e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|