What You'll Build

In this tutorial, you'll create a simple but fully functional REST API using Python and Flask. By the end, you'll have a working API with CRUD operations, proper HTTP status codes, and basic error handling — skills that transfer directly to real-world projects.

Prerequisites

  • Python 3.8 or higher installed
  • Basic familiarity with Python syntax
  • A terminal / command line
  • A tool like curl or Postman to test your endpoints

Step 1: Set Up Your Environment

Start by creating a virtual environment and installing Flask:

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

Create a file named app.py in your project directory.

Step 2: Create the Basic Flask App

Add the following to app.py:

from flask import Flask, jsonify, request

app = Flask(__name__)

# In-memory data store
books = [
    {"id": 1, "title": "Clean Code", "author": "Robert C. Martin"},
    {"id": 2, "title": "The Pragmatic Programmer", "author": "David Thomas"},
]

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

if __name__ == '__main__':
    app.run(debug=True)

Run the app with python app.py and visit http://127.0.0.1:5000/books.

Step 3: Add Create and Read by ID

Extend your routes to handle POST requests and fetching a single item:

@app.route('/books/<int:book_id>', methods=['GET'])
def get_book(book_id):
    book = next((b for b in books if b["id"] == book_id), None)
    if book is None:
        return jsonify({"error": "Book not found"}), 404
    return jsonify(book), 200

@app.route('/books', methods=['POST'])
def add_book():
    data = request.get_json()
    if not data or "title" not in data or "author" not in data:
        return jsonify({"error": "Title and author required"}), 400
    new_book = {"id": len(books) + 1, "title": data["title"], "author": data["author"]}
    books.append(new_book)
    return jsonify(new_book), 201

Step 4: Add Update and Delete

Complete the CRUD surface with PUT and DELETE:

@app.route('/books/<int:book_id>', methods=['PUT'])
def update_book(book_id):
    book = next((b for b in books if b["id"] == book_id), None)
    if book is None:
        return jsonify({"error": "Book not found"}), 404
    data = request.get_json()
    book.update({k: v for k, v in data.items() if k in ("title", "author")})
    return jsonify(book), 200

@app.route('/books/<int:book_id>', methods=['DELETE'])
def delete_book(book_id):
    global books
    books = [b for b in books if b["id"] != book_id]
    return jsonify({"message": "Deleted"}), 200

Step 5: Test Your API

Use curl to test each endpoint:

  • GET all: curl http://127.0.0.1:5000/books
  • POST: curl -X POST -H "Content-Type: application/json" -d '{"title":"SICP","author":"Abelson"}' http://127.0.0.1:5000/books
  • DELETE: curl -X DELETE http://127.0.0.1:5000/books/1

Next Steps

This in-memory API is a great starting point. To take it further:

  1. Replace the in-memory list with a database (SQLite via Flask-SQLAlchemy)
  2. Add authentication with Flask-JWT-Extended
  3. Write automated tests using pytest
  4. Deploy to a cloud platform like Render, Railway, or Heroku

Building and iterating on small APIs like this is one of the fastest ways to develop backend confidence. Keep experimenting!