{"id":9476,"library":"apiclient","title":"apiclient","description":"apiclient is a simple, lightweight Python framework for building API clients for REST-like services, leveraging `urllib3` for HTTP requests. It provides decorators for defining API endpoints and handles the boilerplate of request building and response processing. The current version is 1.0.4, with recent minor updates indicating active maintenance.","status":"active","version":"1.0.4","language":"en","source_language":"en","source_url":"https://github.com/shazow/apiclient","tags":["api client","http","urllib3","framework","rest"],"install":[{"cmd":"pip install apiclient","lang":"bash","label":"Install stable version"}],"dependencies":[{"reason":"Core HTTP client library used by apiclient.","package":"urllib3","optional":false}],"imports":[{"symbol":"APIClient","correct":"from apiclient import APIClient"},{"symbol":"endpoint","correct":"from apiclient import endpoint"}],"quickstart":{"code":"import os\nfrom apiclient import APIClient, endpoint\nimport urllib3.exceptions # Import for specific error handling\n\nclass GitHubClient(APIClient):\n    @endpoint\n    def get_user_repos(self, username: str):\n        # The 'get' method returns a apiclient._response.ResponseWrapper object\n        return self.get(f'/users/{username}/repos')\n\n# Initialize the client. For authentication, pass headers.\n# Use os.environ.get for an example of token usage.\ntoken = os.environ.get('GITHUB_TOKEN', '')\nheaders = {'Authorization': f'token {token}'} if token else {}\nclient = GitHubClient(base_url='https://api.github.com', headers=headers)\n\ntry:\n    # Call the endpoint. The wrapped urllib3 response is returned.\n    response = client.get_user_repos(username='shazow')\n\n    # apiclient returns wrapped urllib3 responses directly.\n    # Always check status and explicitly parse JSON.\n    response.raise_for_status() # Raises an exception for HTTP error codes (e.g., 404, 500)\n    repos = response.json() # Parses the JSON body\n\n    print(f\"Successfully fetched {len(repos)} repositories for shazow.\")\n    if repos:\n        print(f\"First repository: {repos[0]['name']}\")\n\nexcept urllib3.exceptions.HTTPError as e:\n    print(f\"HTTP Error: {e.status} - {e.reason}\")\nexcept urllib3.exceptions.MaxRetryError as e:\n    print(f\"Network Error: Could not connect to host. {e}\")\nexcept Exception as e:\n    print(f\"An unexpected error occurred: {e}\")","lang":"python","description":"This example demonstrates how to define a simple GitHub API client using `APIClient` and the `endpoint` decorator. It fetches public repositories for a given user, explicitly handles the response object for status checking and JSON parsing, and includes basic error handling for network and HTTP errors."},"warnings":[{"fix":"After calling an `endpoint` method, always follow up with `response.raise_for_status()` to check for errors and `response.json()` (or `response.text`, `response.content`) to access the response body.","message":"Explicit Response Handling Required: `apiclient`'s `@endpoint` methods return a wrapped `urllib3` response object (type `apiclient._response.ResponseWrapper`). While this wrapper provides convenient `.json()` and `.raise_for_status()` methods, users must explicitly call them to parse the body or check for HTTP errors. The library does not automatically perform these actions.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Extend the `APIClient` or specific endpoint methods with custom logic to handle retries, rate limits, or other advanced scenarios using `urllib3` directly or other helper libraries.","message":"Minimal Feature Set - Implement Advanced Logic Manually: `apiclient` is a lightweight framework for defining API clients. It does not include built-in features like automatic retries with exponential backoff, rate limit handling, advanced caching, or request signing beyond basic headers. These must be implemented by the user if required for robust production clients.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Keep `urllib3` updated to a version compatible with `apiclient` (and address any `urllib3` specific warnings). Monitor `urllib3` release notes for changes relevant to HTTP client behavior.","message":"Potential for Indirect Impact from `urllib3` Updates: `apiclient` relies on `urllib3` for its HTTP core. While `apiclient` maintains its own stability, breaking changes, deprecations, or security updates in `urllib3` can indirectly affect your client's behavior or require updates to your environment. `apiclient` requires `urllib3>=1.26.0`.","severity":"gotcha","affected_versions":"All versions dependent on `urllib3`"}],"env_vars":null,"last_verified":"2026-04-17T00:00:00.000Z","next_check":"2026-07-16T00:00:00.000Z","problems":[{"fix":"Verify network connection, check `base_url` for typos, ensure the target API server is online and accessible. Consider adding retry logic to your client.","cause":"These exceptions indicate network connectivity issues, an incorrect `base_url` (e.g., wrong host, port, or protocol), or the API server being unreachable.","error":"urllib3.exceptions.MaxRetryError: HTTPConnectionPool(...)` or `urllib3.exceptions.NewConnectionError: <urllib3.connection.HTTPConnection object at ...>: Failed to establish a new connection: [Errno ...]"},{"fix":"Ensure your authentication headers are correctly set (e.g., `Authorization` header), verify the API key/token is valid, and double-check the `endpoint` path and method (e.g., `get` vs. `post`). Remember to call `response.raise_for_status()` to explicitly raise these HTTP errors.","cause":"The API server returned an error status code. This could be due to invalid or missing authentication credentials, incorrect endpoint path, or a resource not being found.","error":"urllib3.exceptions.HTTPError: HTTP 401: Unauthorized` (or `403: Forbidden`, `404: Not Found`, etc.)"}]}