Metadata-Version: 2.5
Name: allowances-api
Version: 1.0.0
Summary: Official Python SDK for the Allowances API
Project-URL: Homepage, https://www.allowancesapi.com
Project-URL: Documentation, https://www.allowancesapi.com/docs
Project-URL: Repository, https://github.com/allowances-api/allowances-api-python
Project-URL: Issues, https://github.com/allowances-api/allowances-api-python/issues
Author-email: Allowances API <contact@allowancesapi.com>
License-Expression: MIT
License-File: LICENSE
Keywords: allowances,dssr,dtmo,gsa,per-diem,travel
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
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: Typing :: Typed
Requires-Python: >=3.9
Requires-Dist: httpx<1,>=0.25
Provides-Extra: dev
Requires-Dist: build>=1.2; extra == 'dev'
Requires-Dist: packaging>=24; extra == 'dev'
Requires-Dist: pytest-cov>=5; extra == 'dev'
Requires-Dist: pytest>=8; extra == 'dev'
Requires-Dist: ruff>=0.9; extra == 'dev'
Requires-Dist: tomli>=2; (python_version < '3.11') and extra == 'dev'
Requires-Dist: twine>=6; extra == 'dev'
Description-Content-Type: text/markdown

# Allowances API Python SDK

The official Python client for [Allowances API](https://www.allowancesapi.com), a normalized API for U.S. government travel and overseas compensation data.

The API brings together rates published by three different government sources:

- **DSSR** — overseas post allowance (COLA), hardship differential, danger pay, education allowance, living quarters allowance, and foreign per diem.
- **DTMO** — military per diem for CONUS and OCONUS locations.
- **GSA** — civilian CONUS per diem, mileage reimbursement, and Fleet vehicle leasing rates.

This SDK handles API-key authentication, URL construction, parameter serialization, response decoding, and useful Python exceptions. It is useful for travel platforms, expense systems, payroll and mobility tools, government contractors, and internal applications that need current or historical allowance data without maintaining scrapers for several unrelated sources.

## Installation

```bash
pip install allowances-api
```

Python 3.9 or newer is required.

## Authentication

Create an API key at [allowancesapi.com](https://www.allowancesapi.com), then provide it directly:

```python
from allowances_api import AllowancesClient

client = AllowancesClient("ak_live_your_key")
```

For applications, keeping the key in an environment variable is preferable. The client will find your api key if you set it explicitely as ALLOWANCES_API_KEY.

```bash
export ALLOWANCES_API_KEY="ak_live_your_key"
```

```python
from allowances_api import AllowancesClient

client = AllowancesClient()  # reads ALLOWANCES_API_KEY
```

Every request sends the key in the API's `X-API-Key` header. Do not embed a secret API key in browser or mobile client code.

## Quick start

Use the client as a context manager so its connection pool is closed automatically:

```python
from datetime import date
from allowances_api import AllowancesClient

with AllowancesClient() as client:
    # Overseas allowances for Nairobi
    kenya = client.dssr.allowances_by_location(
        "KE",
        "Nairobi",
        date=date.today(),
        type=["cola", "hardship", "danger_pay"],
    )

    # Military OCONUS per diem
    australia = client.dtmo.perdiem_oconus("AU", query="Adelaide")

    # Civilian CONUS per diem
    albany = client.gsa.perdiem_by_state("NY", location="Albany")
```

Responses are returned as decoded dictionaries or lists, matching the documented JSON response exactly.

## Common use cases

### Look up an overseas post allowance and calculate COLA

```python
rates = client.dssr.allowances_by_postcode("BE", "10112", types=["cola"])

estimate = client.dssr.calculate_cola(
    "10112",
    family_size=4,
    base_salary=100_000,
)
print(estimate["annual_cola"], estimate["biweekly_cola"])
```

### Retrieve per diem by source

```python
# Department of State foreign per diem
dssr = client.dssr.perdiem_by_location("KE", "Nairobi")

# Defense Travel Management Office military rates
dtmo = client.dtmo.perdiem_conus("US-CO", query="Aspen")

# General Services Administration civilian rates
gsa = client.gsa.perdiem_by_zipcode("12207")
```

### Mileage and GSA Fleet rates

```python
mileage = client.gsa.mileage(mileage_type="automobile")
fleet = client.gsa.vehicle_rates("standard", "10B", year=2026)
```

### Browse locations

```python
countries = client.dssr.countries(query="United")
dssr_locations = client.dssr.country_locations("DE")
dtmo_locations = client.dtmo.locations_oconus("AU", location="Sydney")
states = client.gsa.states()
destinations = client.gsa.destinations(limit=50)
```

### Calculate mileage and trip per diem

```python
reimbursement = client.gsa.calculate_mileage(
    distance=125.5,
    vehicle_type="automobile",
    date="2026-07-11",
)

trip = client.gsa.calculate_perdiem_trip(
    stops=[{
        "location": {"zipcode": "20001"},
        "arrival_date": "2026-10-01",
        "departure_date": "2026-10-03",
        "lodging_cost_per_night": 250,
    }],
    deductible_meals=[{"date": "2026-10-02", "meals": ["breakfast"]}],
    verification_url=True,
)

meals = client.gsa.mie_breakdowns(region="conus", date="2026-10-01")
```

Calculator requests use JSON bodies. Stop and meal-deduction dates accept ISO date
strings or Python `date` objects. The API validates the request and calculates the result.

### Check account usage and data publications

```python
account = client.me()
publications = client.meta.latest()
```

## Errors

The SDK maps common status codes to specific exceptions:

```python
from allowances_api import ForbiddenError, NotFoundError, RateLimitError

try:
    result = client.dssr.perdiem("XX")
except NotFoundError as exc:
    print(exc.status_code, exc.message, exc.request_id)
except ForbiddenError:
    print("This request is not included in the current plan")
except RateLimitError:
    print("Request limit reached")
```

Available exception classes are `AuthenticationError`, `ForbiddenError`, `NotFoundError`, `ValidationError`, `RateLimitError`, `TransportError`, and the base `AllowancesAPIError`.

## Configuration

Use a different endpoint or timeout for local development and testing:

```python
client = AllowancesClient(
    "test-key",
    base_url="http://localhost:8000/v1",
    timeout=10,
)
```

An existing `httpx.Client` can be injected for custom transports, proxies, telemetry, or testing:

```python
import httpx
from allowances_api import AllowancesClient

transport = httpx.HTTPTransport(retries=2)
http = httpx.Client(base_url="https://api.allowancesapi.com/v1", transport=transport)
client = AllowancesClient("ak_live_your_key", http_client=http)
```

When injecting a client, its lifecycle remains owned by the caller.

## Endpoint mapping

SDK methods follow the API's three source groups:

- `client.dssr`: allowances, per diem, COLA calculator, countries, and locations.
- `client.dtmo`: CONUS/OCONUS per diem, search, and locations.
- `client.gsa`: destination/state/ZIP per diem, ZIP and county metadata, mileage,
  vehicle rates, M&IE breakdowns, and mileage/trip calculators.
- `client.meta.latest()`: latest data publications.
- `client.me()`: account information and current billing-period usage.

See the [API reference (OpenAPI specification)](https://www.allowancesapi.com/openapi.json) for endpoint definitions, request parameters, and response schemas.

## Development and publishing

```bash
python -m venv .venv
source .venv/bin/activate
pip install -e '.[dev]'
pytest
ruff check .
python -m build
twine check dist/*
```

Before publishing, choose an unused version (for example, `0.1.1`) and update:

- `version` under `[project]` in `pyproject.toml`.
- `__version__` in `src/allowances_api/__init__.py`.
- Both `allowances-api-python/<version>` User-Agent strings in `src/allowances_api/client.py`.

Use the same version in all three files. PyPI does not allow replacing an already
published release file. Use a patch bump for fixes (for example, `0.1.1`) or a minor
bump for new features (for example, `0.2.0`).

Compare the local `pyproject.toml` version with the latest published release on PyPI:

```bash
make check-pip-version
```

The command reports whether the local version is newer, older, or the same, or
whether the package has no published release. Lookup failures return a nonzero
exit status. Version differences are informational and do not fail the command.

Run the tests, then build, validate, and upload the release to PyPI:

```bash
make publish
```

The command uses `.venv/bin/python` by default; override it with
`make publish PYTHON=python` if needed. Each run builds into a fresh directory under
`dist/`, checks the artifacts with Twine, and uploads only those new artifacts.
If building or validation fails, the upload does not run.

Twine uses your configured PyPI credentials or prompts for them. For API-token
authentication, use `__token__` as the username and your PyPI token as the password.
Keep the token out of Git.

## License

MIT

