Spectree
API spec validator and OpenAPI document generator for Python web frameworks.
Install / Use
/learn @0b01001001/SpectreeREADME
SpecTree
Yet another library to generate OpenAPI documents and validate requests & responses with Python annotations.
If all you need is a framework-agnostic library that can generate OpenAPI document, check defspec.
Features
- Less boilerplate code, only annotations, no need for YAML :sparkles:
- Generate API document with Redoc UI, Scalar UI or Swagger UI :yum:
- Validate query, JSON data, response data with pydantic (both v1 & v2) :wink:
- Current support:
Quick Start
Install with pip:
pip install spectree
If you want to install with offline OpenAPI web pages support:
Offline mode doesn't support SwaggerUI OAuth2 redirection.
pip install spectree[offline]
Examples
Check the examples folder.
Step by Step
- Define your data structure used in (query, json, headers, cookies, resp) with
pydantic.BaseModel - create
spectree.SpecTreeinstance with the web framework name you are using, likeapi = SpecTree('flask') api.validatedecorate the route with (the default value is given in parentheses):queryjsonheaderscookiesresptags(no tags on endpoint)security(None- endpoint is not secured)deprecated(False- endpoint is not marked as deprecated)
- access these data from the function annotations (see the examples below). Of course, you can still access them from the original place where the framework offered.
- register to the web application
api.register(app) - check the document at URL location
/apidoc/redocor/apidoc/swaggeror/apidoc/scalar
If the request doesn't pass the validation, it will return a 422 with a JSON error message(ctx, loc, msg, type).
Falcon response validation
For Falcon response, this library only validates against media as it is the serializable object. Response.text is a string representing response content and will not be validated. For no assigned media situation, resp parameter in api.validate should be like Response(HTTP_200=None)
Opt-in type annotation feature
This library also supports the injection of validated fields into view function arguments along with parameter annotation-based type declaration. This works well with linters that can take advantage of typing features like mypy. See the examples section below.
How-To
How to add summary and description to endpoints?
Just add docs to the endpoint function. The 1st line is the summary, and the rest is the description for this endpoint.
How to add a description to parameters?
Check the pydantic document about description in Field.
Any config I can change?
Of course. Check the config document.
You can update the config when init the spectree like:
SpecTree('flask', title='Demo API', version='v1.0', path='doc')
What is
Responseand how to use it?
To build a response for the endpoint, you need to declare the status code with format HTTP_{code} and corresponding data (optional).
Response(HTTP_200=None, HTTP_403=ForbidModel)
Response('HTTP_200') # equals to Response(HTTP_200=None)
# with custom code description
Response(HTTP_403=(ForbidModel, "custom code description"))
How can I skip the validation?
Add skip_validation=True to the decorator.
Before v1.3.0, this only skip the response validation.
Starts from v1.3.0, this will skip all the validations. As an result, you won't be able to access the validated data from context.
@api.validate(json=Profile, resp=Response(HTTP_200=Message, HTTP_403=None), skip_validation=True)
How can I use the validation without the OpenAPI document?
The OpenAPI endpoints are added by spectree.register(app). If you don't want to add the OpenAPI endpoints, you don't need to register it to the application.
How to secure API endpoints?
For secure API endpoints, it is needed to define the security_schemes argument in the SpecTree constructor. security_schemes argument needs to contain an array of SecurityScheme objects. Then there are two ways to enforce security:
- You can enforce security on individual API endpoints by defining the
securityargument in theapi.validatedecorator of relevant function/method (this corresponds to define security section on operation level, underpaths, inOpenAPI).securityargument is defined as a dictionary, where each key is the name of security used insecurity_schemesargument ofSpecTreeconstructor and its value is required security scope, as is showed in the following example:
api = SpecTree(security_schemes=[
SecurityScheme(
name="auth_apiKey",
data={"type": "apiKey", "name": "Authorization", "in": "header"},
),
SecurityScheme(
name="auth_oauth2",
data={
"type": "oauth2",
"flows": {
"authorizationCode": {
"authorizationUrl": "https://example.com/oauth/authorize",
"tokenUrl": "https://example.com/oauth/token",
"scopes": {
"read": "Grants read access",
"write": "Grants write access",
"admin": "Grants access to admin operations",
},
},
},
},
),
# ...
],
# ...
)
# Not secured API endpoint
@api.validate(
resp=Response(HTTP_200=None),
)
def foo():
...
# API endpoint secured by API key type or OAuth2 type
@api.validate(
resp=Response(HTTP_200=None),
security={"auth_apiKey": [], "auth_oauth2": ["read", "write"]}, # Local security type
)
def bar():
...
</p>
</details>
- You can enforce security on the whole API by defining the
securityargument in theSpecTreeconstructor (this corresponds to the define security section on the root level inOpenAPI). It is possible to override global security by defining local security, as well as override to no security on some API endpoint, in thesecurityargument ofapi.validatedecorator of relevant function/method as was described in the previous point. It is also shown in the following small example:
api = SpecTree(security_schemes=[
SecurityScheme(
name="auth_apiKey",
data={"type": "apiKey", "name": "Authorization", "in": "header"},
),
SecurityScheme(
name="auth_oauth2",
data={
"type": "oauth2",
"flows": {
"authorizationCode": {
"authorizationUrl": "https://example.com/oauth/authorize",
"tokenUrl": "https://example.com/oauth/token",
"scopes": {
"read": "Grants read access",
"write": "Grants write access",
"admin": "Grants access to admin operations",
},
},
},
},
),
# ...
],
security={"auth_apiKey": []}, # Global security type
# ...
)
# Force no security
@api.validate(
resp=Response(HTTP_200=None),
security={}, # Locally overridden security type
)
def foo():
...
# Force another type of security than global one
@api.validate(
resp=Response(HTTP_200=None),
security={"auth_oauth2": ["read"]}, # Locally overridden security type
)
def bar():
...
# Use the global security
@api.validate(
resp=Response(HTTP_200=None),
)
def foobar():
...
</p>
</details>
How to mark deprecated endpoint?
Use deprecated attribute with value True in api.validate() decorator. This way, an endpoint will be marked as
deprecated and will be marked with a strikethrough in API documentation.
Code example:
@api.validate(
deprecated=True,
)
def deprecated_endpoint():
...
What should I return when I'm using the library?
No need to change anything. Just return what the framework required.
How to log when the validation failed?
Validation errors are logged with the INFO level. Details are passed into extra. Check the falcon example for details.
How can I write a customized plugin for another backend framework?
Inherit spectree.plugins.base.BasePlugin and implement the functions you need. After that, init like api = SpecTree(backend=MyCustomizedPlugin).
How to use a customized template page?
Related Skills
claude-opus-4-5-migration
82.5kMigrate prompts and code from Claude Sonnet 4.0, Sonnet 4.5, or Opus 4.1 to Opus 4.5
model-usage
335.2kUse CodexBar CLI local cost usage to summarize per-model usage for Codex or Claude, including the current (most recent) model or a full model breakdown. Trigger when asked for model-level usage/cost data from codexbar, or when you need a scriptable per-model summary from codexbar cost JSON.
TrendRadar
49.7k⭐AI-driven public opinion & trend monitor with multi-platform aggregation, RSS, and smart alerts.🎯 告别信息过载,你的 AI 舆情监控助手与热点筛选工具!聚合多平台热点 + RSS 订阅,支持关键词精准筛选。AI 智能筛选新闻 + AI 翻译 + AI 分析简报直推手机,也支持接入 MCP 架构,赋能 AI 自然语言对话分析、情感洞察与趋势预测等。支持 Docker ,数据本地/云端自持。集成微信/飞书/钉钉/Telegram/邮件/ntfy/bark/slack 等渠道智能推送。
mcp-for-beginners
15.6kThis open-source curriculum introduces the fundamentals of Model Context Protocol (MCP) through real-world, cross-language examples in .NET, Java, TypeScript, JavaScript, Rust and Python. Designed for developers, it focuses on practical techniques for building modular, scalable, and secure AI workflows from session setup to service orchestration.
