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:
- Replace the in-memory list with a database (SQLite via Flask-SQLAlchemy)
- Add authentication with Flask-JWT-Extended
- Write automated tests using pytest
- 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!