Practical examples of creating RESTful APIs with Flask in 2025
Fast-start example of a minimal Flask REST API
Let’s start with the smallest possible example of creating RESTful APIs with Flask that still looks like something you’d use in a real codebase. This is a tiny notes API with in‑memory storage:
from flask import Flask, request, jsonify, abort
app = Flask(__name__)
notes = [] # in-memory store
@app.route("/notes", methods=["GET"])
def list_notes():
return jsonify(notes), 200
@app.route("/notes", methods=["POST"])
def create_note():
data = request.get_json() or {}
if "text" not in data:
abort(400, description="'text' field is required")
note = {"id": len(notes) + 1, "text": data["text"]}
notes.append(note)
return jsonify(note), 201
if __name__ == "__main__":
app.run(debug=True)
This tiny snippet already shows the core pattern behind many examples of creating RESTful APIs with Flask:
- Use
@app.routewith HTTP methods to define resources. - Accept and validate JSON with
request.get_json(). - Return JSON consistently via
jsonifyand proper HTTP status codes.
From here, every other example of a Flask REST API is just layering on structure: blueprints, databases, authentication, background jobs, and rate limiting.
Real examples of creating RESTful APIs with Flask for CRUD data
Most developers start with a simple CRUD API. Here’s a more realistic example of a task manager API using SQLAlchemy and blueprints. This is one of the best examples of how people actually structure Flask projects in 2024.
from flask import Flask, Blueprint, request, jsonify, abort
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///tasks.db"
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
db = SQLAlchemy(app)
tasks_bp = Blueprint("tasks", __name__, url_prefix="/api/tasks")
class Task(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(120), nullable=False)
done = db.Column(db.Boolean, default=False)
def to_dict(self):
return {"id": self.id, "title": self.title, "done": self.done}
@tasks_bp.route("", methods=["GET"])
def get_tasks():
tasks = Task.query.all()
return jsonify([t.to_dict() for t in tasks]), 200
@tasks_bp.route("", methods=["POST"])
def create_task():
data = request.get_json() or {}
title = data.get("title")
if not title:
abort(400, description="'title' is required")
task = Task(title=title)
db.session.add(task)
db.session.commit()
return jsonify(task.to_dict()), 201
@tasks_bp.route("/<int:task_id>", methods=["PATCH"])
def update_task(task_id):
task = Task.query.get_or_404(task_id)
data = request.get_json() or {}
if "title" in data:
task.title = data["title"]
if "done" in data:
task.done = bool(data["done"])
db.session.commit()
return jsonify(task.to_dict()), 200
@tasks_bp.route("/<int:task_id>", methods=["DELETE"])
def delete_task(task_id):
task = Task.query.get_or_404(task_id)
db.session.delete(task)
db.session.commit()
return "", 204
app.register_blueprint(tasks_bp)
if __name__ == "__main__":
with app.app_context():
db.create_all()
app.run(debug=True)
This example of a CRUD API covers patterns you’ll re‑use constantly:
- Blueprints for modular routing (
/api/tasks). - SQLAlchemy models with
to_dict()methods. PATCHfor partial updates, which aligns with API design guidance from organizations like the U.S. Digital Service.
When people ask for real examples of creating RESTful APIs with Flask, this kind of endpoint set is usually what they mean.
Examples include pagination and filtering for real-world datasets
Once your API handles more than a few dozen records, pagination and filtering stop being optional. Here’s a focused example of adding pagination to the tasks API:
from flask import request, jsonify
@app.route("/api/tasks-paged", methods=["GET"])
def get_tasks_paged():
page = request.args.get("page", default=1, type=int)
per_page = request.args.get("per_page", default=20, type=int)
query = Task.query
# # Optional filtering
done = request.args.get("done")
if done is not None:
query = query.filter_by(done=(done.lower() == "true"))
pagination = query.paginate(page=page, per_page=per_page, error_out=False)
return jsonify({
"items": [t.to_dict() for t in pagination.items],
"page": pagination.page,
"per_page": pagination.per_page,
"total": pagination.total
}), 200
This is a practical example of creating RESTful APIs with Flask that behave well under load. By returning page, per_page, and total, you make client‑side UI work much easier.
For API design standards and pagination patterns, the GSA API Standards are worth a read; they influence how many U.S. government APIs behave.
JWT authentication: a security-focused example of a Flask REST API
In 2024–2025, almost every serious API needs token‑based authentication. Here’s a compact example of using JSON Web Tokens (JWT) with Flask. This uses the flask-jwt-extended extension, which is still widely used.
from datetime import timedelta
from flask import Flask, request, jsonify
from flask_jwt_extended import (
JWTManager, create_access_token,
jwt_required, get_jwt_identity
)
app = Flask(__name__)
app.config["JWT_SECRET_KEY"] = "change-me-in-production"
app.config["JWT_ACCESS_TOKEN_EXPIRES"] = timedelta(hours=1)
jwt = JWTManager(app)
USERS = {"alice": "password123"}
@app.route("/auth/login", methods=["POST"])
def login():
data = request.get_json() or {}
username = data.get("username")
password = data.get("password")
if USERS.get(username) != password:
return jsonify({"msg": "Bad username or password"}), 401
token = create_access_token(identity=username)
return jsonify(access_token=token), 200
@app.route("/auth/profile", methods=["GET"])
@jwt_required()
def profile():
current_user = get_jwt_identity()
return jsonify(user=current_user), 200
This example of a secure RESTful API endpoint with Flask shows how you can:
- Issue short‑lived access tokens.
- Protect routes with
@jwt_required(). - Attach user identity to requests without session cookies.
If you’re building health‑related APIs, you’ll also want to look at security guidance from sources like the Office for Civil Rights at HHS, since HIPAA‑aligned systems lean heavily on authenticated, auditable APIs.
Background jobs and async workflows: real examples of Flask APIs in production
Sometimes your API needs to kick off long‑running work: video processing, AI inference, or bulk data imports. A common pattern is to use Flask as the front door and Celery or RQ for background jobs.
Here’s a trimmed‑down example of creating RESTful APIs with Flask that trigger background tasks using RQ and Redis:
import time
import redis
from rq import Queue
from flask import Flask, jsonify
app = Flask(__name__)
redis_conn = redis.Redis(host="localhost", port=6379)
queue = Queue("default", connection=redis_conn)
def long_running_job(x):
time.sleep(10) # simulate heavy work
return x * 2
@app.route("/jobs", methods=["POST"])
def create_job():
job = queue.enqueue(long_running_job, 21)
return jsonify({"job_id": job.get_id()}), 202
@app.route("/jobs/<job_id>", methods=["GET"])
def get_job(job_id):
from rq.job import Job
job = Job.fetch(job_id, connection=redis_conn)
return jsonify({
"id": job.get_id(),
"status": job.get_status(),
"result": job.result
}), 200
This pattern shows up in many best examples of Flask APIs in production, because it keeps the HTTP layer fast and pushes heavy lifting into workers.
Versioning and blueprints: examples include multi-version APIs
Real APIs live for years. That means versioning. Here’s a small example of organizing v1 and v2 endpoints with blueprints:
from flask import Flask, Blueprint, jsonify
app = Flask(__name__)
v1 = Blueprint("v1", __name__, url_prefix="/api/v1")
v2 = Blueprint("v2", __name__, url_prefix="/api/v2")
@v1.route("/status")
def status_v1():
return jsonify({"status": "ok", "version": 1}), 200
@v2.route("/status")
def status_v2():
return jsonify({"status": "ok", "version": 2, "features": ["metrics"]}), 200
app.register_blueprint(v1)
app.register_blueprint(v2)
This example of API versioning with Flask is intentionally simple, but the pattern scales. As your API grows, you can split each version into its own package and migrate clients gradually.
Standards like the NIST Secure Software Development Framework emphasize lifecycle thinking; versioned APIs are one practical way to apply that mindset.
JSON schema validation: examples of safer input handling
Another pattern that shows up in better examples of creating RESTful APIs with Flask is explicit input validation. Instead of manually checking every field, you can use marshmallow or similar libraries.
Here’s a short example using marshmallow to validate a user signup payload:
from flask import Flask, request, jsonify
from marshmallow import Schema, fields, ValidationError
app = Flask(__name__)
class SignupSchema(Schema):
email = fields.Email(required=True)
password = fields.Str(required=True, validate=lambda p: len(p) >= 8)
signup_schema = SignupSchema()
@app.errorhandler(ValidationError)
def handle_validation_error(err):
return jsonify({"errors": err.messages}), 400
@app.route("/auth/signup", methods=["POST"])
def signup():
data = request.get_json() or {}
valid = signup_schema.load(data)
# # create user here
return jsonify({"email": valid["email"]}), 201
This style of validation makes your API behavior easier to reason about, and it’s the kind of detail that separates toy examples of Flask APIs from code you’d trust in production.
OpenAPI and documentation: an example of self-describing Flask APIs
By 2025, clients expect well-documented APIs with machine‑readable specs. Flask plays nicely with tools that generate OpenAPI (Swagger) definitions.
Here’s a minimal example using flask-smorest to auto‑generate OpenAPI docs:
from flask import Flask
from flask_smorest import Api, Blueprint
app = Flask(__name__)
app.config["API_TITLE"] = "Books API"
app.config["API_VERSION"] = "v1"
app.config["OPENAPI_VERSION"] = "3.0.3"
api = Api(app)
blp = Blueprint("books", "books", url_prefix="/books", description="Books operations")
@blp.route("")
class BooksResource:
@blp.response(200)
def get(self):
"""List books"""
return []
api.register_blueprint(blp)
Run this, and you’ll get interactive documentation at /swagger-ui (or similar, depending on configuration). Among all the examples of creating RESTful APIs with Flask, this is one that pays off immediately: developers can explore and test endpoints without reading your source code.
Trends for Flask REST APIs in 2024–2025
Looking across these examples of creating RESTful APIs with Flask, a few trends stand out in current projects:
- Microservices and containers: Teams often run multiple small Flask APIs in Docker, fronted by an API gateway.
- Typed Python: More codebases use type hints plus tools like
mypyto catch API contract issues early. - Security hardening: JWTs, OAuth2, rate limiting, and strict CORS settings are now standard rather than nice‑to‑have.
- Observability: Logging, tracing, and metrics (via tools like OpenTelemetry) are wired into APIs from day one.
If you’re building anything that touches regulated data (health, finance, education), it’s worth skimming guidance from places like HealthIT.gov or your country’s digital service for expectations around API reliability and privacy.
The bottom line: the best examples of creating RESTful APIs with Flask in 2025 don’t just show @app.route and jsonify. They show structure, validation, authentication, and documentation—exactly the patterns you’ve seen in the examples above.
FAQ: examples of common questions about Flask REST APIs
Q: What is a simple example of creating RESTful APIs with Flask for beginners?
A straightforward starting point is a single‑file app that exposes a /items endpoint with GET and POST, stores data in memory, and returns JSON using jsonify. The first code sample in this article is exactly that style of beginner‑friendly example.
Q: How do I secure a Flask REST API with tokens?
Use a library like flask-jwt-extended to issue JWT access tokens on login, then protect sensitive routes with @jwt_required(). The JWT example of a Flask API above shows the core pattern, including token expiration and identity lookup.
Q: Are there production-grade examples of Flask APIs using databases?
Yes. Many teams pair Flask with SQLAlchemy or PostgreSQL clients. The task manager example in this guide demonstrates a realistic CRUD pattern with a Task model, migrations via db.create_all(), and HTTP verbs mapped to database operations.
Q: Can Flask handle real-time or high-traffic APIs?
Flask itself is synchronous, but it runs well behind WSGI servers like Gunicorn or uWSGI and can scale horizontally with load balancers. For heavy workloads or real‑time features, teams often combine Flask with message queues, background workers, or async services for the hottest paths.
Q: Where can I find more examples of well-designed REST APIs?
You can study public government and research APIs, which often publish standards and example implementations. The GSA API Standards and related U.S. government API guidelines are good references, even if you’re not building civic tech.
Related Topics
Examples of User Authentication in Flask: 3 Practical Patterns You’ll Actually Use
Best real-world examples of Flask-Migrate database migration examples
Practical examples of Flask-CORS: Handling Cross-Origin Requests
Flask Forms Made Human: How Data Really Moves From Browser to Python
Practical examples of creating RESTful APIs with Flask in 2025
Best examples of 3 practical examples of creating a basic Flask application
Explore More Flask Code Snippets
Discover more examples and insights in this category.
View All Flask Code Snippets