UniRate API exchange-rate integration for Medusa v2 — register a currency service module in your Medusa app to get real-time FX rates, currency conversion, historical rates (Pro), and VAT rates, with zero runtime dependencies.
npm install medusa-plugin-unirateGet a free API key at unirateapi.com.
import { defineConfig } from "@medusajs/framework/utils"
export default defineConfig({
// ... your existing config
modules: [
{
resolve: "medusa-plugin-unirate",
options: {
apiKey: process.env.UNIRATE_API_KEY,
baseCurrency: "USD", // default base for getRates() calls
},
},
],
})Or use the typed helper:
import { createUniRateModule } from "medusa-plugin-unirate"
export default defineConfig({
modules: [
createUniRateModule({ apiKey: process.env.UNIRATE_API_KEY }),
],
})import { UNIRATE_MODULE } from "medusa-plugin-unirate"
import type { UniRateCurrencyModuleService } from "medusa-plugin-unirate"
// In a Medusa workflow step:
export const convertCurrencyStep = createStep(
"convert-currency",
async (input: { amount: number; from: string; to: string }, { container }) => {
const unirate = container.resolve<UniRateCurrencyModuleService>(UNIRATE_MODULE)
const converted = await unirate.convert(input.amount, input.from, input.to)
return new StepResponse({ converted })
},
)
// In a custom API route:
export const GET = async (req: MedusaRequest, res: MedusaResponse) => {
const unirate = req.scope.resolve<UniRateCurrencyModuleService>(UNIRATE_MODULE)
const rates = await unirate.getRates("USD")
res.json({ base: "USD", rates })
}All methods are on UniRateCurrencyModuleService, resolved from Medusa's container via UNIRATE_MODULE.
// All rates relative to a base currency (defaults to module's baseCurrency)
const rates: Record<string, number> = await unirate.getRates()
const rates: Record<string, number> = await unirate.getRates("EUR")
// Single currency pair
const rate: number = await unirate.getRate("USD", "EUR") // e.g. 0.92// Convert an amount between two currencies
const result: number = await unirate.convert(100, "USD", "EUR") // e.g. 92.00// List all supported currency codes
const currencies: string[] = await unirate.listCurrencies()
// ["USD", "EUR", "GBP", "JPY", ...]Historical endpoints require a UniRate Pro subscription.
// Single historical rate
const rate: number = await unirate.getHistoricalRate("2024-01-15", "USD", "EUR")
// All historical rates for a date
const rates: Record<string, number> = await unirate.getHistoricalRates("2024-01-15", "USD")
// Historical conversion
const result: number = await unirate.convertHistorical(500, "USD", "EUR", "2024-01-15")
// Date range series
const series: Record<string, Record<string, number>> = await unirate.getTimeSeries(
"2024-01-01",
"2024-01-07",
"USD", // base (optional, defaults to module's baseCurrency)
["EUR", "GBP"], // filter currencies (optional)
)
// Per-currency data availability
const limits = await unirate.getHistoricalLimits()// All countries
const all = await unirate.getVatRates()
// { total_countries: 50, date: "...", vat_rates: { DE: { vat_rate: 19, ... }, ... } }
// Single country (ISO 3166-1 alpha-2)
const de = await unirate.getVatRates("DE")
// { country: "DE", vat_data: { country_code: "DE", country_name: "Germany", vat_rate: 19 } }| Option | Type | Default | Description |
|---|---|---|---|
apiKey |
string |
UNIRATE_API_KEY env var |
UniRate API key |
baseCurrency |
string |
"USD" |
Default base for getRates() and time-series calls |
baseUrl |
string |
https://api.unirateapi.com |
Override the API base URL |
timeoutMs |
number |
30000 |
Request timeout in milliseconds |
All errors extend UniRateError. Specific subtypes:
| Class | HTTP status | When |
|---|---|---|
AuthenticationError |
401 | Missing or invalid API key |
ProRequiredError |
403 | Endpoint requires a Pro subscription |
InvalidCurrencyError |
404 | Currency not found or no data |
InvalidRequestError |
400 | Invalid request parameters |
RateLimitError |
429 | Rate limit exceeded |
UniRateError |
— | Network error or unexpected response |
import { ProRequiredError, UniRateError } from "medusa-plugin-unirate"
try {
const rate = await unirate.getHistoricalRate("2024-01-01", "USD", "EUR")
} catch (err) {
if (err instanceof ProRequiredError) {
// endpoint needs Pro subscription
} else if (err instanceof UniRateError) {
console.error(err.status, err.message)
}
}UniRate client libraries: Python · Node.js · Go · Rust · Ruby · PHP · Java · Swift · .NET
Framework integrations: Next.js · NestJS · SvelteKit · Nuxt · Vue · React · Astro · Eleventy · Hugo · Jekyll
Backend / data integrations: Django · FastAPI · Flask · Wagtail · LangChain · Airflow · dbt · Directus · Laravel
Money library adapters: Ruby Money gem
Tools: CLI · MCP server · VS Code · Obsidian · n8n
UniRate ships official integrations for 40+ ecosystems, all maintained under the UniRate-API org.
Core clients (9 languages) Python · Node.js / TypeScript · Go · Rust · Java · Ruby · PHP · .NET · Swift
JavaScript / TypeScript React · Next.js · Remix · SvelteKit · Vue · Angular · Nuxt · NestJS · tRPC
Static-site generators Astro · Eleventy · Hugo · Jekyll
CMS & e-commerce Wagtail · WordPress · WooCommerce · Drupal · Strapi · Medusa · Symfony · Laravel · Directus
Data, AI & backend LangChain (Python) · LangChain.js · FastAPI · Flask · Django REST Framework · Apache Airflow · dbt
Platform & tools MCP server · CLI · Cloudflare Workers · Home Assistant · n8n · Google Sheets · VS Code · Obsidian
Money library bridges money gem (Ruby) · NodaMoney (.NET)
Get a free API key at unirateapi.com.
MIT — see LICENSE.