{"id":13467452,"url":"https://github.com/apiflask/apiflask","last_synced_at":"2025-05-13T21:04:41.839Z","repository":{"id":37296251,"uuid":"329190167","full_name":"apiflask/apiflask","owner":"apiflask","description":"A lightweight Python web API framework.","archived":false,"fork":false,"pushed_at":"2025-05-04T03:52:37.000Z","size":2171,"stargazers_count":1091,"open_issues_count":25,"forks_count":136,"subscribers_count":19,"default_branch":"main","last_synced_at":"2025-05-13T08:15:41.682Z","etag":null,"topics":["api","flask","marshmallow","openapi","openapi3","python","redoc","rest","swagger","swagger-ui"],"latest_commit_sha":null,"homepage":"https://apiflask.com","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/apiflask.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGES.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yaml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":".github/SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":null,"patreon":null,"open_collective":"apiflask","ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":null}},"created_at":"2021-01-13T04:08:48.000Z","updated_at":"2025-05-08T13:48:47.000Z","dependencies_parsed_at":"2024-03-17T05:25:17.461Z","dependency_job_id":"b982d52a-18d2-4d78-a597-b4867945aa3a","html_url":"https://github.com/apiflask/apiflask","commit_stats":{"total_commits":792,"total_committers":45,"mean_commits":17.6,"dds":"0.19444444444444442","last_synced_commit":"d71d64a3e4b18ce74129de103e364a321ee33b66"},"previous_names":[],"tags_count":44,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/apiflask%2Fapiflask","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/apiflask%2Fapiflask/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/apiflask%2Fapiflask/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/apiflask%2Fapiflask/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/apiflask","download_url":"https://codeload.github.com/apiflask/apiflask/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254028498,"owners_count":22002273,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api","flask","marshmallow","openapi","openapi3","python","redoc","rest","swagger","swagger-ui"],"created_at":"2024-07-31T15:00:56.651Z","updated_at":"2025-05-13T21:04:41.829Z","avatar_url":"https://github.com/apiflask.png","language":"Python","funding_links":["https://opencollective.com/apiflask"],"categories":["Python","Third-Party Extensions","Web APIs"],"sub_categories":["APIs"],"readme":"\n![](https://apiflask.com/_assets/apiflask-logo.png)\n\n# APIFlask\n\n[![Build status](https://github.com/apiflask/apiflask/actions/workflows/tests.yml/badge.svg)](https://github.com/apiflask/apiflask/actions) [![codecov](https://codecov.io/gh/apiflask/apiflask/branch/main/graph/badge.svg?token=2CFPCZ1DMY)](https://codecov.io/gh/apiflask/apiflask)\n\nAPIFlask is a lightweight Python web API framework based on [Flask](https://github.com/pallets/flask) and [marshmallow-code](https://github.com/marshmallow-code) projects. It's easy to use, highly customizable, ORM/ODM-agnostic, and 100% compatible with the Flask ecosystem.\n\nWith APIFlask, you will have:\n\n- More sugars for view function (`@app.input()`, `@app.output()`, `@app.get()`, `@app.post()` and more)\n- Automatic request validation and deserialization\n- Automatic response formatting and serialization\n- Automatic [OpenAPI Specification](https://github.com/OAI/OpenAPI-Specification) (OAS, formerly Swagger Specification) document generation\n- Automatic interactive API documentation\n- API authentication support (with [Flask-HTTPAuth](https://github.com/miguelgrinberg/flask-httpauth))\n- Automatic JSON response for HTTP errors\n\n\n## Requirements\n\n- Python 3.8+\n- Flask 2.0+\n\n\n## Installation\n\nFor Linux and macOS:\n\n```bash\n$ pip3 install apiflask\n```\n\nFor Windows:\n\n```bash\n\u003e pip install apiflask\n```\n\n\n## Links\n\n- Website: \u003chttps://apiflask.com\u003e\n- Documentation: \u003chttps://apiflask.com/docs\u003e\n- 中文文档: \u003chttps://zh.apiflask.com/docs\u003e\n- PyPI Releases: \u003chttps://pypi.python.org/pypi/APIFlask\u003e\n- Change Log: \u003chttps://apiflask.com/changelog\u003e\n- Source Code: \u003chttps://github.com/apiflask/apiflask\u003e\n- Issue Tracker: \u003chttps://github.com/apiflask/apiflask/issues\u003e\n- Discussion: \u003chttps://github.com/apiflask/apiflask/discussions\u003e\n- 中文论坛: \u003chttps://codekitchen.community\u003e\n- Twitter: \u003chttps://twitter.com/apiflask\u003e\n- Open Collective: \u003chttps://opencollective.com/apiflask\u003e\n\n\n## Donate\n\nIf you find APIFlask useful, please consider [donating](https://opencollective.com/apiflask) today. Your donation keeps APIFlask maintained and evolving.\n\nThank you to all our backers and sponsors!\n\n### Backers\n\n[![](https://opencollective.com/apiflask/backers.svg?width=890)](https://opencollective.com/apiflask)\n\n### Sponsors\n\n[![](https://opencollective.com/apiflask/sponsors.svg?width=890)](https://opencollective.com/apiflask)\n\n## Example\n\n```python\nfrom apiflask import APIFlask, Schema, abort\nfrom apiflask.fields import Integer, String\nfrom apiflask.validators import Length, OneOf\n\napp = APIFlask(__name__)\n\npets = [\n    {'id': 0, 'name': 'Kitty', 'category': 'cat'},\n    {'id': 1, 'name': 'Coco', 'category': 'dog'}\n]\n\n\nclass PetIn(Schema):\n    name = String(required=True, validate=Length(0, 10))\n    category = String(required=True, validate=OneOf(['dog', 'cat']))\n\n\nclass PetOut(Schema):\n    id = Integer()\n    name = String()\n    category = String()\n\n\n@app.get('/')\ndef say_hello():\n    # returning a dict or list equals to use jsonify()\n    return {'message': 'Hello!'}\n\n\n@app.get('/pets/\u003cint:pet_id\u003e')\n@app.output(PetOut)\ndef get_pet(pet_id):\n    if pet_id \u003e len(pets) - 1:\n        abort(404)\n    # you can also return an ORM/ODM model class instance directly\n    # APIFlask will serialize the object into JSON format\n    return pets[pet_id]\n\n\n@app.patch('/pets/\u003cint:pet_id\u003e')\n@app.input(PetIn(partial=True))  # -\u003e json_data\n@app.output(PetOut)\ndef update_pet(pet_id, json_data):\n    # the validated and parsed input data will\n    # be injected into the view function as a dict\n    if pet_id \u003e len(pets) - 1:\n        abort(404)\n    for attr, value in json_data.items():\n        pets[pet_id][attr] = value\n    return pets[pet_id]\n```\n\n\u003cdetails\u003e\n\u003csummary\u003eYou can also use class-based views based on \u003ccode\u003eMethodView\u003c/code\u003e\u003c/summary\u003e\n\n```python\nfrom apiflask import APIFlask, Schema, abort\nfrom apiflask.fields import Integer, String\nfrom apiflask.validators import Length, OneOf\nfrom flask.views import MethodView\n\napp = APIFlask(__name__)\n\npets = [\n    {'id': 0, 'name': 'Kitty', 'category': 'cat'},\n    {'id': 1, 'name': 'Coco', 'category': 'dog'}\n]\n\n\nclass PetIn(Schema):\n    name = String(required=True, validate=Length(0, 10))\n    category = String(required=True, validate=OneOf(['dog', 'cat']))\n\n\nclass PetOut(Schema):\n    id = Integer()\n    name = String()\n    category = String()\n\n\nclass Hello(MethodView):\n\n    # use HTTP method name as class method name\n    def get(self):\n        return {'message': 'Hello!'}\n\n\nclass Pet(MethodView):\n\n    @app.output(PetOut)\n    def get(self, pet_id):\n        \"\"\"Get a pet\"\"\"\n        if pet_id \u003e len(pets) - 1:\n            abort(404)\n        return pets[pet_id]\n\n    @app.input(PetIn(partial=True))\n    @app.output(PetOut)\n    def patch(self, pet_id, json_data):\n        \"\"\"Update a pet\"\"\"\n        if pet_id \u003e len(pets) - 1:\n            abort(404)\n        for attr, value in json_data.items():\n            pets[pet_id][attr] = value\n        return pets[pet_id]\n\n\napp.add_url_rule('/', view_func=Hello.as_view('hello'))\napp.add_url_rule('/pets/\u003cint:pet_id\u003e', view_func=Pet.as_view('pet'))\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eOr use \u003ccode\u003easync def\u003c/code\u003e\u003c/summary\u003e\n\n```bash\n$ pip install -U \"apiflask[async]\"\n```\n\n```python\nimport asyncio\n\nfrom apiflask import APIFlask\n\napp = APIFlask(__name__)\n\n\n@app.get('/')\nasync def say_hello():\n    await asyncio.sleep(1)\n    return {'message': 'Hello!'}\n```\n\nSee \u003cem\u003e\u003ca href=\"https://flask.palletsprojects.com/async-await\"\u003eUsing async and await\u003c/a\u003e\u003c/em\u003e for the details of the async support in Flask 2.0.\n\n\u003c/details\u003e\n\nSave this as `app.py`, then run it with:\n\n```bash\n$ flask run --reload\n```\n\nOr run in debug mode:\n\n```bash\n$ flask run --debug\n```\n\nNow visit the interactive API documentation (Swagger UI) at \u003chttp://localhost:5000/docs\u003e:\n\n![](https://apiflask.com/_assets/swagger-ui.png)\n\nOr you can change the API documentation UI when creating the APIFlask instance with the `docs_ui` parameter:\n\n```py\napp = APIFlask(__name__, docs_ui='redoc')\n```\n\nNow \u003chttp://localhost:5000/docs\u003e will render the API documentation with Redoc.\n\nSupported `docs_ui` values (UI libraries) include:\n\n- `swagger-ui` (default value): [Swagger UI](https://github.com/swagger-api/swagger-ui)\n- `redoc`: [Redoc](https://github.com/Redocly/redoc)\n- `elements`: [Elements](https://github.com/stoplightio/elements)\n- `rapidoc`: [RapiDoc](https://github.com/rapi-doc/RapiDoc)\n- `rapipdf`: [RapiPDF](https://github.com/mrin9/RapiPdf)\n\nThe auto-generated OpenAPI spec file is available at \u003chttp://localhost:5000/openapi.json\u003e. You can also get the spec with [the `flask spec` command](https://apiflask.com/openapi/#the-flask-spec-command):\n\n```bash\n$ flask spec\n```\n\nFor some complete examples, see [/examples](https://github.com/apiflask/apiflask/tree/main/examples).\n\n\n## Relationship with Flask\n\nAPIFlask is a thin wrapper on top of Flask. You only need to remember the following differences (see *[Migrating from Flask](https://apiflask.com/migrations/flask/)* for more details):\n\n- When creating an application instance, use `APIFlask` instead of `Flask`.\n- When creating a blueprint instance, use `APIBlueprint` instead of `Blueprint`.\n- The `abort()` function from APIFlask (`apiflask.abort`) returns JSON error response.\n\nFor a minimal Flask application:\n\n```python\nfrom flask import Flask, request\nfrom markupsafe import escape\n\napp = Flask(__name__)\n\n@app.route('/')\ndef hello():\n    name = request.args.get('name', 'Human')\n    return f'Hello, {escape(name)}'\n```\n\nNow change to APIFlask:\n\n```python\nfrom apiflask import APIFlask  # step one\nfrom flask import request\nfrom markupsafe import escape\n\napp = APIFlask(__name__)  # step two\n\n@app.route('/')\ndef hello():\n    name = request.args.get('name', 'Human')\n    return f'Hello, {escape(name)}'\n```\n\nIn a word, to make Web API development in Flask more easily, APIFlask provides `APIFlask` and `APIBlueprint` to extend Flask's `Flask` and `Blueprint` objects and it also ships with some helpful utilities. Other than that, you are actually using Flask.\n\n\n## Relationship with marshmallow\n\nAPIFlask accepts marshmallow schema as data schema, uses webargs to validate the request data against the schema, and uses apispec to generate the OpenAPI representation from the schema.\n\nYou can build marshmallow schemas just like before, but APIFlask also exposes some marshmallow APIs for convenience:\n\n- `apiflask.Schema`: The base marshmallow schema class.\n- `apiflask.fields`: The marshmallow fields, contain the fields from both marshmallow and Flask-Marshmallow. Beware that the aliases (`Url`, `Str`, `Int`, `Bool`, etc.) were removed.\n- `apiflask.validators`: The marshmallow validators.\n\n```python\nfrom apiflask import Schema\nfrom apiflask.fields import Integer, String\nfrom apiflask.validators import Length, OneOf\nfrom marshmallow import pre_load, post_dump, ValidationError\n```\n\n## Credits\n\nAPIFlask starts as a fork of [APIFairy](https://github.com/miguelgrinberg/APIFairy) and is inspired by [flask-smorest](https://github.com/marshmallow-code/flask-smorest) and [FastAPI](https://github.com/tiangolo/fastapi) (see *[Comparison and Motivations](https://apiflask.com/comparison)* for the comparison between these projects).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fapiflask%2Fapiflask","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fapiflask%2Fapiflask","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fapiflask%2Fapiflask/lists"}