Skip to main content

Async-first production-grade SDK for Kenya's GavaConnect Enterprise API platform.

Project description

gava-connect-plus banner

built in license last commit CI contributors stars

gava-connect-plus

Every Kenyan developer who has built an e-commerce platform, an accounting tool, or a payroll system eventually faces the same formidable milestone: integrating with the Kenya Revenue Authority (KRA) APIs.

Historically, this meant wading through fragmented PDF documentation, wrestling with clunky authentication flows, and writing thousands of lines of fragile boilerplate just to check if a PIN is valid or an eTIMS invoice is authentic. The process wasn't just slow—it was a tax on developer sanity.

gava-connect-plus was born out of a simple, rebellious realization: Integrating with local compliance infrastructure shouldn't feel like standing in a physical KRA line. This library serves as a beautiful, unofficial bridge between modern Python applications and the government gateway—built to handle the heavy lifting of compliance safely, invisibly, and instantly.

Core Principles

The architecture of gava-connect-plus is guided by three simple truths:

1. Developer Zen

The code you write should look like clean Python, not government bureaucracy. Complex SOAP/REST structures, weird payload mappings, and authentication handshakes are abstracted away behind an elegant, predictable API surface. One method call does exactly what it says.

2. Radical Isolation

Security is peace of mind. Every corporate department or microservice deserves its own cryptographic boundaries. By keeping service credentials strictly isolated (Invoice, PIN, and Station each running on their own terms), the library prevents permission creep and ensures your production tokens never bleed into one another.

3. Execution "Chap Chap"

Time is the only non-renewable asset. Whether running automated testing pipelines in the cloud or deploying to live production, the library is lightweight, optimized, and zero-fluff. It does its job and gets out of your way.

Installation & Quick Start

True to the principle of execution chap chap, getting the library into your environment takes a single command. We recommend using uv for lightning-fast environment resolution, but standard tools work perfectly too.

# For the mordenist usinv uv
uv add gava-connect-plus

# The classic way
pip install gava-connect-plus

Obtaining passwords, keys etc

Before writing any code, you need to secure your cryptographic credentials from the official gateway ecosystem.

  1. Head over to the Kenyan Government Developer Portal.
  2. Register an account and navigate to your dashboard workspace to provision access keys.

Tutorials for obtaining passwords available on youtube and beyond the scope of this doc

The Multi-App Architecture (Crucial Note)

The KRA API gateway relies on strict security scoping. Permissions are segregated at the application layer rather than bundled into a single master key. This means credentials must be obtained per module/API.

If your software requires both taxpayer identity verification and invoice tracking, you cannot use a single client key. You must create two separate applications inside the portal:

  • App #1: Provisioned explicitly with the PIN Checker by PIN scope.
  • App #2: Provisioned explicitly with the Invoice Checker scope.

Once you have your isolated keys, gava-connect-plus takes complete control of the administrative mess.

The Promise: You do not need to worry about the underlying Authorization endpoints, token expiration thresholds, or handshake state machines. Once the library is supplied with your application keys, internal OAuth token provisioning, caching, and background refreshes are executed seamlessly on autopilot.

1. Configure the Environment Sanctuary

Expose your isolated sandbox or production credential pairs directly to your system shell thread. The library automatically tracks these exact environment keys, keeping your production secrets completely out of source control:

# App #1: PIN Validation Credentials
export KRA_PIN_KEY="your_pin_app_consumer_key"
export KRA_PIN_SECRET="your_pin_app_consumer_secret"

# App #2: eTIMS Invoice Credentials
export KRA_INVOICE_KEY="your_invoice_app_consumer_key"
export KRA_INVOICE_SECRET="your_invoice_app_consumer_secret"

2. Write Pure, Frictionless Python

With your system environments aligned, initialize the workspace context. The library dynamically routes internal token handshakes to their respective apps in the background based on the API you invoke.

from gavaconnect import GavaConnect
from gavaconnect.exceptions import GavaConnectError

# Initialize the engine targeting the KRA gateway sandbox
with GavaConnect(environment="sandbox") as gava:
    try:
        # Validates identity via your PIN-scoped application keys
        record = gava.pin.check("A001234567Z")
        print(f"Identity Verified: {record.taxpayer_name}")
        
        # Audits eTIMS status via your Invoice-scoped application keys
        # All background OAuth tokens swap silently behind the scenes
        invoice = gava.invoice.get("INV-99824-X")
        print(f"Gross Invoice Value: KES {invoice.total_invoice_amount:,.2f}")
        
    except GavaConnectError as e:
        print(f"The gateway returned a peaceful error: {e}")

3. Explicit Dependency Injection (Alternative)

If you are managing configuration objects programmatically at runtime (e.g., retrieving secrets from an encrypted vault), bypass the environment variables by injecting the multi-app map dictionary directly into the builder constructor:

from gavaconnect import GavaConnectSync

# Map explicit credentials precisely to their module domain targets
custom_config = {
    "pin": {
        "consumer_key": "vault_pin_key_xyz",
        "consumer_secret": "vault_pin_secret_abc"
    },
    "invoice": {
        "consumer_key": "vault_invoice_key_123",
        "consumer_secret": "vault_invoice_secret_789"
    }
}

with GavaConnect(environment="sandbox", **custom_config) as gava:
    station = gava.station.get("A001234567Z")
    print(f"Assigned Tax Station: {station.station_name}")

# Notice that the above snippet uses the synchronous variant
# of the library
# 
# All such synchronous blocking calls are used with the Sync suffix

A word about using the library

Sync & Async Harmony

Python architectures are diverse. Some systems demand the raw speed of non-blocking concurrency, while others require the rock-solid predictability of standard sequential execution. gava-connect-plus honors both paths by providing native, separate engines for both synchronous and asynchronous workflows.

When initializing the library, you can choose the engine that perfectly aligns with your environment constraints and runtime architecture.

The Asynchronous Path (For High-Concurrence API Gateways)

If you are building high-throughput microservices using modern async frameworks like FastAPI, Litestar, or Sanic, use the async flavor to ensure your application threads never sleep while waiting for network I/O from the KRA gateway:

import asyncio
from gavaconnect import GavaConnect

async def main():
    # Non-blocking connection pooling executing natively inside your event loop
    async with GavaConnect(environment="sandbox") as gava:
        record = await gava.pin.check("A001234567Z")
        print(f"Async Identity Verified: {record.taxpayer_name}")

asyncio.run(main())

The Synchronous Path (For Predictable, Thread-Safe Workflows)

For applications built on standard blocking architectures, the synchronous engine provides a clean, dependency-free wrapper that executes line-by-line without an active event loop loop manager:

from gavaconnect import GavaConnectSync

with GavaConnectSync(environment="sandbox") as gava:
    record = gava.pin.check("A001234567Z")
    print(f"Sync Identity Verified: {record.taxpayer_name}")

Architectural Nuance: When to stay Synchronous (The Django Paradigm)

It is tempting to default to async for all network utilities, but context dictates performance. For example, if you are integrating this library into a traditional Django application served via a standard WSGI stack (like Gunicorn or uWSGI), you should choose the synchronous version.

The Technical Reason: Django’s core engine, request lifecycle middlewares, and database ORM layers are fundamentally synchronous by design. While Django offers async views, mixing them into a WSGI runtime forces the framework to wrap execution threads in thread-switching utility layers (async_to_sync and sync_to_async).

If your view is already handling a synchronous database transaction, throwing an asynchronous API call into the middle of it triggers complex context-switching overhead and thread hopping inside the Python runtime. This context switching can actually degrade performance and introduce subtle race conditions with thread-local data. Staying purely synchronous inside a synchronous application architecture keeps your execution path flat, memory overhead minimal, and debugging straightforward.


Path to Completeness (Module Roadmap)

The KRA API ecosystem is vast, covering everything from basic identity checks to complex customs calculations and tax filing routines. Rome wasn't built in a day, and neither is the ultimate developer gateway toolkit.

gava-connect-plus is a living blueprint. While the core verification bedrock is fully operational and production-ready, several advanced transactional modules are currently slated for future integration cycles.

Below is the current state of alignment between the SDK and the official developer.go.ke portal services:

Feature / API Endpoint Status Tested
Automated OAuth Token Lifecycle Management & Caching
PIN Checker by PIN (PIN_Validation_by_PIN)
PIN Checker by ID (DTD_PINChecker)
Know KRA Tax Service Office/Station (SUC-iTax-USSD_Know_Your_Station)
eTIMS Invoice Checker (Invoice-Checker)
Fetch Taxpayer Obligations (TaxPayer_Tax_Obligations_Fetcher) ⏳ Planned -
Withholding Tax PRN Generation (Income Tax, Rental, VAT) ⏳ Planned -
Tax Compliance Certificate (TCC) Validation & Application ⏳ Planned -
Automated NIL Return Filing (iTax_NIL_Return) ⏳ Planned -
Income Tax & VAT Exemption Checker ⏳ Planned -
Turnover Tax (TOT) Return Filing ⏳ Planned -
Customs Declaration Status Checker & Tax Calculator ⏳ Planned -
Import Certificate Checker (By Number / PIN) ⏳ Planned -
Individual KRA PIN Registration Gateway ⏳ Planned -
eTIMS OSCU Integrator Automated Testing Suite ⏳ Planned -
Excise License Checker (By Pin / Certificate Number) ⏳ Planned -

The Genesis & Contributing

Let’s clear the air right away: I am not affiliated, associated, authorized, or in any way officially connected with the Kenya Revenue Authority (KRA). This project was born out of pure, unadulterated developer frustration. While building a commercial product that required KRA portal integrations, I looked around the ecosystem for a robust, production-grade Python package that could handle the gateway safely and seamlessly. I found absolutely nothing.

Faced with a wall of fragmented PDFs and custom network scripts, I decided to take a deep breath, skip a few nights of sleep, and jump straight down the rabbit hole to build the tool that should have already existed. gava-connect-plus is the result of that journey.

Join the Journey

Because this is a community-driven initiative, your hands and minds are needed to help shape it. Whether you want to squash an edge-case bug, optimize the internal caching layers, or drag one of the Planned transactional modules into operational reality, contributions are deeply welcomed.

Feel free to open an issue, start a discussion thread, or send a pull request over the wall. Let's make integration painless for the next developer.

Support the energy

If gava-connect-plus saves you days of digging through portal specifications, keeps your production builds green, or spares your team a minor existential crisis, consider giving back to the project:

  • ⭐ Star the Repository: It costs nothing and directly helps other Kenyan developers discover the project on GitHub.
  • 🗣️ Spread the Word: Share the project link in your local tech WhatsApp groups, Discord servers, or on X (Twitter). Let's build a stronger local open-source culture.
  • ☕ Buy Me a Coffee: If this library saved your business real billable hours, consider fueling the midnight oil for the next sprint of module developments. Your support keeps the zen flowing.

chart

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

gava_connect_plus-0.2.1.tar.gz (14.4 kB view details)

Uploaded Source

Built Distribution

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

gava_connect_plus-0.2.1-py3-none-any.whl (20.5 kB view details)

Uploaded Python 3

File details

Details for the file gava_connect_plus-0.2.1.tar.gz.

File metadata

  • Download URL: gava_connect_plus-0.2.1.tar.gz
  • Upload date:
  • Size: 14.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.26 {"installer":{"name":"uv","version":"0.11.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for gava_connect_plus-0.2.1.tar.gz
Algorithm Hash digest
SHA256 171ae4c74c710313698688726ce123a180b867fc48250450bcf8412bbfef1f64
MD5 42debb00defea8e4e4a0df25faddd2e3
BLAKE2b-256 d880cdf32834667df4fac39e1c8f12a13ffd42a8a69d1c52303e1f870efbe2ba

See more details on using hashes here.

File details

Details for the file gava_connect_plus-0.2.1-py3-none-any.whl.

File metadata

  • Download URL: gava_connect_plus-0.2.1-py3-none-any.whl
  • Upload date:
  • Size: 20.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.26 {"installer":{"name":"uv","version":"0.11.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for gava_connect_plus-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 8d70647b46af19d5126054c0e5717b92f05733997760ff9aea84dc5ea9ef7cd1
MD5 26d371824c59f0da1745dc8cb677fb9f
BLAKE2b-256 17d651bd2458bd2f7464a53efca00c60cf3321a6639c6537607cb64779cd8633

See more details on using hashes here.

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