0
0
Rest-apiHow-ToBeginner · 4 min read

REST API Design Best Practices for Clean and Efficient APIs

Use clear resource names with nouns, apply correct HTTP methods like GET, POST, PUT, DELETE, and return proper status codes to indicate success or errors. Keep APIs stateless, versioned, and consistent for easy use and maintenance.
📐

Syntax

A REST API uses HTTP methods to perform actions on resources identified by URLs. Common methods include:

  • GET to retrieve data
  • POST to create new data
  • PUT to update existing data
  • DELETE to remove data

Resources are named using plural nouns in URLs, e.g., /users or /products. APIs should be stateless, meaning each request contains all needed info.

http
GET /users          # Retrieve list of users
POST /users         # Create a new user
GET /users/123      # Retrieve user with ID 123
PUT /users/123      # Update user with ID 123
DELETE /users/123   # Delete user with ID 123
💻

Example

This example shows a simple REST API design for managing books. It uses proper HTTP methods, resource naming, and status codes.

python
from flask import Flask, jsonify, request, abort

app = Flask(__name__)

books = [
    {"id": 1, "title": "1984", "author": "George Orwell"},
    {"id": 2, "title": "To Kill a Mockingbird", "author": "Harper Lee"}
]

@app.route('/books', methods=['GET'])
def get_books():
    return jsonify(books), 200

@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:
        abort(404)
    return jsonify(book), 200

@app.route('/books', methods=['POST'])
def create_book():
    if not request.json or 'title' not in request.json or 'author' not in request.json:
        abort(400)
    new_book = {
        'id': books[-1]['id'] + 1 if books else 1,
        'title': request.json['title'],
        'author': request.json['author']
    }
    books.append(new_book)
    return jsonify(new_book), 201

@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:
        abort(404)
    if not request.json:
        abort(400)
    book['title'] = request.json.get('title', book['title'])
    book['author'] = request.json.get('author', book['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 '', 204

if __name__ == '__main__':
    app.run(debug=True)
Output
Running Flask server on http://127.0.0.1:5000/
⚠️

Common Pitfalls

Common mistakes include:

  • Using verbs in URLs instead of nouns, e.g., /getUser instead of /users.
  • Ignoring proper HTTP status codes, like always returning 200 even on errors.
  • Not versioning the API, which breaks clients when changes occur.
  • Making APIs stateful, requiring session info on the server.
http
Wrong:
GET /getUser?id=123
Response: 200 OK with error message

Right:
GET /users/123
Response: 404 Not Found if user missing
📊

Quick Reference

Best PracticeDescription
Use nouns for resourcesName endpoints with plural nouns like /users, /orders
Use correct HTTP methodsGET for read, POST for create, PUT for update, DELETE for delete
Return proper status codes200 OK, 201 Created, 400 Bad Request, 404 Not Found, 500 Server Error
Keep APIs statelessEach request must contain all info, no server session
Version your APIUse /v1/, /v2/ in URLs to manage changes

Key Takeaways

Use clear, plural noun resource names in URLs for consistency.
Apply correct HTTP methods to match the action on resources.
Return appropriate HTTP status codes to communicate results.
Keep APIs stateless to simplify client-server interaction.
Version your API to avoid breaking changes for users.