PYTHON

Generic Python API Wrapper for Consistent Interactions

Build a reusable Python class to encapsulate API interactions, handling base URLs, headers, and error responses for cleaner and more maintainable API integrations.

import requests
import json

class ApiWrapper:
    def __init__(self, base_url, api_key=None, default_headers=None):
        self.base_url = base_url.rstrip('/')
        self.headers = {'Content-Type': 'application/json'}
        if api_key:
            self.headers['Authorization'] = f'Bearer {api_key}'
        if default_headers:
            self.headers.update(default_headers)

    def _request(self, method, endpoint, params=None, data=None, json_data=None, headers=None):
        url = f"{self.base_url}/{endpoint.lstrip('/')}"
        request_headers = self.headers.copy()
        if headers:
            request_headers.update(headers)

        try:
            response = requests.request(
                method,
                url,
                params=params,
                data=data,
                json=json_data,
                headers=request_headers,
                timeout=10 # Add a timeout for robustness
            )
            response.raise_for_status() # Raise HTTPError for bad responses (4xx or 5xx)
            return response.json() if response.text else {}
        except requests.exceptions.HTTPError as e:
            try:
                error_details = e.response.json()
            except json.JSONDecodeError:
                error_details = e.response.text
            print(f"HTTP Error for {url}: {e.response.status_code} - {error_details}")
            raise
        except requests.exceptions.ConnectionError as e:
            print(f"Connection Error for {url}: {e}")
            raise
        except requests.exceptions.Timeout as e:
            print(f"Timeout Error for {url}: {e}")
            raise
        except requests.exceptions.RequestException as e:
            print(f"An unexpected error occurred for {url}: {e}")
            raise

    def get(self, endpoint, params=None, headers=None):
        return self._request('GET', endpoint, params=params, headers=headers)

    def post(self, endpoint, data=None, json_data=None, headers=None):
        return self._request('POST', endpoint, data=data, json_data=json_data, headers=headers)

    def put(self, endpoint, data=None, json_data=None, headers=None):
        return self._request('PUT', endpoint, data=data, json_data=json_data, headers=headers)

    def delete(self, endpoint, headers=None):
        return self._request('DELETE', endpoint, headers=headers)

# Example Usage:
# API_BASE_URL = "https://api.example.com"
# API_KEY = "your_secret_api_key"

# my_api = ApiWrapper(API_BASE_URL, api_key=API_KEY)

# try:
#     # Fetch users
#     users = my_api.get("/users", params={"limit": 5})
#     print("Users:", users)

#     # Create a new item
#     new_item = my_api.post("/items", json_data={"name": "New Widget", "price": 29.99})
#     print("New Item:", new_item)

#     # Update an item
#     updated_item = my_api.put("/items/123", json_data={"price": 34.99})
#     print("Updated Item:", updated_item)

# except Exception as e:
#     print(f"API interaction failed: {e}")
How it works: This Python `ApiWrapper` class provides a structured way to interact with an external REST API. It centralizes the base URL, default headers (like authentication tokens and content type), and robust error handling for various HTTP and network issues. By abstracting the `requests` library calls into `get`, `post`, `put`, and `delete` methods, it promotes consistency, reduces code duplication, and makes API integrations easier to manage and debug in a larger application.

Need help integrating this into your project?

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

Hire DigitalCodeLabs