REST APIs with Flask: Build a JSON API in 30 Minutes
Flask is excellent for REST APIs. Here's how to build one that's actually production-ready.
Setup
pip install flask flask-cors
Application Structure
from flask import Flask, jsonify, request, abort
from flask_cors import CORS
import sqlite3
app = Flask(__name__)
CORS(app) # allow cross-origin requests
def get_db():
db = sqlite3.connect('api.db')
db.row_factory = sqlite3.Row
return db
CRUD Endpoints
# GET /api/v1/posts
@app.route('/api/v1/posts')
def list_posts():
page = request.args.get('page', 1, type=int)
per_page = min(request.args.get('per_page', 10, type=int), 100)
offset = (page - 1) * per_page
db = get_db()
posts = db.execute(
'SELECT * FROM posts ORDER BY created_at DESC LIMIT ? OFFSET ?',
(per_page, offset)
).fetchall()
total = db.execute('SELECT COUNT(*) FROM posts').fetchone()[0]
return jsonify({
'data': [dict(p) for p in posts],
'meta': {'page': page, 'per_page': per_page, 'total': total},
})
# GET /api/v1/posts/<id>
@app.route('/api/v1/posts/<int:post_id>')
def get_post(post_id):
post = get_db().execute(
'SELECT * FROM posts WHERE id=?', (post_id,)
).fetchone()
if not post:
return jsonify({'error': 'Not found'}), 404
return jsonify(dict(post))
# POST /api/v1/posts
@app.route('/api/v1/posts', methods=['POST'])
def create_post():
data = request.get_json(silent=True) or {}
title = data.get('title', '').strip()
body = data.get('body', '').strip()
if not title or not body:
return jsonify({'error': 'title and body are required'}), 422
db = get_db()
cur = db.execute(
'INSERT INTO posts (title, body) VALUES (?,?)', (title, body)
)
db.commit()
return jsonify({'id': cur.lastrowid, 'title': title}), 201
# DELETE /api/v1/posts/<id>
@app.route('/api/v1/posts/<int:post_id>', methods=['DELETE'])
def delete_post(post_id):
db = get_db()
db.execute('DELETE FROM posts WHERE id=?', (post_id,))
db.commit()
return '', 204
API Key Authentication
import functools
VALID_KEYS = {'sk-test-abc123', 'sk-prod-xyz789'}
def require_api_key(f):
@functools.wraps(f)
def wrapper(*args, **kwargs):
key = request.headers.get('X-API-Key') or request.args.get('api_key')
if key not in VALID_KEYS:
return jsonify({'error': 'Unauthorized'}), 401
return f(*args, **kwargs)
return wrapper
# Apply to protected routes:
@app.route('/api/v1/posts', methods=['POST'])
@require_api_key
def create_post():
...
Error Handling
@app.errorhandler(404)
def not_found(e):
return jsonify({'error': 'Resource not found'}), 404
@app.errorhandler(405)
def method_not_allowed(e):
return jsonify({'error': 'Method not allowed'}), 405
Your API is now ready to power a mobile app, a frontend SPA, or integrate with third-party services.
0 Comments
Join the conversation
No comments yet. Be the first!