@unirate/remix
Remix / React Router 7 integration for the UniRate API — free currency exchange rates, historical data, and VAT rates.
Provides createUniRate() for use in loaders and actions, ready-made loader factories (createRateLoader, createConvertLoader, createCurrenciesLoader), and a proxy resource-route handler that keeps your API key server-side. Zero runtime dependencies.
Install
npm install @unirate/remix
Quick start
In any loader
// app/routes/pricing.ts
import { createUniRate } from "@unirate/remix/server";
const unirate = createUniRate(); // reads UNIRATE_API_KEY from env
export async function loader() {
const rate = await unirate.getRate("USD", "EUR");
const currencies = await unirate.listCurrencies();
return { rate, currencies };
}
Loader factories
// app/routes/rates.ts
import { createRateLoader } from "@unirate/remix/loaders";
// Reads `from` and `to` from ?from=USD&to=EUR
export const loader = createRateLoader({ defaultFrom: "USD" });
// In your component: const { rate, from, to } = useLoaderData<typeof loader>();
// app/routes/convert.ts
import { createConvertLoader } from "@unirate/remix/loaders";
// Reads ?from=USD&to=EUR&amount=100
export const loader = createConvertLoader();
// app/routes/currencies.ts
import { createCurrenciesLoader } from "@unirate/remix/loaders";
export const loader = createCurrenciesLoader();
// Returns { currencies: ["USD", "EUR", ...] }
Proxy resource route (keeps API key server-side)
// app/routes/api.unirate.ts
import { createUniRateProxyLoader } from "@unirate/remix/handler";
export const loader = createUniRateProxyLoader();
// Client calls: /api/unirate?path=/api/rates&from=USD&to=EUR
// api_key is injected server-side; never exposed to the client
API
createUniRate(opts?)
Returns a UniRate instance for use in server-only code (loaders, actions).
import { createUniRate } from "@unirate/remix/server";
const unirate = createUniRate({
apiKey: process.env.UNIRATE_API_KEY, // default: read from env
baseUrl: "https://api.unirateapi.com", // default
timeoutMs: 30_000, // default
});
// Methods
await unirate.getRate("USD", "EUR"); // → 0.92
await unirate.getRate("USD"); // → { EUR: 0.92, GBP: 0.79, ... }
await unirate.convert("USD", "EUR", 100); // → 92.34
await unirate.listCurrencies(); // → ["USD", "EUR", "GBP", ...]
await unirate.getVatRates(); // → { total_countries, vat_rates: {...} }
await unirate.getVatRates("DE"); // → { country: "DE", vat_data: {...} }
await unirate.getHistoricalRate("2025-01-01", "USD", "EUR"); // → 0.88 (Pro)
await unirate.getTimeSeries("2025-01-01", "2025-01-07"); // → { date: { EUR: 0.92 } } (Pro)
await unirate.getHistoricalLimits(); // → { total_currencies, currencies: {...} } (Pro)
Top-level helpers are also exported for convenience (read UNIRATE_API_KEY from env automatically):
import { getRate, convert, listCurrencies } from "@unirate/remix/server";
Loader factories
| Factory | Query params | Returns |
|---|---|---|
createRateLoader(opts?) |
?from=USD&to=EUR |
{ rate, from, to } |
createConvertLoader(opts?) |
?from=USD&to=EUR&amount=100 |
{ result, from, to, amount } |
createCurrenciesLoader(opts?) |
none | { currencies } |
All factories accept { apiKey?, baseUrl?, timeoutMs?, defaultFrom? }.
Proxy loader
import { createUniRateProxyLoader } from "@unirate/remix/handler";
const loader = createUniRateProxyLoader({
apiKey: process.env.UNIRATE_API_KEY, // default: read from env
allowedPaths: ["/api/rates", "/api/convert"], // default: all UniRate paths
timeoutMs: 30_000,
});
Allowed paths (default): /api/rates, /api/convert, /api/currencies, /api/vat/rates, /api/historical/rates, /api/historical/timeseries, /api/historical/limits.
Error handling
import { UniRateError, AuthenticationError, RateLimitError } from "@unirate/remix/client";
try {
const rate = await unirate.getRate("USD", "EUR");
} catch (err) {
if (err instanceof AuthenticationError) { /* invalid key */ }
if (err instanceof RateLimitError) { /* slow down */ }
if (err instanceof UniRateError) {
console.error(err.status, err.message);
}
}
Error classes: UniRateError (base) · AuthenticationError (401) · ProRequiredError (403) · InvalidCurrencyError (404) · RateLimitError (429) · InvalidRequestError (400).
Free vs Pro tier
Free tier: /api/rates, /api/convert, /api/currencies, /api/vat/rates. Historical endpoints require a Pro subscription.
Related packages
UniRate API client libraries: Python · Node.js · Go · Rust · Ruby · PHP · Java · Swift · .NET
Framework integrations: Next.js · Nuxt · SvelteKit · Astro · NestJS · Strapi · Remix (this package)
PHP ecosystem: Laravel Money · WordPress · Symfony Bundle
Data & AI: LangChain Python · FastAPI · Flask · Django REST · dbt · Airflow
Other: MCP server · CLI · Directus · Medusa · Home Assistant
License
MIT Unirate Team