# TypeScript and the CurrencyCore API

> Use the official TypeScript SDK for typed convert, rates and history calls, then fall back to raw fetch when you need custom request options.

Canonical: https://currency-core.com/docs/guides/typescript/
Updated: 2026-11-11
Published: 2026-11-11

---
The official `@currencycore/sdk` is generated from the OpenAPI 3.1 contract, so the request and response types match the API. It resolves `CURRENCYCORE_API_KEY`, sets the base URL, and returns typed models. Use it unless you need a framework-specific fetch option that the generated client does not expose.

The SDK runs on Node.js 18 or later, modern browsers, and React Native. Do not put a secret key in a browser bundle. Free includes 1,000 requests per month at 60 per minute; test keys share the data and quota, capped at 60 per minute, and live keys require a paid plan.

```bash
npm install @currencycore/sdk
```

```ts

const api = createClient(); // reads CURRENCYCORE_API_KEY

try {
  const conversion = await api.convert({
    from: "USD",
    to: "INR",
    amount: 100,
  });
  const rates = await api.ratesByBase({ base: "EUR" });

  console.log(conversion.results[0].result, rates.rates.USD);
} catch (error) {
  if (error instanceof ResponseError) {
    const body = await error.response.json().catch(() => null);
    console.error(error.response.status, body?.error?.code);
  } else {
    throw error;
  }
}
```

The two endpoints return different envelopes. `/v1/convert` returns one entry per target, and `/v1/rates/{base}` returns a map with the base fixed at `1`:

```json
{
  "from": "USD",
  "amount": 100,
  "date": "2026-11-10",
  "results": [{ "to": "INR", "result": 8345.0, "rate": 83.45 }]
}
```

```json
{
  "base": "EUR",
  "date": "2026-11-10",
  "rates": { "EUR": 1, "USD": 1.0861, "INR": 91.62 }
}
```

`ResponseError` exposes the HTTP response, so you can read the shared error envelope. Branch on `error.code`, not the message. `400` means bad input, `401` a bad key, `403` a plan gate or the Free 30-day window, and `429` a rate limit. Honor `Retry-After` on a time-based `429`.

For a framework that needs a custom cache option, a zero-dependency script, or a request feature the SDK does not expose, call the API with `fetch` directly. The wire contract is the same.

Cache by `date`, base, and the request parameters. Historical dates are stable for normal caching, so they can live for a long time. Keep the response date; if a source revision appears, retain both observations. For today's snapshot, choose a TTL from your tolerance, not from an assumption of real-time updates.

## Next steps

- [Official SDKs](/docs/sdks/) for Python, Dart, Kotlin and Swift
- [API reference](/docs/api/) and [OpenAPI specification](/docs/openapi/)
- [Authentication](/docs/authentication/) and [error codes](/docs/errors/)
- [All developer guides](/docs/guides/)
