Flask REST APIs & JSON

🌐 REST method conventions

MethodMeaningExample
GETretrieveGET /api/users
POSTcreatePOST /api/users
PUTreplace entirelyPUT /api/users/42
PATCHpartial updatePATCH /api/users/42
DELETEremoveDELETE /api/users/42

πŸ—οΈ Basic CRUD

from flask import jsonify, request, abort
 
@app.route("/api/users", methods=["GET"])
def get_users():
    return jsonify(users)
 
@app.route("/api/users/<int:user_id>", methods=["GET"])
def get_user(user_id):
    user = next((u for u in users if u["id"] == user_id), None)
    if user is None:
        abort(404)
    return jsonify(user)
 
@app.route("/api/users", methods=["POST"])
def create_user():
    data = request.get_json()
    if not data or "name" not in data:
        return jsonify({"error": "name required"}), 400
    new_user = {"id": len(users)+1, "name": data["name"]}
    users.append(new_user)
    return jsonify(new_user), 201    # 201 = Created, return the new resource
 
@app.route("/api/users/<int:user_id>", methods=["DELETE"])
def delete_user(user_id):
    global users
    users = [u for u in users if u["id"] != user_id]
    return "", 204    # 204 = No Content

πŸ—„οΈ With SQLAlchemy model

@app.route("/api/users/<int:user_id>")
def get_user(user_id):
    user = User.query.get_or_404(user_id)
    return jsonify(user.to_dict())
 
class User(db.Model):
    def to_dict(self):
        return {"id": self.id, "username": self.username, "email": self.email}

to_dict() on the model = control exactly what's exposed (keep password_hash out).

πŸ“š Marshmallow (structured serialization, bigger APIs)

pip install flask-marshmallow marshmallow-sqlalchemy
from flask_marshmallow import Marshmallow
ma = Marshmallow(app)
 
class UserSchema(ma.SQLAlchemyAutoSchema):
    class Meta:
        model = User
        load_instance = True
 
users_schema = UserSchema(many=True)
return jsonify(users_schema.dump(users))

πŸ”‘ Token auth

from functools import wraps
 
def require_api_key(f):
    @wraps(f)
    def wrapper(*a, **kw):
        if request.headers.get("X-API-Key") != "expected-key":
            return jsonify({"error": "Invalid API key"}), 401
        return f(*a, **kw)
    return wrapper
 
@app.route("/api/protected")
@require_api_key
def protected():
    return jsonify({"message": "access granted"})

Real production APIs typically use JWT ( flask-jwt-extended) instead of a shared key.

🌍 CORS

pip install flask-cors
from flask_cors import CORS
CORS(app)                                       # any origin β€” dev only
CORS(app, origins=["https://myfrontend.com"])       # restricted β€” production

πŸ”— Next

Flask Error Handling & Logging Β· Flask Testing & Deployment