Skip to main content

africa-compliance-data

Client library for the Africa Compliance Data API: public holidays, business days, a holiday watch for announced and moon-sighted holidays, VAT (with dated rate history), withholding tax and tax-treaty rates, tax ID formats, filing deadlines and finance-law digests for 54 African countries, with coverage shown per country. Every value cites its source: official texts first; secondary sources, press reports and estimates are labelled, with a confidence level.

No dependencies (standard library only). Python 3.8+.

pip install africa-compliance-data

Quick start

from africa_compliance_data import AfricaComplianceData

acd = AfricaComplianceData()  # reads ACD_API_KEY, or pass api_key="..."

holidays = acd.holidays("MA", 2027)
due = acd.add_business_days("KE", "2026-12-23", 5)
watch = acd.holiday_watch(days=30, countries=["KE", "NG", "MA"])
vat = acd.vat("NG")                                # Pro or Compliance plan
check = acd.validate_tax_id("ZA", "0123456782")    # Pro or Compliance plan

Get a key at africacompliancedata.com: the Free plan costs nothing (holidays and business days, non-commercial use); paid plans add commercial use and tax data.

Methods

Method Endpoint Plan
countries() / country(country) /v1/countries, /v1/countries/{cc} All (tax sections of the profile: Pro for the countries of your pack, Compliance)
holidays(country, year, include_religious_scopes=None) /holidays All
holidays_ics(country, from_year=None, to_year=None, include_religious_scopes=None) /holidays.ics (returns iCalendar text) All
holiday_watch(days=None, countries=None) /v1/holidays/watch (announced and moon-sighted holidays) Developer, Pro, Compliance
is_business_day(country, date) /is-business-day All
business_days(country, from_date, to_date) /business-days All
add_business_days(country, date, days) /add-business-days All
account() /v1/account (plan, monthly quota, country pack, today's usage) All
country_pack(), set_country_pack(countries) /v1/account/countries (the countries of tax data in your pack; a change that removes a country: once every 30 days) Pro
vat(country, date=None) /vat (with date: the standard rate in force that day) Pro (countries of your pack), Compliance
vat_history(country) /vat/history Pro (countries of your pack), Compliance
withholding_tax(country, payment_type=None, recipient_country=None) /withholding-tax (with recipient_country: the treaty rates too) Pro (countries of your pack), Compliance
treaties(country, partner=None) /treaties Pro (countries of your pack), Compliance
validate_tax_id(country, value, server=False) Checked on your machine with the signed format rules (GET /v1/tax-id/rules, verified with the built-in Ed25519 key in pure Python, refreshed daily, valid 35 days): the number is not sent. Same answer as the API plus checked_locally: True. Falls back to POST /tax-id/validate (number in the JSON body, never the URL) if the rules cannot be had; server=True forces it. Options: tax_id_mode="local" never sends a number, "server" always uses the API; tax_id_rules() returns the bundle to save and pass back as tax_id_rules= Pro (countries of your pack), Compliance
deadlines(country, year, month) /deadlines Pro (countries of your pack), Compliance
finance_law(country) /finance-law Compliance
list_webhooks(), create_webhook(url, countries=None, features=None), delete_webhook(webhook_id), test_webhook(webhook_id) /v1/webhooks Developer and Pro (holiday changes), Compliance (all changes)

Optional arguments are keyword-only. A method outside your plan raises ApiError with status 403 and an upgrade message. include_religious_scopes=True adds holidays limited to one group (a faith, women, the public sector); by default only national holidays are returned.

Dates may be YYYY-MM-DD strings or datetime.date objects. Errors raise ApiError with .status and .body. Rate-limit (429) and temporary errors are retried twice, honouring Retry-After. Webhook create and test (POST) are retried only on 429 and 503, never after a timeout or network error (the request may have gone through). In holiday_watch, an empty countries list raises ValueError; omit it for all countries.

Private mode (version 1.2.0)

acd = AfricaComplianceData(private_mode=True, bundle_cache_dir="~/.cache/acd-bundles")
due = acd.add_business_days("KE", "2026-12-23", 5)   # computed on your machine
# due["computed_locally"] is True

With private_mode=True, holidays, is_business_day, business_days, add_business_days, vat (with or without date), vat_history and deadlines are computed on your machine. The client downloads a signed bundle per country and year (GET /v1/countries/{cc}/bundle?year=), and the dates, ranges, months and day counts of your queries are not sent. The only details of your queries in those requests are the country and the year (they also carry your API key, like every request). The answers have the same fields and values as the API's, plus computed_locally: True.

  • Each bundle is checked before use: its Ed25519 signature (the same built-in key as the tax ID rules, verified in pure Python), the country and year, and its expiry. A bundle expires 1 day after it is issued for the current year and later years, because holiday dates can still be confirmed or moved; for past years it expires after 30 days. An expired bundle is never used: a new one is downloaded.
  • Bundles are kept in memory. bundle_cache_dir (optional) also keeps them in that folder between runs (expanded with os.path.expanduser). Bundles read from disk are verified again.
  • If a bundle cannot be downloaded or does not verify, the method raises PrivateModeError. The client never sends the query to the API instead. The API's own refusals pass through unchanged: an unknown country (404), a plan without tax data (403, as the API's tax endpoints say), or the monthly quota (429).
  • Plans: holiday parts on every plan; tax parts (VAT, VAT history, deadline rules) on Compliance, and on Pro for the countries of your pack. A tax method on Pro adds the country to a pack that has room, as a tax endpoint would. Each bundle download counts as one request against the monthly quota.
  • private_mode also sets tax_id_mode="local" unless you set tax_id_mode yourself, so tax ID numbers are not sent either.
  • Other methods (countries, profiles, holiday watch, iCalendar feeds, withholding tax, treaties, finance law, account, webhooks) call the API as usual.
  • country_bundle(country, year, parts="all") returns a verified bundle, and verify_bundle(signed, public_key=...) checks one yourself.

Webhooks

from africa_compliance_data import verify_webhook

event = verify_webhook(request.body, request.headers["ACD-Signature"], WEBHOOK_SECRET)
# event["type"] == "dataset.changed"; event["changes"] lists the countries and features that changed.
# A retry carries the same event["id"] (header ACD-Event-Id): use it to ignore duplicates.

Full reference: africacompliancedata.com/docs · OpenAPI: openapi.json

License

MIT · Ingot Supply, LLC. MIT covers this client code only; API data is governed by the Terms of Service. Not legal or tax advice.

Metadata

Release files for africa-compliance-data 1.2.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 africa-compliance-data 1.2.0
File Size Uploaded Provenance
africa_compliance_data-1.2.0.tar.gz 40.7 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for africa-compliance-data 1.2.0
File Interpreter ABI Platform
africa_compliance_data-1.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 68.5 kB

Release files / africa_compliance_data-1.2.0.tar.gz

Download URL africa_compliance_data-1.2.0.tar.gz
Size 40.7 kB
Tags Source
SHA-256 checksum
How to use checksums
a7cc8aac185120c7bca323112b2cba7fb114c93f60f73b3895d8da77807575cb
BLAKE2b-256 checksum
How to use checksums
6e55e677de503a62b8acf9628566a5861c5ee42be7d839db128e0b1f73a6c7dd
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.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 Oct 24, 2026.

Transparency log

Release files / africa_compliance_data-1.2.0-py3-none-any.whl

Download URL africa_compliance_data-1.2.0-py3-none-any.whl
Size 27.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
cc44814f5b5753b7804dfd03561728cd4993ce52cb3ce3cd06a657b51cb67a22
BLAKE2b-256 checksum
How to use checksums
ffb77766ebe1685d78aaa8193f18a4c3da80ca4c1772bbe2c3ffc9ebe9cf5315
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.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 Oct 24, 2026.

Transparency log

Security for africa-compliance-data 1.2.0

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.

Select from 2 files

Attestation for africa_compliance_data-1.2.0.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 Oct 24, 2026.

Transparency log

A 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.

Release history Release notifications | RSS feed

This release

1.2.0 This release

2 release files Full provenance

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