APIs and backends

EU VAT number validator API with caching

FastAPI service that validates EU VAT numbers via VIES, returns registered company details, and caches definitive results with a TTL.

pythonfastapihttpxpydanticpytestuv

Built 1 time, downloaded 0 times.

Install from your terminal

Run this in your project folder. It signs you in, shows what changes and asks before it overwrites a file.

npx claude-lab add eu-vat-number-validator-api-with-caching-8db9b3
CLAUDE.md
# the app

FastAPI service that validates EU VAT numbers against the VIES service and returns the registered company name and address. GET /vat/{country}/{number} returns a JSON object with the valid flag, name, address, source, cached status and checked_at time. Results are cached with a TTL, and a /health route reports service status without calling VIES.

## Commands

- `uv sync` installs dependencies from the lockfile.
- `uv run uvicorn app.main:app --reload` starts the dev server on port 8000.
- `uv run pytest -q` runs the tests.
- `uv run ruff check .` runs lint.
- `uv run ruff format --check .` checks formatting.
- `uv run mypy app` runs type checks on the app package.

## Layout

- `app/main.py`: routes and the app factory. Routes call service functions and hold no business logic.
- `app/vies_client.py`: HTTP client for VIES. This is the only module that makes network calls.
- `app/cache.py`: TTL cache with LRU eviction, behind a small Protocol with an injectable clock.
- `app/models.py`: Pydantic request and response models.
- `app/config.py`: settings read from environment variables.
- `tests/`: pytest tests. VIES is mocked with respx. Fixtures live in `tests/fixtures/`.
- `SPEC.md`: expected behavior. Tests should map to it.
- `PLAN.md`: phased build plan.
- `REVIEW.md`: review rules, imported below.

## Gotchas

- Normalize input first. Strip spaces, dashes and dots, uppercase the value, then check the 2-letter prefix.
- Greece uses the prefix EL, not GR. Check `vies-client` skill notes before changing prefix handling.
- VIES is sometimes unavailable or rate limited. Map upstream timeouts and 5xx responses to 503 with a Retry-After header.
- Never cache upstream errors or timeouts. Cache only definitive answers (valid or invalid).
- Never log a full VAT number at INFO level. Log a masked form.
- Use fake VAT numbers and recorded JSON in tests. Never commit real company data.

## Rules

- Use `httpx.AsyncClient` with an explicit timeout. The default is 5 seconds, set by an environment variable. Do not use bare `requests` calls.
- Keep all network calls inside `app/vies_client.py`.
- No secrets in code. Read config from environment variables and document each one in `.env.example` with placeholder values only. Never create or commit a real `.env`.
- Add a dependency only with a one-line reason in the PR description.
- Every change ends with the `verify` skill passing. Show the command output before saying a task is done. Do not skip steps.
- Use the injected clock in tests. Do not use `sleep()`.

@REVIEW.md
Use for my project