How to Build a REST API with Python Flask: Step-by-Step Tutorial for Beginners

One of the most popular services we offer is ongoing website maintenance because most clients we work with become return clients.

How to Build a REST API with Python Flask: Step-by-Step Tutorial for Beginners

Build a REST API with Python Flask: A Practical Guide for 2026

If you want to build a REST API with Python Flask, you are in the right place. In this tutorial, we will walk through everything you need to create a fully working API: setting up Flask, defining routes, handling JSON requests, returning responses, and managing errors properly. All code examples are copy-paste ready and tested on Python 3.12 and Flask 3.1.

Unlike most tutorials that stop at a basic “hello world”, we will build a small but realistic Books API with full CRUD operations, so you finish this article with something you can actually reuse in your projects.

python code laptop

Why Flask for REST APIs?

Flask is a lightweight WSGI web framework that has remained one of the most popular choices for Python developers, even in 2026. It is minimal, flexible, and perfect for small to medium APIs or microservices.

  • Minimal setup: install one package and you are ready.
  • Flexible: choose your own libraries for database, validation, auth.
  • Huge ecosystem: Flask-SQLAlchemy, Flask-Smorest, Flask-JWT-Extended.
  • Great documentation and a massive community.

Flask vs FastAPI in 2026

Criteria Flask FastAPI
Learning curve Very easy Easy
Performance Good (sync) Excellent (async)
Ecosystem Mature, very large Growing fast
Best for Simple APIs, microservices, prototypes High-performance async APIs

If you need raw speed and async out of the box, FastAPI is a great choice. If you want simplicity, stability and full control, Flask is still an excellent pick.

Step 1: Set Up Your Project

Create a new folder and a virtual environment:

mkdir flask-books-api
cd flask-books-api
python -m venv venv
source venv/bin/activate   # On Windows: venv\Scripts\activate
pip install flask

Then create a file named app.py. That is the only file we will need for this tutorial.

python code laptop

Step 2: Your First Flask Route

Let’s start with a minimal Flask app to make sure everything works:

from flask import Flask, jsonify

app = Flask(__name__)

@app.route("/", methods=["GET"])
def home():
    return jsonify({"message": "Welcome to the Books API"})

if __name__ == "__main__":
    app.run(debug=True, port=5000)

Run it with:

python app.py

Open http://localhost:5000 and you should see a JSON response. Done, your first Flask endpoint is live.

Step 3: Build the Full CRUD REST API

Now let’s replace the content of app.py with a complete CRUD API for a list of books. We will use an in-memory dictionary as a fake database to keep things simple.

from flask import Flask, jsonify, request, abort

app = Flask(__name__)

# Fake in-memory database
books = {
    1: {"title": "Clean Code", "author": "Robert C. Martin", "year": 2008},
    2: {"title": "The Pragmatic Programmer", "author": "Andy Hunt", "year": 1999},
}
next_id = 3


@app.route("/api/books", methods=["GET"])
def get_books():
    return jsonify(books), 200


@app.route("/api/books/<int:book_id>", methods=["GET"])
def get_book(book_id):
    book = books.get(book_id)
    if book is None:
        abort(404, description="Book not found")
    return jsonify(book), 200


@app.route("/api/books", methods=["POST"])
def create_book():
    global next_id
    if not request.is_json:
        abort(400, description="Request body must be JSON")

    data = request.get_json()
    required = ["title", "author", "year"]
    if not all(field in data for field in required):
        abort(400, description=f"Missing fields. Required: {required}")

    new_book = {
        "title": data["title"],
        "author": data["author"],
        "year": data["year"],
    }
    books[next_id] = new_book
    created_id = next_id
    next_id += 1
    return jsonify({"id": created_id, "book": new_book}), 201


@app.route("/api/books/<int:book_id>", methods=["PUT"])
def update_book(book_id):
    if book_id not in books:
        abort(404, description="Book not found")
    if not request.is_json:
        abort(400, description="Request body must be JSON")

    data = request.get_json()
    book = books[book_id]
    book["title"] = data.get("title", book["title"])
    book["author"] = data.get("author", book["author"])
    book["year"] = data.get("year", book["year"])
    return jsonify(book), 200


@app.route("/api/books/<int:book_id>", methods=["DELETE"])
def delete_book(book_id):
    if book_id not in books:
        abort(404, description="Book not found")
    deleted = books.pop(book_id)
    return jsonify({"deleted": deleted}), 200


# Error handlers
@app.errorhandler(400)
def bad_request(error):
    return jsonify({"error": "Bad Request", "message": str(error.description)}), 400


@app.errorhandler(404)
def not_found(error):
    return jsonify({"error": "Not Found", "message": str(error.description)}), 404


@app.errorhandler(405)
def method_not_allowed(error):
    return jsonify({"error": "Method Not Allowed"}), 405


@app.errorhandler(500)
def server_error(error):
    return jsonify({"error": "Internal Server Error"}), 500


if __name__ == "__main__":
    app.run(debug=True, port=5000)

Restart the app and you now have a fully working REST API with five endpoints.

Endpoint Summary

Method Endpoint Description
GET /api/books List all books
GET /api/books/<id> Get one book
POST /api/books Create a new book
PUT /api/books/<id> Update an existing book
DELETE /api/books/<id> Delete a book

Step 4: Test Your API

You can test the API using curl, Postman, HTTPie, or your favorite REST client.

Create a new book (POST)

curl -X POST http://localhost:5000/api/books \
  -H "Content-Type: application/json" \
  -d '{"title":"Designing Data-Intensive Applications","author":"Martin Kleppmann","year":2017}'

Get all books (GET)

curl http://localhost:5000/api/books

Update a book (PUT)

curl -X PUT http://localhost:5000/api/books/1 \
  -H "Content-Type: application/json" \
  -d '{"year":2009}'

Delete a book (DELETE)

curl -X DELETE http://localhost:5000/api/books/2
python code laptop

Step 5: Best Practices to Take It Further

Now that you have a working API, here are the next steps to make it production-ready:

  1. Use a real database with Flask-SQLAlchemy (PostgreSQL, MySQL, or SQLite).
  2. Validate input using Pydantic, Marshmallow, or Flask-Smorest.
  3. Add authentication with Flask-JWT-Extended.
  4. Document the API automatically with APIFlask or Flask-Smorest (OpenAPI/Swagger).
  5. Use Blueprints to organize routes when the project grows.
  6. Deploy with Gunicorn behind Nginx, or use a PaaS like Fly.io or Render.
  7. Add tests with pytest and Flask’s test client.

Recommended Project Structure

flask-books-api/
├── app/
│   ├── __init__.py
│   ├── routes/
│   │   └── books.py
│   ├── models.py
│   └── schemas.py
├── tests/
│   └── test_books.py
├── requirements.txt
└── run.py

Common Pitfalls to Avoid

  • Forgetting jsonify(): returning a Python dict works in modern Flask, but jsonify gives you full control of headers.
  • Running debug mode in production: never do this, it exposes a Python shell.
  • Skipping input validation: always validate JSON payloads before using them.
  • No error handlers: without them, your users get HTML error pages instead of JSON.

FAQ

Is Flask still used in 2026?

Yes. Flask remains one of the most popular Python web frameworks in 2026, especially for microservices, internal tools and APIs where simplicity matters more than async performance.

Is Python Flask a REST API framework?

Flask itself is a general-purpose web framework, but it is widely used to build REST APIs thanks to its routing system and JSON helpers. Extensions like Flask-Smorest or APIFlask add REST-specific features.

Can I build a REST API in Python without Flask?

Yes. Alternatives include FastAPI, Django REST Framework, Starlette, Falcon, and even the standard library. Flask is just one of the easiest to start with.

Should I choose Flask or FastAPI?

Choose Flask for simplicity, stability and a huge ecosystem. Choose FastAPI if you need async performance and automatic OpenAPI documentation out of the box.

How do I deploy a Flask REST API?

Use a production WSGI server like Gunicorn or uWSGI behind Nginx, or deploy to platforms like Render, Fly.io, Railway, AWS, or Google Cloud Run.

Conclusion

You just learned how to build a REST API with Python Flask from scratch, including routing, JSON handling, CRUD operations, and proper error management. The code in this tutorial works out of the box and is a solid foundation for any real-world project.

From here, plug in a database, add validation and authentication, and you have a production-grade API. Happy coding from the Pixelseed team!

Subscription Form

Contact Details

Quick Links

Copyright © 2022 Pixel Seed. All Rights Reserved.