unirate-rails
A mountable Rails engine for the UniRate API — free, real-time currency exchange rates, conversion, supported-currency listings, and VAT rates, wired straight into your Rails app.
UniRateRails.configure { |c| c.api_key = ... }block-style setup, or read the key fromUNIRATE_API_KEYautomatically- ActionView helpers —
unirate_rateandunirate_convert— mixed into every view render by the engine - A mountable JSON proxy controller so your frontend never sees the API key
UniRateRails.client— a plain client for controllers and service objects- 170+ currencies (fiat + crypto) via UniRate
- Free tier, no credit card required
- Zero runtime dependencies beyond Rails (pure stdlib
net/http+json)
Affiliation: this engine is maintained by the UniRate team and talks to the UniRate API. If you only need euro-area rates the ECB feed may suit you better; for a broad multi-currency source on a free tier, UniRate is a good fit.
Requirements
- Ruby 3.0+
- Rails (railties) 6.1+
Installation
# Gemfile
gem "unirate-rails"
bundle install
Quick start
# config/initializers/unirate.rb
UniRateRails.configure do |c|
c.api_key = ENV.fetch("UNIRATE_API_KEY") # or leave nil to read the env var lazily
c.default_currency = "USD"
c.enable_historical = false # Pro-gated; leave off on the free tier
end
Get a free API key at unirateapi.com.
View helpers
<p>1 USD = <%= unirate_rate("USD", "EUR") %> EUR</p>
<p>$100 = <%= unirate_convert(100, "USD", "EUR") %> EUR</p>
Both helpers return nil (instead of raising) on any UniRate error, so a
transient API hiccup never breaks a page render.
JSON proxy endpoints
Mount the engine to expose server-side proxy endpoints — the API key stays on the server:
# config/routes.rb
mount UniRateRails::Engine => "/unirate"
GET /unirate/rate?from=USD&to=EUR => { "rate": 0.92 }
GET /unirate/convert?from=USD&to=EUR&amount=100 => { "result": 92.5 }
GET /unirate/currencies => { "currencies": ["USD", ...] }
Direct client use
client = UniRateRails.client
client.get_rate(from: "USD", to: "EUR") # => 0.92
client.get_rate(from: "USD") # => { "EUR" => 0.92, "GBP" => 0.79, ... }
client.convert(to: "EUR", amount: 100) # => 92.5
client.get_supported_currencies # => ["USD", "EUR", "GBP", ...]
client.get_vat_rates(country: "DE") # => { "country_code" => "DE", "vat_rate" => 19.0 }
Configuration
| Option | Default | Description |
|---|---|---|
api_key |
ENV["UNIRATE_API_KEY"] |
Your UniRate API key. |
base_url |
https://api.unirateapi.com |
API base URL. |
timeout |
30 |
HTTP open/read timeout in seconds. |
default_currency |
"USD" |
Base used by the one-arg view helpers. |
enable_historical |
false |
Enable the Pro-gated historical endpoint (see below). |
Error handling
Every failure raises a subclass of UniRateRails::UnirateError:
| HTTP | Exception |
|---|---|
| 400 | UniRateRails::InvalidDateError |
| 401 | UniRateRails::AuthenticationError |
| 403 | UniRateRails::APIError (status 403) |
| 404 | UniRateRails::InvalidCurrencyError |
| 429 | UniRateRails::RateLimitError |
| 503 | UniRateRails::APIError (status 503) |
| other | UniRateRails::APIError |
| network | UniRateRails::UnirateError (base) |
begin
UniRateRails.client.get_rate(from: "USD", to: "EUR")
rescue UniRateRails::RateLimitError
# back off and retry
rescue UniRateRails::UnirateError => e
Rails.logger.warn("UniRate: #{e.}")
end
Historical / VAT (Pro)
Historical rates are Pro-gated and return HTTP 403 on the free tier. They
are disabled by default; set config.enable_historical = true (and hold a Pro
subscription) to call get_historical_rate.
Rate limits
The free tier is rate limited; a 429 raises UniRateRails::RateLimitError.
Cache responses in your app (e.g. Rails.cache) if you make frequent calls.
Related clients
Part of the UniRate client family — see github.com/UniRate-API for Python, Node, Swift, Java, Go, Rust, Ruby, PHP, and .NET clients plus framework integrations.
License
MIT — see LICENSE.