Search by

codecruz / currency-flow

codecruz

Official ECB euro foreign exchange reference rates, with historical lookups and previous-business-day resolution.

Package info

github.com/codecruz/currency-flow-api

pkg:composer/codecruz/currency-flow

Statistics

Installs: 2

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v0.1.0 2026-11-09 08:29 UTC

This package is auto-updated.

Last update: 2026-11-09 09:19:01 UTC


README

Official euro foreign exchange reference rates from the European Central Bank, for PHP.

  • Latest, historical (since 1999-01-04) and range lookups.
  • Weekends and holidays resolve to the previous publication, and the response tells you so.
  • Rates are kept as published decimal strings, no float rounding.
  • Optional PSR-16 cache, with stale data served if the ECB is unreachable.
  • No HTTP client or framework required.

Installation

composer require codecruz/currency-flow

Requires PHP 8.2+ with ext-xmlreader.

Usage

use CodeCruz\CurrencyFlow\CurrencyFlow;

$flow = CurrencyFlow::ecb(cache: $psr16Cache); // cache is optional but recommended

$rate = $flow->rate('USD');                    // latest publication
$rate->value;                                  // "1.0827"  (1 EUR = 1.0827 USD)
$rate->date;                                   // DateTimeImmutable 2025-03-21

$rate = $flow->rate('USD', '2025-03-23');      // a Sunday
$rate->date->format('Y-m-d');                  // "2025-03-21"
$rate->isFallback();                           // true

$flow->rates('2025-03-21');                    // ['AUD' => Rate, 'BRL' => Rate, ...]
$flow->history('GBP', '2024-01-01', '2024-12-31'); // list<Rate>, publication days only
$flow->currencies();                           // ['AUD', 'BRL', 'CAD', ...]

$rate->toArray();
// ['base' => 'EUR', 'currency' => 'USD', 'rate' => '1.0827',
//  'date' => '2025-03-21', 'requested_date' => '2025-03-23', 'source' => 'ECB']

Dates can be YYYY-MM-DD strings or any DateTimeInterface, and are interpreted in the ECB's time zone (Europe/Berlin).

Errors

Every exception implements CodeCruz\CurrencyFlow\Exception\CurrencyFlowException.

Exception When
InvalidArgument Malformed currency code or date, future date, reversed range
UnknownCurrency The ECB does not publish that currency
RateNotAvailable No rate for that date (before the series, discontinued, or gap too long)
SourceUnavailable The ECB could not be reached and there is no cached copy
InvalidSourceData The ECB answered with data that failed validation and nothing is cached

Configuration

use CodeCruz\CurrencyFlow\CurrencyFlow;
use CodeCruz\CurrencyFlow\Provider\Ecb\EcbProvider;
use CodeCruz\CurrencyFlow\Http\NativeTransport;

$flow = new CurrencyFlow(
    provider: new EcbProvider(new NativeTransport(timeoutSeconds: 5)),
    cache: $psr16Cache,
    cacheTtl: 3600,          // seconds a cached feed is considered fresh
    staleTtl: 7 * 86400,     // seconds a cached feed is kept as fallback when the ECB is down
    maxLookbackDays: 7,      // max distance between requested and published date
    clock: $psr20Clock,      // optional, useful in tests
);

Implement CodeCruz\CurrencyFlow\Http\Transport to use your own HTTP client, or CodeCruz\CurrencyFlow\Provider\RateProvider to add another data source.

How data is fetched

The ECB publishes three feeds, used according to the date you ask for:

Request Feed Size
No date eurofxref-daily.xml ~2 KB
Within the last ~80 days eurofxref-hist-90d.xml ~40 KB
Older eurofxref-hist.xml several MB

Each feed is downloaded at most once per instance and once per cacheTtl when a cache is provided. The ECB updates rates around 16:00 CET on TARGET business days.

HTTP API

The server/ directory contains a ready-to-run HTTP API built on this library (Slim 4, file cache, RFC 7807 errors, ETags). It is not part of the Composer package.

cd server
composer install
composer serve            # http://127.0.0.1:8080
Endpoint Description
GET /v1/rates?date=YYYY-MM-DD All rates for a date (latest if omitted)
GET /v1/rates/{currency}?date=YYYY-MM-DD One currency
GET /v1/rates/{currency}/history?from=…&to=… Series between two dates
GET /v1/currencies Currencies in the latest publication
GET /health 200 when data is fresh, 503 otherwise
GET /openapi.yaml OpenAPI 3.1 specification

Configuration through environment variables: CACHE_DIR, CACHE_TTL (seconds, default 3600), SOURCE_TIMEOUT (seconds, default 10), CORS_ORIGIN (default *) and APP_DEBUG (1 to show error details).

Development

composer install
composer test
composer analyse

License

MIT