Skip to main content

A modern Python framework for building clean, typed, and extensible API clients.

Project description

๐Ÿš€ HakiAPI

Build production-grade Python API SDKs โ€” not boilerplate.

Authentication ยท Retries ยท Pagination ยท Typed Exceptions ยท Session Management

PyPI Python License Tests Typing Downloads

Stop rewriting authentication, retries, and pagination for every API client you build.

Installation โ€ข Quick Start โ€ข Features โ€ข Architecture โ€ข Create Your Own Client โ€ข Roadmap


Why HakiAPI?

Every API client grows the same infrastructure, in the same order. You start with a simple HTTP call. Then you add authentication. Then retries. Then pagination. Then timeout and exception handling. Then session management. A month later, you've rebuilt the same plumbing you already wrote for the last five projects.

HakiAPI extracts all of that into one reusable core, so every client you build on top of it inherits production-ready behavior automatically. Instead of writing infrastructure, you write business logic.

Without HakiAPI vs. with HakiAPI

Raw requests HakiAPI
Retry on 429/500/502/503/504 Write your own urllib3.Retry + HTTPAdapter wiring Built into BaseAPIClient automatically
Auth (Bearer / API Key / HMAC) Reimplement per project 4 reusable AuthBase strategies, drop-in
Rate limits, timeouts, 4xx/5xx Manually check response.status_code everywhere Raised as typed, catchable exceptions
Pagination Write a while loop per API's pagination style Auto-detects Link-header and cursor/token pagination, iterated lazily
New service client Copy-paste session + error-handling code Subclass BaseAPIClient, define endpoints, done

โœจ Features

Feature Details
๐Ÿ” Multiple auth strategies BearerTokenAuth, HeaderApiKeyAuth, QueryApiKeyAuth, HmacAuth
๐Ÿ” Automatic retries Exponential backoff on 429/500/502/503/504, mounted transparently on every session
๐Ÿ“„ Automatic pagination Auto-detects Link-header (GitHub-style) and cursor/token (meta.next_token) pagination, lazily iterated with an optional max_pages safety valve
โš ๏ธ Typed exception hierarchy RateLimitError, AuthenticationError, ClientError, ServerError, RequestTimeoutError, all rooted in HakiAPIError
๐ŸŒ Persistent HTTP sessions Connection pooling via requests.Session, closed automatically with with
๐Ÿงฉ Extensible base client Subclass BaseAPIClient, inherit everything above for free
๐Ÿ“ฆ Ready-to-use clients GitHub, Gmail
๐Ÿงช Fully tested 214 tests, full coverage of core + clients
๐Ÿ Python 3.10+ Fully type-hinted

Installation

pip install hakiapi

Requires Python 3.10+.


Quick Start

GitHub

from hakiapi.clients.github import GitHubClient

with GitHubClient() as github:
    user = github.get_user("torvalds")
    print(f"{user['name']} โ€” {user['public_repos']} public repos")

No authentication plumbing. No retry logic. No session handling. Just Python.

Automatic pagination

Forget page numbers, while loops, and manually checking for a next page โ€” HakiAPI follows Link headers, cursor pagination, and token pagination automatically, lazily:

with GitHubClient() as github:
    for repo in github.get_all_user_repos("torvalds"):
        print(repo["name"])

A full example

Aggregate every programming language used across a user's public repositories, entirely through the paginator:

from hakiapi.clients.github import GitHubClient

with GitHubClient() as github:
    target_user = "Gugilla-Aakash"

    user_data = github.get_user(target_user)
    print(f"User: {user_data.get('name')}")
    print(f"Public Repos: {user_data.get('public_repos')}")

    lang_stats = github.get_aggregate_user_languages(target_user, params={"per_page": 5})

    total_bytes = sum(lang_stats.values())
    print("\nLanguage Breakdown (by byte allocation):")
    for lang, byte_count in sorted(lang_stats.items(), key=lambda i: i[1], reverse=True):
        percentage = (byte_count / total_bytes) * 100 if total_bytes else 0
        print(f"- {lang}: {byte_count} bytes ({percentage:.2f}%)")

Output shape is illustrative โ€” real numbers depend on the account queried.

Gmail

from hakiapi.clients.gmail import GmailClient

with GmailClient(token="your-oauth-token") as gmail:
    for message in gmail.get_all_messages():
        print(message["id"])

Authentication, pagination, and retries โ€” already handled.


Exception Handling

Never check HTTP status codes manually again:

from hakiapi.core.exceptions import AuthenticationError, RateLimitError, ServerError

try:
    github.get_user("torvalds")
except RateLimitError as e:
    print(f"Rate limited โ€” retry after {e.retry_after}s")
except AuthenticationError:
    print("Invalid credentials.")
except ServerError:
    print("GitHub is currently unavailable.")

Every exception inherits from HakiAPIError, so you can catch broadly or narrowly โ€” each carries status_code and the original response object.

HakiAPIError
โ”œโ”€โ”€ ClientError                 (4xx)
โ”‚   โ”œโ”€โ”€ RateLimitError          (429, carries retry_after)
โ”‚   โ””โ”€โ”€ AuthenticationError     (401 / 403, carries auth_method)
โ”œโ”€โ”€ ServerError                 (5xx)
โ””โ”€โ”€ RequestTimeoutError         (network-level timeout, no status code)

Supported Authentication

Strategy Use case
BearerTokenAuth Standard Authorization: Bearer <token> (GitHub, Gmail, most OAuth2 APIs)
HeaderApiKeyAuth Custom header-based API keys (e.g. X-API-Key: <key>)
QueryApiKeyAuth Query-string API keys, appended without dropping existing params
HmacAuth HMAC-SHA256 request signing โ€” signs method, path, timestamp, and body; sets the key, timestamp, and signature headers

Every strategy is a reusable AuthBase instance โ€” pass it once into BaseAPIClient.__init__, and every request is signed automatically.


Automatic Retry

Retries happen transparently on 429, 500, 502, 503, and 504, via urllib3's Retry mounted on the session's HTTPAdapter:

  • Exponential backoff
  • Connection reuse across retries
  • Timeout handling surfaced as RequestTimeoutError
  • No configuration required for standard usage โ€” override total_retries, backoff_factor, or status_forcelist if you need to

Architecture

              GitHubClient, GmailClient, ...
                         โ”‚
                         โ–ผ
                  BaseAPIClient
       โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
       โ”‚              โ”‚         โ”‚          โ”‚
 Authentication     Retry   Pagination  Exceptions
  (auth.py)       (retry.py) (paginator.py) (exceptions.py)
                         โ”‚
                         โ–ผ
                     requests

Every service client inherits production-ready infrastructure automatically โ€” nothing to wire up per client.


Create Your Own Client

Creating a new SDK is intentionally simple: subclass BaseAPIClient, point it at a base URL, and define your endpoints as plain methods.

from hakiapi import BaseAPIClient

class WeatherClient(BaseAPIClient):
    def __init__(self, **kwargs):
        super().__init__(base_url="https://api.open-meteo.com/v1", **kwargs)

    def get_weather(self, latitude: float, longitude: float):
        return self.get(
            "forecast",
            params={
                "latitude": latitude,
                "longitude": longitude,
                "current_weather": True,
            },
        )


if __name__ == "__main__":
    # Hyderabad, Telangana, India
    with WeatherClient() as client:
        weather = client.get_weather(latitude=17.385, longitude=78.4867)
        print(weather["current_weather"])

Output

{
    'time': '2026-07-19T10:00',
    'interval': 900, 
    'temperature': 30.6, 
    'windspeed': 13.9, 
    'winddirection': 271, 
    'is_day': 1, 
    'weathercode': 51
}

Authentication, retries, pagination, sessions, and exceptions are already included โ€” you only write the endpoint logic.


Project Structure

hakiapi/
โ”œโ”€โ”€ core/
โ”‚   โ”œโ”€โ”€ auth.py            # BearerTokenAuth, HeaderApiKeyAuth, QueryApiKeyAuth, HmacAuth
โ”‚   โ”œโ”€โ”€ retry.py            # Exponential-backoff HTTPAdapter factory
โ”‚   โ”œโ”€โ”€ paginator.py        # Link-header + cursor/token pagination, lazily iterated
โ”‚   โ”œโ”€โ”€ base_client.py      # Session management, request lifecycle, error mapping
โ”‚   โ””โ”€โ”€ exceptions.py       # Typed exception hierarchy
โ”‚
โ””โ”€โ”€ clients/
    โ”œโ”€โ”€ github.py            # GitHubClient
    โ””โ”€โ”€ gmail.py             # GmailClient

Design Principles

  • Infrastructure should be written once.
  • API clients should remain lightweight.
  • Explicit is better than magical.
  • Strong typing improves maintainability.
  • Production readiness should be the default, not an afterthought.
  • Developer experience matters as much as correctness.

Testing

pip install hakiapi[dev]
pytest
  • โœ… 214 tests passing
  • โœ… Core framework covered (auth, retry, paginator, base client, exceptions)
  • โœ… GitHub client covered
  • โœ… Gmail client covered

Roadmap

Completed

  • Base API framework (BaseAPIClient)
  • Authentication system (Bearer, Header, Query, HMAC)
  • Retry engine with exponential backoff
  • Automatic pagination (Link header + cursor/token)
  • Typed exception hierarchy
  • GitHub client
  • Gmail client

Planned

  • Google Calendar client
  • Stripe client
  • Twitter/X client
  • Async client (httpx-based)
  • OAuth2 helpers
  • Plugin system
  • More service clients

Contributing

Contributions are welcome โ€” bug fixes, documentation, tests, or new clients. Please open an issue before proposing major changes so we can discuss the approach first.


License

MIT License โ€” see LICENSE for details.


โญ If HakiAPI saved you from rewriting the same API client for the tenth time, consider giving it a star.

It helps more developers discover the project and motivates future development.

Built with โค๏ธ by Gugilla Aakash

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

hakiapi-1.2.0.tar.gz (28.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

hakiapi-1.2.0-py3-none-any.whl (14.7 kB view details)

Uploaded Python 3

File details

Details for the file hakiapi-1.2.0.tar.gz.

File metadata

  • Download URL: hakiapi-1.2.0.tar.gz
  • Upload date:
  • Size: 28.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for hakiapi-1.2.0.tar.gz
Algorithm Hash digest
SHA256 b1f61227c88d0f98a01dec9f67fdc90e67bc039d9d09502b344ca9e53fe9446a
MD5 1a5d0a038649358ece993cd3a5d8479d
BLAKE2b-256 ccba42fc8c86fc6c7d5f58363dfde3db9656ffc4c617cf315425f6919c4f651a

See more details on using hashes here.

Provenance

The following attestation bundles were made for hakiapi-1.2.0.tar.gz:

Publisher: release.yml on Gugilla-Aakash/hakiapi

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file hakiapi-1.2.0-py3-none-any.whl.

File metadata

  • Download URL: hakiapi-1.2.0-py3-none-any.whl
  • Upload date:
  • Size: 14.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for hakiapi-1.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 adeaa4d45eda4b286846f28f51ee1d80797172cd048d16ed5f77d52ba9967448
MD5 73c678627661c26d4e40ab55a60c19b9
BLAKE2b-256 84f5806d9af049d54b560087640fda3561334297f42f2c3cde96c123b95a3d1a

See more details on using hashes here.

Provenance

The following attestation bundles were made for hakiapi-1.2.0-py3-none-any.whl:

Publisher: release.yml on Gugilla-Aakash/hakiapi

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page