Metadata-Version: 2.4
Name: afriref
Version: 1.0.0
Summary: Official Python client for the afriref fleet: cited government reference data (rates, tax, wages, holidays, FX) for 137 countries
Author-email: "3L Group Consulting (PTY) LTD" <api@3l-groupconsulting.co.za>
License: MIT
Project-URL: Homepage, https://afriref.dev
Project-URL: Documentation, https://afriref.dev/docs
Project-URL: Accuracy, https://afriref.dev/accuracy
Project-URL: Status, https://afriref.dev/status
Project-URL: Pricing, https://afriref.dev/pricing
Project-URL: Support, https://afriref.dev/docs
Keywords: reference-data,government,tax,vat,public-holidays,exchange-rates,central-bank,x402,compliance
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Financial and Insurance Industry
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Topic :: Office/Business :: Financial
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: license-file

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

```bash
pip install afriref
```

## Start free

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

```python
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:

```python
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

```python
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:

```python
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:

```python
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:

```python
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

```python
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>
