ngtaxkit
Nigerian tax compliance SDK for Python. Implements the Nigeria Tax Act (NTA) 2025 — VAT, PAYE, WHT, Pension, Statutory deductions, Marketplace transactions, and Payroll batch processing.
Zero dependencies. Pure functions. Deterministic output. Python 3.10+.
Install
pip install ngtaxkit
Optional extras:
pip install ngtaxkit[pdf] # PDF generation (fpdf2)
pip install ngtaxkit[django] # Django fields + template tags
pip install ngtaxkit[flask] # Flask blueprint + Jinja filters
pip install ngtaxkit[fastapi] # FastAPI router + Pydantic models
Quick Start
from ngtaxkit import vat, paye, wht, pension, payroll
# ─── VAT ────────────────────────────────────────────────────────────────────
# Calculate VAT on an amount
result = vat.calculate(amount=100_000)
# → {'net': 100000, 'vat': 7500, 'gross': 107500, 'rate': 0.075, 'rate_type': 'standard', ...}
# Extract VAT from an inclusive amount
result = vat.extract(amount=107_500)
# → {'net': 100000, 'vat': 7500, 'gross': 107500, ...}
# Zero-rated categories
result = vat.calculate(amount=50_000, category='basic-food')
# → {'vat': 0, 'rate': 0, 'rate_type': 'zero-rated', 'input_vat_recoverable': True, ...}
# Exempt categories
result = vat.calculate(amount=200_000, category='residential-rent')
# → {'vat': 0, 'rate_type': 'exempt', 'input_vat_recoverable': False, ...}
# ─── PAYE ───────────────────────────────────────────────────────────────────
result = paye.calculate(
gross_annual=5_000_000,
pension_contributing=True,
nhf_contributing=True,
rent_paid_annual=600_000,
)
# → {
# 'annual_paye': ...,
# 'monthly_paye': ...,
# 'effective_rate': ...,
# 'tax_bands': [...],
# 'reliefs': {'consolidated_relief', 'pension_relief', 'nhf_relief', 'rent_relief', 'total'},
# 'net_monthly': ...,
# 'monthly_deductions': {'paye', 'pension', 'nhf', 'total'},
# 'employer_costs': {'pension', 'nsitf', 'itf', 'total'},
# 'legal_basis': '...',
# }
# ─── WHT ────────────────────────────────────────────────────────────────────
result = wht.calculate(
amount=500_000,
payee_type='company',
service_type='professional',
)
# → {
# 'wht_amount': 50000,
# 'rate': 0.1,
# 'net_payment': 450000,
# 'credit_note_required': True,
# 'remittance_deadline': '2026-05-21',
# }
# ─── Pension ────────────────────────────────────────────────────────────────
result = pension.calculate(
basic_salary=300_000,
housing_allowance=100_000,
transport_allowance=50_000,
)
# → {
# 'pensionable_earnings': 450000,
# 'employee_contribution': 36000,
# 'employer_contribution': 45000,
# 'total_contribution': 81000,
# }
# ─── Payroll (batch) ────────────────────────────────────────────────────────
result = payroll.calculate_batch([
{'name': 'Amina', 'gross_annual': 4_000_000, 'state_of_residence': 'LA', 'pension_contributing': True},
{'name': 'Chidi', 'gross_annual': 8_000_000, 'state_of_residence': 'FC', 'pension_contributing': True},
{'name': 'Bola', 'gross_annual': 2_400_000, 'state_of_residence': 'LA', 'nhf_contributing': True},
])
# → {
# 'employees': [...],
# 'by_state': {
# 'LA': {'state_name': 'Lagos', 'irs_name': 'LIRS', 'employee_count': 2, ...},
# 'FC': {'state_name': 'FCT', 'irs_name': 'FCT-IRS', 'employee_count': 1, ...},
# },
# 'totals': {'total_gross', 'total_paye', 'total_pension', 'total_nhf', 'employee_count'},
# }
Trust & Explainability
Every bundled rate can be explained with source metadata, and VAT/PAYE/WHT can return a calculation trace for audit logs, user-facing receipts, and integrations.
from ngtaxkit import rates, vat, paye, wht
trace = vat.explain_calculate(amount=100_000, category="standard")
trace["result"]["vat"] # 7500
trace["formula"] # reproducible calculation steps
trace["rate_keys"] # ["vat.standard.rate"]
trace["sources"][0] # source URL, legal basis, review date, confidence
trace["warnings"] # non-empty if a source is needs_review/disputed
rates.explain("paye.exemptionThreshold")
rates.audit()
paye.explain_calculate(gross_annual=5_000_000, pension_contributing=True)
wht.explain_calculate(amount=500_000, payee_type="company", service_type="professional")
Source metadata is bundled offline. Treat it as developer evidence, not legal advice; re-check high-impact filings against official notices and professional advice.
For deterministic tool integrations, use the tools namespace:
from ngtaxkit import tools
tools.get_tool_schemas() # JSON Schema-compatible tool definitions
tools.get_openapi_spec() # OpenAPI 3.1 wrapper shape
tools.call_tool(
"ngtaxkit.vat.explain_calculate",
{"amount": 100_000, "category": "standard"},
)
Modules
| Module | Description |
|---|---|
vat |
VAT calculation, extraction, category classification |
paye |
PAYE income tax with NTA 2025 graduated brackets and reliefs |
wht |
Withholding tax by service type and payee type |
pension |
Contributory Pension Scheme — employee/employer splits |
statutory |
NHF, NSITF, ITF statutory deductions |
marketplace |
End-to-end marketplace transaction: VAT + commission + WHT + payout |
payroll |
Batch payroll with per-state aggregation and filing info |
rates |
Versioned rate registry — all rates, brackets, and thresholds |
tools |
JSON schemas, OpenAPI wrapper spec, and deterministic dispatcher |
Statutory Deductions
from ngtaxkit import statutory
# Individual deductions
nhf = statutory.nhf(basic_salary=300_000)
nsitf = statutory.nsitf(monthly_payroll=5_000_000)
itf = statutory.itf(annual_payroll=60_000_000, employee_count=25)
# All at once
all_deductions = statutory.calculate_all(
basic_salary=300_000,
monthly_payroll=5_000_000,
annual_payroll=60_000_000,
employee_count=25,
)
Marketplace Transactions
from ngtaxkit import marketplace
result = marketplace.calculate_transaction(
sale_amount=100_000,
platform_commission=0.10, # 10% commission
seller_vat_registered=True,
buyer_type='individual',
service_category='standard',
)
# → {
# 'sale_amount': 100000,
# 'vat': {'net': 100000, 'vat': 7500, ...},
# 'total_from_buyer': 107500,
# 'platform_commission': {'rate': 0.1, 'amount': 10000, ...},
# 'seller_payout': ...,
# 'wht': {...} or None,
# 'vat_liability': {'collected_by': 'seller', 'amount': 7500, ...},
# }
VAT Categories
| Category | Rate | Type | Input VAT Recoverable |
|---|---|---|---|
standard |
7.5% | Standard | Yes |
basic-food |
0% | Zero-rated | Yes |
medicine |
0% | Zero-rated | Yes |
medical-equipment |
0% | Zero-rated | Yes |
medical-services |
0% | Zero-rated | Yes |
educational-books |
0% | Zero-rated | Yes |
tuition |
0% | Zero-rated | Yes |
electricity |
0% | Zero-rated | Yes |
export-services |
0% | Zero-rated | Yes |
humanitarian-goods |
0% | Zero-rated | Yes |
residential-rent |
0% | Exempt | No |
public-transport |
0% | Exempt | No |
financial-services |
0% | Exempt | No |
insurance |
0% | Exempt | No |
Key Design Decisions
- Banker's rounding — all monetary values use round-half-even to 2 decimal places (Python's
ROUND_HALF_EVEN) - Legal citations — every result includes a
legal_basisstring citing the NTA 2025 section - Source-backed explanations — VAT, PAYE, and WHT expose formula steps, source metadata, and warnings for values that need review
- Versioned rates — bundled as JSON; override at runtime via
rates.set_custom() - Cross-language parity — produces identical results to the TypeScript version, enforced by shared test fixtures
- Type hints — full
py.typedsupport with strict mypy compliance
Framework Integrations
Django
# settings.py
INSTALLED_APPS = [..., 'ngtaxkit.contrib.django']
# models.py
from ngtaxkit.contrib.django import TINField, NairaField, VATCategoryField
class Invoice(models.Model):
seller_tin = TINField()
amount = NairaField()
category = VATCategoryField()
# templates
{% load ngtaxkit_tags %}
{{ amount|naira }} {# NGN 1,234,567.89 #}
{{ amount|vat_amount }} {# NGN 92,592.59 #}
{% vat_rate "standard" %} {# 7.5% #}
Flask
from ngtaxkit.contrib.flask import init_app
app = Flask(__name__)
init_app(app) # Registers /tax/vat/calculate, /tax/paye/calculate, /tax/wht/calculate + Jinja filters
# In templates
{{ amount|naira }}
{{ amount|vat }}
FastAPI
from ngtaxkit.contrib.fastapi import create_router
app = FastAPI()
app.include_router(create_router(), prefix="/api")
# Adds /api/tax/vat/calculate, /api/tax/paye/calculate, etc. with Pydantic validation
Install extras:
pip install ngtaxkit[django] # Django fields + template tags
pip install ngtaxkit[flask] # Flask blueprint + Jinja filters
pip install ngtaxkit[fastapi] # FastAPI router + Pydantic models
License
MIT — see LICENSE
Author
Abraham Tanta
Links
Metadata
Release files for ngtaxkit 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| ngtaxkit-0.1.1.tar.gz | 54.2 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| ngtaxkit-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 112.1 kB
Release files / ngtaxkit-0.1.1.tar.gz
| Download URL | ngtaxkit-0.1.1.tar.gz |
|---|---|
| Size | 54.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
21877e1230844a92d48c44ace52b012293142a6deb36aea39a950eafbcb5d13d
|
|
BLAKE2b-256 checksum How to use checksums |
d42df915bae389dac00f7e2da7f92a28d4f16b83d665b09b92edbf360adbb891
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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 Jun 14, 2026.
Transparency logRelease files / ngtaxkit-0.1.1-py3-none-any.whl
| Download URL | ngtaxkit-0.1.1-py3-none-any.whl |
|---|---|
| Size | 57.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
bbda0000d6e44022e7cd42901ab8e9b78cf7803df8cf41d58b8df047cdfbb21f
|
|
BLAKE2b-256 checksum How to use checksums |
0d77dbc9696c5dbaeaeb9f47221cd31fcf22a84758a53bc092f44e828acee675
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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 Jun 14, 2026.
Transparency logSecurity for ngtaxkit 0.1.1
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.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for ngtaxkit-0.1.1.tar.gz
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 Jun 14, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.