PYTHON

Building a Reusable Python API Client

Create a robust and reusable Python class to interact with a RESTful API, encapsulating requests, error handling, and common patterns for cleaner integrations.

import requests
import os

class MyApiClient:
    def __init__(self, base_url, api_key_env_var='MY_API_KEY'):
        self.base_url = base_url
        self.api_key = os.getenv(api_key_env_var)
        if not self.api_key:
            raise ValueError(f"API key environment variable '{api_key_env_var}' not set.")
        self.headers = {
            'Authorization': f'Bearer {self.api_key}',
            'Content-Type': 'application/json',
            'Accept': 'application/json'
        }

    def _request(self, method, endpoint, params=None, data=None, json=None):
        url = f"{self.base_url}/{endpoint.lstrip('/')}"
        try:
            response = requests.request(
                method,
                url,
                headers=self.headers,
                params=params,
                data=data,
                json=json,
                timeout=10 # Set a timeout for requests
            )
            response.raise_for_status() # Raises HTTPError for bad responses (4xx or 5xx)
            return response.json()
        except requests.exceptions.HTTPError as e:
            print(f"HTTP Error: {e.response.status_code} - {e.response.text}")
            raise
        except requests.exceptions.ConnectionError as e:
            print(f"Connection Error: {e}")
            raise
        except requests.exceptions.Timeout as e:
            print(f"Timeout Error: {e}")
            raise
        except requests.exceptions.RequestException as e:
            print(f"Request Error: {e}")
            raise

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

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

    def put(self, endpoint, json=None):
        return self._request('PUT', endpoint, json=json)

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

# --- Example Usage ---
if __name__ == "__main__":
    # Set a dummy API key for testing (in real app, use environment variables)
    os.environ['MY_API_KEY'] = 'your_super_secret_api_key'

    try:
        client = MyApiClient(base_url='https://jsonplaceholder.typicode.com')

        # Get a post
        post = client.get('/posts/1')
        print("Fetched Post:", post)

        # Create a new post
        new_post_data = {'title': 'foo', 'body': 'bar', 'userId': 1}
        created_post = client.post('/posts', json=new_post_data)
        print("Created Post:", created_post)

        # Simulate an error
        # This would raise an exception due to 404
        # client.get('/nonexistent-endpoint')

    except ValueError as e:
        print(f"Configuration Error: {e}")
    except requests.exceptions.RequestException as e:
        print(f"API Client Error: {e}")
How it works: This Python class provides a structured way to interact with a RESTful API. It initializes with a base URL and an API key retrieved from environment variables for security. The `_request` method handles common HTTP request logic, including setting headers, timeouts, and robust error handling using `requests.exceptions`. It then exposes convenient methods like `get`, `post`, `put`, and `delete`, making API interactions clean and consistent throughout your application.

Need help integrating this into your project?

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

Hire DigitalCodeLabs