Labs ICT
Pro Login

REST APIs

Building JSON APIs with Flask.

REST APIs

Not every Flask app needs to serve HTML pages. Sometimes you just want to send and receive data — that's where REST APIs come in. Your Flask app becomes a backend that mobile apps, JavaScript frontends, or other services can talk to. JSON is the language of APIs.

JSON Responses with jsonify

Flask gives you jsonify() to convert Python dictionaries into proper JSON responses with the right content type header.

from flask import jsonify

@app.route('/api/users')
def get_users():
    users = User.query.all()
    users_list = [{'id': u.id, 'username': u.username, 'email': u.email}
                  for u in users]
    return jsonify(users=users_list)

The jsonify() function handles serialization, sets the Content-Type: application/json header, and returns a proper Response object. You can also pass a list directly or wrap multiple values in a dictionary.

API Route Design

Good API routes are predictable. Use nouns for resources and HTTP methods for actions. GET to read, POST to create, PUT to update, DELETE to remove.

@app.route('/api/posts', methods=['GET', 'POST'])
def posts():
    if request.method == 'GET':
        # Return all posts
        pass
    elif request.method == 'POST':
        # Create a new post
        pass

@app.route('/api/posts/<int:id>', methods=['GET', 'PUT', 'DELETE'])
def post(id):
    if request.method == 'GET':
        # Return single post
        pass
    elif request.method == 'PUT':
        # Update post
        pass
    elif request.method == 'DELETE':
        # Delete post
        pass

HTTP Status Codes

Status codes tell the client what happened. Don't always return 200 — use the right code for the situation.

@app.route('/api/users/<int:id>')
def get_user(id):
    user = User.query.get(id)
    if user is None:
        return jsonify({'error': 'User not found'}), 404
    return jsonify({'id': user.id, 'username': user.username}), 200

@app.route('/api/users', methods=['POST'])
def create_user():
    data = request.get_json()
    if not data or 'username' not in data:
        return jsonify({'error': 'Username required'}), 400

    user = User(username=data['username'], email=data.get('email', ''))
    db.session.add(user)
    db.session.commit()
    return jsonify({'id': user.id, 'username': user.username}), 201

Common codes: 200 OK, 201 Created, 400 Bad Request, 401 Unauthorized, 404 Not Found, 500 Server Error. Clients rely on these to know how to handle the response.

Reading JSON Input

Use request.get_json() to parse JSON from the request body. It returns a Python dictionary or None if the body isn't valid JSON.

data = request.get_json()
username = data.get('username')
email = data.get('email')

API Authentication

Most APIs need some form of authentication. Token-based auth is common — the client sends a token in the request header, and you verify it on the server.

from functools import wraps

def token_required(f):
    @wraps(f)
    def decorated(*args, **kwargs):
        token = request.headers.get('Authorization')
        if not token or not verify_token(token):
            return jsonify({'error': 'Invalid token'}), 401
        return f(*args, **kwargs)
    return decorated

@app.route('/api/profile')
@token_required
def profile():
    return jsonify({'message': 'Authenticated!'})

CORS Headers

If your API is accessed from a different domain (like a React frontend on localhost:3000 calling a Flask API on localhost:5000), you need CORS headers. The Flask-CORS extension makes this easy.

from flask_cors import CORS

app = Flask(__name__)
CORS(app)  # Enables CORS for all routes

Why REST APIs Are Essential

REST APIs separate your frontend from your backend. Your Flask app becomes a data service that any client — web, mobile, IoT device — can consume. It's the foundation of modern web development and opens up your app to a much wider world.

Try it Yourself ->