Skip to main content

🚀 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

A real example: fetching your 3 latest unread emails

Talk is cheap — here's the same task, side by side. No auth boilerplate, no manual pagination, no hand-rolled URLs.

❌ Without HakiAPI

import requests
import os

token = os.environ["GMAIL_OAUTH_TOKEN"]
headers = {"Authorization": f"Bearer {token}"}
base_url = "https://gmail.googleapis.com/gmail/v1/users/me"

params = {"q": "is:unread"}
unread_messages = []

# Keep pulling pages until we have 3 messages or run out of pages
while True:
    response = requests.get(f"{base_url}/messages", headers=headers, params=params)
    response.raise_for_status()
    data = response.json()

    for msg in data.get("messages", []):
        unread_messages.append(msg)
        if len(unread_messages) >= 3:
            break

    if len(unread_messages) >= 3 or "nextPageToken" not in data:
        break

    params["pageToken"] = data["nextPageToken"]

# Fetch the full body for each message
for msg in unread_messages:
    msg_data = requests.get(f"{base_url}/messages/{msg['id']}", headers=headers).json()
    print(msg_data.get("snippet"))

✅ With HakiAPI

import os
from hakiapi import GmailClient

token = os.environ["GMAIL_OAUTH_TOKEN"]

with GmailClient(token=token) as gmail:
    # Auth, retries, and pagination are handled for you
    unread_messages = gmail.messages.search(query="is:unread", max_pages=1)

    for count, msg in enumerate(unread_messages):
        if count >= 3:
            break
        full_msg = gmail.messages.get(message_id=msg["id"])
        print(full_msg.get("snippet"))

What HakiAPI handles for you here:

  • Pagination — Google-style nextPageToken (and Link-header pagination elsewhere) is followed automatically, with a max_pages safety valve so you never accidentally loop forever.
  • Resource routing — client.resource.action() instead of hand-building URLs and re-typing the same base path everywhere.
  • Type safety — built with static analysis in mind, so tools like Ruff and Pyright stay useful instead of fighting dict soup.

✨ 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, GoogleCalendar
🧪 Fully tested 220+ 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
    └── google_calendar.py   # GoogleCalendarClient

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
  • Google Calendar client

Planned

  • 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

Metadata

Release files for hakiapi 2.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for hakiapi 2.0.0
File Size Uploaded
hakiapi-2.0.0.tar.gz 43.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for hakiapi 2.0.0
File Interpreter ABI Platform
hakiapi-2.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 67.4 kB

Release files / hakiapi-2.0.0.tar.gz

Download URL hakiapi-2.0.0.tar.gz
Size 43.5 kB
Tags Source
SHA-256 checksum
How to use checksums
456c12bc77e68bdcc4a317ad56485e367877d30a378322c8f13d30c20bc814fc
BLAKE2b-256 checksum
How to use checksums
da4280682f07b2deb7dbf5ace39ec5b16e0a897e0e463ad138bd969ed6d41c93
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 23, 2026.

Transparency log

Release files / hakiapi-2.0.0-py3-none-any.whl

Download URL hakiapi-2.0.0-py3-none-any.whl
Size 24.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
0245fee88957587ebf5930318a59c0a07fd6a39d5459643aeee6c892a26383ed
BLAKE2b-256 checksum
How to use checksums
8c81d83d60cfea39c4faf90f93c3f5a6ec8f9c1739b84340e0c3b84369f221cd
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 23, 2026.

Transparency log

Release history Release notifications | RSS feed

2.1.6

2 release files

2.1.5

2 release files

2.1.4

2 release files

2.1.2

2 release files

2.1.0

2 release files

2.0.2

2 release files

2.0.1

2 release files

This release

2.0.0 This release

2 release files

1.2.2

2 release files

1.2.0

2 release files

1.1.0

2 release files

1.0.5

2 release files

1.0.4

2 release files

1.0.2

2 release files

1.0.1

2 release files

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page