REST API Communication

REST (Representational State Transfer) is an architectural style for designing web services. A REST API is an application programming interface that conforms to the design principles of REST. REST APIs provide a lightweight way to build web APIs and are commonly used to exchange data between applications, web services and databases. In a RESTful design the client and server are decoupled; the client only needs to know the URI of the resource and the server is responsible for processing the request.

REST design principles

A well‑designed REST API adheres to several architectural constraints:

  • Uniform interface – each resource is identified by a URI and all requests for the same resource look the same.
  • Client/server decoupling – the client and server operate independently; the client should not know anything about how the server is implemented.
  • Statelessness – each HTTP request contains all information necessary to process it; no client context is stored on the server.
  • Cacheability – responses can be labeled as cacheable to improve performance.
  • Layered system – requests may pass through multiple layers (such as proxies or load balancers) but the client cannot tell whether it communicates with the end server or an intermediary.

HTTP defines verbs such as GET, POST, PUT, DELETE, etc. These verbs have different properties. For example, GET and PUT are idempotent—issuing the same request multiple times has the same effect—whereas POST is not. In a REST API, GET is used to read data, POST to create new resources, PUT to update resources, and DELETE to remove them.

Install packages

To build a REST API in Python you need a web framework for the server and a client library for sending HTTP requests. Use Flask to create a simple server and requests to act as an HTTP client.

pip install flask requests

REST server with Flask

The following script implements a minimal REST API that manages key–value pairs. It defines endpoints for the HTTP verbs GET, POST, PUT and DELETE. Run the script to start the server on port 5000.

from flask import Flask, request, jsonify

app = Flask(__name__)

# in‑memory store for demonstration
items = {}

@app.route('/items/<key>', methods=['GET'])
def get_item(key):
    """Return the value for a given key or a 404 error."""
    if key not in items:
        return jsonify({'error': 'Not found'}), 404
    return jsonify({'value': items[key]})

@app.route('/items/<key>', methods=['POST'])
def create_item(key):
    """Create a new item; returns 201 on success."""
    data = request.get_json()
    items[key] = data['value']
    return jsonify({'message': 'Item created'}), 201

@app.route('/items/<key>', methods=['PUT'])
def update_item(key):
    """Update an existing item or create it if missing."""
    data = request.get_json()
    items[key] = data['value']
    return jsonify({'message': 'Item updated'})

@app.route('/items/<key>', methods=['DELETE'])
def delete_item(key):
    """Delete an existing item."""
    if key in items:
        del items[key]
        return jsonify({'message': 'Item deleted'})
    return jsonify({'error': 'Not found'}), 404

if __name__ == '__main__':
    app.run(port=5000)

REST client with requests

Use the requests library to interact with the API. The following example sends POST, GET, PUT and DELETE requests against the /items/<key> endpoint.

import requests

base_url = "http://localhost:5000/items"

# Create a new item
resp = requests.post(f"{base_url}/username", json={'value': 'Alice'})
print('POST:', resp.status_code, resp.json())

# Retrieve the item
resp = requests.get(f"{base_url}/username")
print('GET:', resp.status_code, resp.json())

# Update the item
resp = requests.put(f"{base_url}/username", json={'value': 'Bob'})
print('PUT:', resp.status_code, resp.json())

# Delete the item
resp = requests.delete(f"{base_url}/username")
print('DELETE:', resp.status_code, resp.json())

✅ Activity

Develop a RESTful API for managing a simple to‑do list. The server should support adding new tasks (POST), listing all tasks (GET), updating a task’s completion status (PUT), and deleting tasks (DELETE). Each task can have a unique identifier, a description and a Boolean flag indicating whether it is complete.

  • Server: Use Flask to implement the /tasks resource. Store tasks in a dictionary (or list) with a task ID as the key. Implement endpoints for GET /tasks (list all tasks), POST /tasks/<id> (create a task with a JSON payload containing a description), PUT /tasks/<id> (update the completion status), and DELETE /tasks/<id> (delete a task).
from flask import Flask, request, jsonify

app = Flask(__name__)
tasks = {}  # {id: {'description': str, 'complete': bool}}

@app.route('/tasks', methods=['GET'])
def list_tasks():
    return jsonify(list(tasks.values()))

@app.route('/tasks/<task_id>', methods=['POST'])
def add_task(task_id):
    data = request.get_json()
    tasks[task_id] = {'id': task_id, 'description': data['description'], 'complete': False}
    return jsonify({'message': 'Task added'}), 201

@app.route('/tasks/<task_id>', methods=['PUT'])
def update_task(task_id):
    if task_id in tasks:
        data = request.get_json()
        tasks[task_id]['complete'] = data.get('complete', tasks[task_id]['complete'])
        return jsonify({'message': 'Task updated'})
    return jsonify({'error': 'Task not found'}), 404

@app.route('/tasks/<task_id>', methods=['DELETE'])
def delete_task(task_id):
    if task_id in tasks:
        del tasks[task_id]
        return jsonify({'message': 'Task deleted'})
    return jsonify({'error': 'Task not found'}), 404

if __name__ == '__main__':
    app.run(port=5001)
  • Client: Write a Python script that sends requests to your API to add a task, mark it complete and retrieve the task list. Print the JSON responses to the console.
import requests

base = 'http://localhost:5001/tasks'

# Add tasks
requests.post(f'{base}/task1', json={'description': 'Learn REST APIs'})
requests.post(f'{base}/task2', json={'description': 'Build a Flask server'})

# Mark task1 complete
requests.put(f'{base}/task1', json={'complete': True})

# List all tasks
resp = requests.get(base)
print('All tasks:', resp.json())

# Delete task2
requests.delete(f'{base}/task2')

# List again
resp = requests.get(base)
print('Remaining tasks:', resp.json())

✅ Knowledge Check

1. Which HTTP method is idempotent and should be used to update an existing resource without creating a duplicate?

A. POST
Incorrect. POST is used to create new resources and is not idempotent; sending the same POST multiple times creates multiple resources or side effects.
B. PUT
Correct. PUT is idempotent — sending the same PUT request repeatedly results in the same state because the resource is fully replaced.
C. DELETE
Incorrect. Although DELETE is idempotent, its purpose is to remove resources, not update them.
D. PATCH
Incorrect. PATCH modifies resources but is not guaranteed to be idempotent.

2. According to REST architectural constraints, where is client state stored?

A. On the server, in session variables.
Incorrect. REST APIs are stateless: each request contains all necessary information and the server does not store client state.
B. In hidden cookies managed by the server.
Incorrect. Statelessness means the server does not rely on hidden cookies to track client context.
C. In the client request itself.
Correct. Each REST request must include all information necessary to process it; servers do not retain client state between requests.
D. In a shared cache across clients.
Incorrect. Caching improves performance, but the authoritative state of the resource is stored on the server, not in a shared client cache.

Course on GitHub

Python

Access

Communicate

Electrical

Series

Data Engineering

Applications

Text OCR 👁️
Generative AI 🗣️
Humidity 📐
👁️=Computer Vision
⚙️=Actuators
⏱️=Time Series
🗣️=Language
🔊=Audio
📈=Regression
📊=Classification
📐=Sensors

Related Courses

Admin

Streaming Chatbot
💬