Skip to content

OpenExchange

github-actions[bot] edited this page Oct 4, 2026 · 2 revisions

Open Exchange Rates

Typed Open Exchange Rates API client for Deno, Bun, Node.js and Cloudflare Workers. Latest and historical currency exchange rates, time series, currency conversion, OHLC data and account usage.

JSR JSR Score

Overview

OpenExchange provides validated latest, historical, time-series, conversion, currency, status, and OHLC responses. It uses RESTler for transport and Guardian for runtime response validation.

Testing your code

Your tests don't need to fake HTTP. Have your code take an OpenExchange instance and pass in a stand-in that returns the shapes from @tundraconnect/openexchange/schemas or throws a real OpenExchangeError:

import { OpenExchangeError } from '@tundraconnect/openexchange/errors';

const outage = new OpenExchangeError('SERVICE_UNAVAILABLE', { status: 503 });
console.log(outage.code);

To exercise the client itself against a fake transport, subclass it and reassign the protected _fetch.

Documentation

Topic Description
API Client configuration and endpoint methods
Errors Error codes and diagnostic metadata
Schemas Public Guardian schemas and inferred types

Upstream

Installation

Deno:

deno add jsr:@tundraconnect/openexchange

Bun:

bunx jsr add @tundraconnect/openexchange

Node.js:

npx jsr add @tundraconnect/openexchange

Quick Start

import { OpenExchange } from '@tundraconnect/openexchange';

const client = new OpenExchange({
  auth: { type: 'CUSTOM', appId: 'your-app-id' },
});
const rates = await client.getRates({ base: 'USD', symbols: ['EUR'] });

console.log(rates.EUR);

Migrating from 0.1.x

0.2.0 is the first release built on the current RESTler/Guardian conventions. The method signatures, return types, and every exported schema and error name are unchanged. What changes:

1. The App ID moves under auth (a compile error until updated):

// 0.1.x
const client = new OpenExchange({ appId: 'your-app-id' });

// 0.2.0
const client = new OpenExchange({
  auth: { type: 'CUSTOM', appId: 'your-app-id' },
});

2. Some errors now carry a more accurate code. Code that branches on OpenExchangeError should check these:

Situation 0.1.x 0.2.0
HTTP 429 (rate limited) RESPONSE_ERROR RATE_LIMITED, with retryAfterSeconds in context
An undocumented 4xx (e.g. 418) SERVICE_UNAVAILABLE — or returned as success if the body happened to validate UNKNOWN_ERROR
getHistoricalRates() with a non-YYYY-MM-DD date sent to the vendor rejected locally with INVALID_DATE, no request

3. Additions (non-breaking): every error exposes a readonly code, so you can branch on error.code === 'RATE_LIMITED' instead of matching .message; and passing maxRetryWait at construction makes the client wait out a rate-limit hint and retry once — see Errors.

License

MIT. Part of Tundra Connect, typed vendor API clients for Deno, Bun, Node.js and Cloudflare Workers.

Clone this wiki locally