Packages

A fully-typed Elixir client for the Federal Reserve Economic Data (FRED) API. Covers all 36 endpoints: categories, releases, series, sources, tags, GeoFRED and bulk v2.Includes intelligent Cachex-backed caching with frequency-aware TTLs.

Current section

Files

Jump to
fred_api_client CHANGELOG.md
Raw

CHANGELOG.md

# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
## [0.1.0] - 2026-03-12
### Added
#### Core
- Full coverage of all **36 FRED API endpoints** across 7 modules:
- `FredApiClient.Categories` — 6 endpoints
- `FredApiClient.Releases` — 9 endpoints
- `FredApiClient.Series` — 10 endpoints
- `FredApiClient.Sources` — 3 endpoints
- `FredApiClient.Tags` — 3 endpoints
- `FredApiClient.Maps` — 4 endpoints (GeoFRED)
- `FredApiClient.V2` — 1 endpoint (bulk)
- Top-level `FredApiClient` module with `defdelegate` shortcuts for all 36 endpoints
- Application config support via `config :fred_api_client, api_key: ...`
- Explicit per-call config support for multi-tenant / per-request API key usage
- `Req`-based HTTP client with per-request timeout and structured error handling
- `FredApiClient.Error` exception struct with `code`, `status`, `message` fields
#### Caching (`FredApiClient.Cache`)
- Cachex-backed in-process caching, started automatically by the OTP application
- **Frequency-aware TTLs** for `Series.get_observations/2`:
- Daily / weekly (`d`, `w`, `bw` and weekly variants) → **not cached**
- Monthly (`m`) → **1 h**
- Quarterly / semi-annual / annual (`q`, `sa`, `a`) → **6 h**
- Unspecified frequency → **not cached** (safe default)
- Static data cached aggressively: category tree and series metadata at **24 h**,
release metadata at **12 h**, GeoFRED shapes at **24 h**, regional data at **2 h**
- Volatile endpoints intentionally not cached: `Series.search/2`,
`Series.get_updates/2`, `Tags.get_series/2`, V2 bulk
- `Cache.invalidate/1` — delete a single key
- `Cache.invalidate_prefix/1` — delete all keys under a prefix (e.g. `"fred:categories:"`)
using `Cachex.stream!` + `Cachex.Query.build(output: :key)` for safe ETS iteration
- `Cache.clear/0` — flush entire cache
- `Cache.stats/0` — hit rate, size, eviction counts via `Cachex.stats/1`
- `Cache.build_key/3` — deterministic, order-independent key builder (MD5 of sorted params)
- Global on/off via `config :fred_api_client, cache_enabled: false`
- Per-bucket TTL overrides via `config :fred_api_client, ttl_overrides: %{...}`
- Configurable cache process name via `config :fred_api_client, cache_name: :my_cache`
#### Rate Limiting
- Automatic **exponential backoff retry** on `HTTP 429 Too Many Requests`
(FRED enforces 120 requests/minute per API key)
- Default: 3 retries with 20 s base delay (20 s → 40 s → 60 s), safely within
FRED's 60 s rate-limit window
- `HTTP 503 Service Unavailable` also retried with a 5 s base delay
- Transport-level `:timeout` errors retried with a 3 s base delay
- Terminal errors (400, 404, 423, 500) returned immediately without retry
- Configurable via `rate_limit_max_retries` and `rate_limit_base_delay_ms`
#### Documentation & Quality
- ExDoc documentation with grouped modules (API, HTTP, Cache)
- Dialyzer typespecs on all public functions
- Credo strict-mode static analysis (`.credo.exs`)
- ExCoveralls test coverage with `lcov` reporter
- Bypass-based integration tests — no real HTTP calls in the test suite
- GitHub Actions CI: lint → test matrix (Elixir 1.15/1.16/1.17 × OTP 26/27)
→ Dialyzer → Hex publish on master push
### Fixed
- `Cache.invalidate_prefix/1`: replaced non-existent `Cachex.filter!/2` and
`Cachex.Entry.key/1` with correct `Cachex.stream!(query)` +
`Cachex.Query.build(output: :key)` pattern; keys are buffered before deletion
to avoid mutating the ETS table during iteration