Catalog PyPI
PACKAGE EXPLORERView in registry

afriref

PyPI

Official Python client for the afriref fleet: cited government reference data (rates, tax, wages, holidays, FX) for 137 countries

central-bankcomplianceexchange-ratesgovernmentpublic-holidaysreference-datataxvatx402
Versions collected1
Direct dependencies0From release 1.0.0
Last observed20 Oct, 21:11 UTC

README

Version 1.0.0 documentation

afriref — Python client

Cited government reference data as Python objects: central-bank policy rates, VAT, corporate and personal income tax, minimum wages, CPI, statutory interest, official central-bank FX fixes and public holidays across 137 countries.

Every value carries the official source URL it was verified against, the date it took effect, and the date we last re-checked it. Zero dependencies — standard library only.

pip install afriref

Start free

Nothing here needs a key, a wallet or an account.

from afriref import Client

c = Client()                          # afriref.dev (Africa)
print(c.holidays("za").value)         # full cited calendar — free, always
print(len(c.catalog()["countries"]))  # what exists
print(c.changes()["freshness"])       # how recently each value was re-verified

Seven regional services share one API. Pick the one that covers your country:

from afriref import Client, BRANDS
print(sorted(BRANDS))
# afriref, ausref, asiaref, euroref, latamref, mearef, usaref

eu = Client(brand="euroref")
bavaria = eu.holidays("de", subdivision="DE-BY")   # national + Land holidays

Paid values

c = Client(api_key="YOUR_KEY")        # buy credit at https://afriref.dev/pricing
v = c.series("za", "vat")

v.value            # 15
v.unit             # 'percent'
v.effective_from   # when it took legal effect — not when we published it
v.last_confirmed   # when we last re-read the official source
v.source_url       # the government document. Follow it and check us.
v.confidence       # 'primary' = read from the authority's own publication
v.stale            # past its expected update cycle?

Point-in-time, for the question that actually comes up in contracts:

gb = Client(brand="euroref")
gb.series("gb", "corporate-tax", as_at="2020-06-30").value   # 19
gb.series("gb", "corporate-tax").value                       # 25

Two things this client models that a plain HTTP wrapper gets wrong

A refusal is data, not a failure. When the service holds no verified answer it says so, with a machine-readable reason, and does not charge you. Catching Refused is the correct way to use this API:

from afriref import Client, Refused

try:
    c.working_days("ng", "2027-01-01", "2027-01-31")
except Refused as e:
    print(e.reason)      # 'calendar_not_publishable_in_advance'
    print(e.permanent)   # True — do NOT queue a retry

permanent=True means the answer will never become available: some public holidays are confirmed by moon sighting days ahead, or gazetted annually, so no amount of waiting produces the 2027 calendar. A client that retries these forever is the failure mode this flag exists to prevent.

HTTP 402 is a price quote, not an error. Without a key, paid endpoints answer with the exact price, asset and chain:

from afriref import PaymentRequired

try:
    c.series("za", "vat")
except PaymentRequired as e:
    print(e.price_usd, e.network, e.pay_to)   # 0.001 eip155:8453 0x1F04...

You can pay per call in USDC on Base with any x402 client — no account, no signup — or hold prepaid credit and pass api_key. Both rails, same data.

Everything else

c.history("gb", "corporate-tax")      # earlier values with effective ranges
c.snapshot()                          # every series, one call
c.vat("za", 1000)                     # net / tax / gross incl. levy components
c.income_tax("za", 650_000)           # tax due + per-bracket workings
c.wage_check("za", 5000, "monthly")   # at or above the statutory floor?
c.settlement_date("za", "2026-03-02") # T+n across statutory calendars
c.provenance("za", "vat")             # sha256 of the exact source bytes we read
c.status()                            # live service state and rate limits

Notes

  • history() returning an empty list means "not established", not "never changed". Where we hold no verified start date for a prior period we publish nothing rather than inventing one.
  • Each regional service answers only for its own countries. A NotFound on a valid country code usually means right country, wrong brand.
  • Free discovery routes are rate limited; paid data routes are not.

Independent service, not affiliated with any government. Verify against the cited official source before legal or financial use.

Docs: https://afriref.dev/docs · Accuracy record: https://afriref.dev/accuracy

Downloads & popularity

Awaiting observations

No metric observations yet

Download counts and popularity will appear here as the collector receives them.

Versions 1

Collected releases
VersionPublishedDirect dependenciesOpen version
1.0.03 Aug 20260

Package advisories

0
No matching advisories collected

This describes our collected data; it is not a security assessment.

Metadata history

Meaningful changes
Current collected state Current

Observed since 20 Oct, 21:11 UTC

No superseded metadata states collected. Unchanged observations do not create new revisions.

Record identity

package:5eab85fcc153bd0e9bad6a8c97d6658805ba90f1648a9fa276415eebb7ccfe50