A lightweight, production-ready TypeScript SDK for the Frankfurter currency API.
It stays close to the HTTP API, uses fetch, ships type declarations, and works in modern Node.js and browsers.
npm install frankfurter-jsimport { FrankfurterClient } from "frankfurter-js";
const client = new FrankfurterClient();
const latest = await client.latest({
base: "USD",
quotes: ["EUR", "GBP"]
});The default base URL is https://api.frankfurter.dev. The client targets the OpenAPI server path at /v2 internally.
import { FrankfurterClient, createFrankfurterClient } from "frankfurter-js";
const client = new FrankfurterClient({
timeout: 5_000
});
const clientFromFactory = createFrankfurterClient();Thin mapping to GET /rates.
const rates = await client.rates({
date: "2025-01-10",
base: "EUR",
quotes: ["USD", "CHF"],
providers: ["ECB"],
});Convenience method for the latest rates.
const latest = await client.latest({
base: "USD",
quotes: ["EUR", "GBP"]
});Convenience method for a specific date.
const historical = await client.historical("2025-01-10", {
base: "EUR",
quotes: "USD"
});Convenience method for date ranges.
const ranged = await client.range("2025-01-01", "2025-01-31", {
base: "EUR",
quotes: ["USD", "CHF"],
group: "month"
});Maps to GET /currencies.
const currencies = await client.currencies();
const allCurrencies = await client.currencies({ scope: "all" });Maps to GET /providers.
const providers = await client.providers();import { FrankfurterClient } from "frankfurter-js";
const client = new FrankfurterClient({
baseUrl: "https://rates.example.com"
});import { FrankfurterClient } from "frankfurter-js";
const client = new FrankfurterClient({
fetch: window.fetch.bind(window)
});const client = new FrankfurterClient({
timeout: 5_000
});
const controller = new AbortController();
const rates = await client.latest(
{ base: "EUR", quotes: ["USD"] },
{ signal: controller.signal }
);Non-2xx responses throw FrankfurterError.
import { FrankfurterClient, FrankfurterError } from "frankfurter-js";
const client = new FrankfurterClient();
try {
await client.historical("invalid-date");
} catch (error) {
if (error instanceof FrankfurterError) {
console.error(error.status);
console.error(error.statusText);
console.error(error.url);
console.error(error.body);
}
}import type { Currency, Provider, Rate } from "frankfurter-js";
import { FrankfurterClient } from "frankfurter-js";
const client = new FrankfurterClient();
const rates: Rate[] = await client.latest({ base: "EUR", quotes: ["USD"] });
const currencies: Currency[] = await client.currencies();
const providers: Provider[] = await client.providers();quotesandprovidersaccept either a comma-separated string or a string array.- Query serialization follows the OpenAPI contract and sends comma-separated values for list params.
- The SDK intentionally does not add retries, caching, or response reshaping.
npm install
npm run build
npm test