Add UniRateAPI service - #180
Merged
Merged
Conversation
Adds `Exchanger\Service\UniRateApi` (registry identifier `unirate_api`), covering both latest and historical rate queries against https://unirateapi.com. The free tier supports the latest endpoint with all 170+ currencies; historical rates require a paid plan and are surfaced through the same `HistoricalExchangeRateQuery` path so chaining and caching work unchanged. Tests follow the FastForex pattern (mocked HTTP adapter + JSON fixtures). Psalm baseline updated with the same `MissingOverrideAttribute` entries used for the other services. - src/Service/UniRateApi.php new HttpService implementation - src/Service/Registry.php register `unirate_api` - tests/Tests/Service/UniRateApiTest.php 8 tests, 36 assertions - tests/Fixtures/Service/UniRateApi/ latest, historical, error - README.md + doc/readme.md service tables + count bumped to 31 - psalm-baseline.xml MissingOverrideAttribute entries
There was a problem hiding this comment.
Pull request overview
Adds a new UniRateApi service provider to Exchanger, registered as unirate_api, supporting both latest and historical exchange rate queries with an api_key option. Mirrors the structure of existing services such as FastForex.
Changes:
- New
Exchanger\Service\UniRateApiclass implementingHttpService+SupportsHistoricalQuerieswithprocessOptions,getLatestExchangeRate,getHistoricalExchangeRate. - Registered alias
unirate_apiinRegistryand added Psalm baseline entries. - New PHPUnit tests + JSON fixtures and provider table/count updates in README/doc.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| src/Service/UniRateApi.php | New service class for UniRateAPI endpoints (latest + historical). |
| src/Service/Registry.php | Registers unirate_api alias. |
| tests/Tests/Service/UniRateApiTest.php | Unit tests covering options, queries, errors, and naming. |
| tests/Fixtures/Service/UniRateApi/*.json | Mock JSON responses for tests. |
| README.md | Updates provider count 30 → 31 and adds row to commercial table. |
| doc/readme.md | Adds UniRateApi row to options table. |
| psalm-baseline.xml | Adds MissingOverrideAttribute entries for new class methods. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
alies-dev
approved these changes
May 18, 2026
alies-dev
left a comment
Collaborator
There was a problem hiding this comment.
Hey @rob-browncc
Thank you for the contribution — looks great! I'll tune Psalm and docs to make the PR workflow even more friendly.
Thank you again!
This was referenced May 21, 2026
alies-dev
pushed a commit
to florianv/swap
that referenced
this pull request
Jun 17, 2026
Exchanger merged UniRateAPI support in florianv/exchanger#180. Swap auto-inherits provider services from Exchanger's Registry, so `->add('unirate_api', ['api_key' => getenv('UNIRATE_API_KEY')])` already works on master; only the docs were missing. - README.md: add row to commercial providers table (alphabetical position between `open_exchange_rates` and `webservicex`); bump provider counts 30 → 31 in tagline, providers section, and the Exchanger sibling-package line. - doc/readme.md: add `unirate_api` / `api_key` row to the commercial config table. UniRateAPI is a commercial REST API for FX (latest rates on the free tier; historical and commodities on the paid tier — same shape as the other paid providers in the table).
alies-dev
pushed a commit
to florianv/laravel-swap
that referenced
this pull request
Jun 17, 2026
Exchanger merged UniRateAPI support in florianv/exchanger#180 and Swap's docs PR is florianv/swap#155. Laravel Swap auto-inherits the underlying Swap service list, so `'unirate_api' => ['api_key' => env(...)]` already works on master once the next Exchanger release tag lands; only the docs and the published config stub were missing. - config/swap.php: add `unirate_api` to the in-file docblock spec list (after `xchangeapi`) and add a commented-out example line to the `services` array next to the other commercial providers, mirroring the existing `apilayer_fixer` / `open_exchange_rates` examples. - README.md: add `UniRateAPI` row to the commercial provider table (alphabetical, between `open_exchange_rates` and `webservicex`); bump count 30 → 31. - doc/readme.md: add `unirate_api` / `api_key` row to the commercial configuration table. UniRateAPI is a commercial REST API for FX. Latest rates are on the free tier; historical and commodities are paid-tier only — the upstream `Exchanger\Service\UniRateApi` maps HTTP 403 on those endpoints to `Exchanger\Exception\ChainException`, matching the existing fastFOREX / Fixer plan-gated behaviour.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Adds
Exchanger\Service\UniRateApi(registry identifierunirate_api) — a new commercial provider for UniRateAPI.Why
UniRateAPI is a free-tier-first JSON FX API covering ~170 fiat + crypto currencies, historical rates back to 1999 (paid), and the usual conversion / time-series / VAT endpoints. Adding it to Exchanger gives users a no-credit-card-required option to drop into a
Chainalongside or in front of ECB/Fixer/fastFOREX.Surface
Exchanger\Service\UniRateApi extends HttpServicewithSupportsHistoricalQueriesapi_keyGET /api/rates?api_key=…&from=…&to=…→{"rate": "0.92"}GET /api/historical/rates?api_key=…&date=YYYY-MM-DD&from=…&to=…→{"rate": "0.91"}(paid plan)unirate_apiFastForexTest)phpunitfull suite: 285 tests, 1380 assertions — all green on PHP 8.3 inside the container I testedpsalmclean (baseline updated with the sameMissingOverrideAttributeentries already used for the other services)doc/readme.mdprovider tables updated; provider count bumped 30 → 31Files
src/Service/UniRateApi.php— newsrc/Service/Registry.php— register aliastests/Tests/Service/UniRateApiTest.php— newtests/Fixtures/Service/UniRateApi/{rate-usd-eur,historical-usd-eur,error-invalid-currency}.json— newREADME.md+doc/readme.md— service tables + countpsalm-baseline.xml—MissingOverrideAttributebaseline parityDisclosure
I work on UniRateAPI. The PR is intentionally additive and follows the existing service pattern (closest reference:
FastForex/CurrencyDataFeed). Happy to take a different naming choice for the registry alias, drop the README mentions, or split the doc edit out — let me know.