PYTHON

Ensuring Idempotency for API Requests with a Unique Key

Learn to implement idempotency for your API endpoints using a unique request key, preventing duplicate processing of requests even when clients retry.

from flask import Flask, request, jsonify, g
import uuid
import time

app = Flask(__name__)

# In a real application, this would be a persistent store (e.g., Redis, database)
# Storing (idempotency_key -> response_data) for a short period
idempotency_store = {}
IDEMPOTENCY_EXPIRY_SECONDS = 3600 # 1 hour

def get_idempotent_response(idempotency_key):
    record = idempotency_store.get(idempotency_key)
    if record and (time.time() - record['timestamp'] < IDEMPOTENCY_EXPIRY_SECONDS):
        return record['response']
    return None

def store_idempotent_response(idempotency_key, response_data):
    idempotency_store[idempotency_key] = {
        'timestamp': time.time(),
        'response': response_data
    }

@app.route('/create_resource', methods=['POST'])
def create_resource():
    idempotency_key = request.headers.get('X-Idempotency-Key')

    if not idempotency_key:
        return jsonify({"error": "X-Idempotency-Key header is required"}), 400

    # 1. Check if this request has been processed recently
    cached_response = get_idempotent_response(idempotency_key)
    if cached_response:
        print(f"Returning cached response for idempotency key: {idempotency_key}")
        return jsonify(cached_response)

    # 2. Process the request (simulate creation)
    try:
        data = request.get_json()
        if not data or 'name' not in data:
            return jsonify({"error": "Name is required"}), 400

        # Simulate database operation
        new_resource_id = str(uuid.uuid4())
        resource_data = {"id": new_resource_id, "name": data['name'], "status": "created"}
        print(f"Resource created: {resource_data}")

        # 3. Store the successful response
        store_idempotent_response(idempotency_key, resource_data)

        return jsonify(resource_data), 201
    except Exception as e:
        # Handle potential errors during processing, don't cache errors for idempotency
        return jsonify({"error": str(e)}), 500

# if __name__ == '__main__':
#     app.run(debug=True)
How it works: This Python Flask snippet illustrates how to implement idempotency for API endpoints, particularly for mutation operations like creating resources. Clients send a unique `X-Idempotency-Key` header with their request. The server first checks if a response for that key is already cached. If so, it returns the cached response, preventing duplicate processing. If not, it proceeds to process the request (e.g., create a resource) and then stores the successful response with the idempotency key before sending it back. This ensures that even if a client retries a request due to network issues, the operation is performed only once.

Need help integrating this into your project?

Our team of expert developers can help you build your custom application from scratch.

Hire DigitalCodeLabs