> ## Documentation Index
> Fetch the complete documentation index at: https://docs.financialdatapi.com/llms.txt
> Use this file to discover all available pages before exploring further.

# TypeScript SDK

> @financialdatapi/client: a typed, zero-dependency client over the Financial Data API envelope and errors.

`@financialdatapi/client` is a thin, typed TypeScript and JavaScript client for the Financial Data API. It is read-only and has no runtime dependencies: it uses the global `fetch` (Node 18+ or browsers). It targets the same response envelope and the same stable error codes as the HTTP API, so what you learn from the REST surface carries over directly.

The SDK adds three things over raw `fetch`: typed methods for each endpoint, a `FinancialDataApiError` thrown on non-2xx responses, and an async iterator that auto-follows cursor pagination.

## Install and build

<CodeGroup>
  ```bash npm theme={"theme":"css-variables"}
  cd clients/typescript
  npm install
  npm run build   # emits dist/index.js + dist/index.d.ts
  ```
</CodeGroup>

## Construct the client

Pass your API key. The base URL defaults to `https://api.financialdatapi.com`, and the key is sent as `x-api-key` on every request.

```typescript theme={"theme":"css-variables"}
import { FinancialDataApiClient } from "@financialdatapi/client";

const client = new FinancialDataApiClient({
  apiKey: process.env.FINANCIALDATA_API_KEY,
  // baseUrl defaults to https://api.financialdatapi.com
  // fetch: customFetch, // optional: override the fetch implementation (e.g. for tests)
});
```

<Info>
  The constructor accepts `apiKey`, `baseUrl`, and `fetch`. On a runtime older than Node 18 with no global `fetch`, pass your own implementation via the `fetch` option or the client throws at construction.
</Info>

## Make a call

Every typed method returns the full envelope, so you read `data` and `meta` exactly as you would from the HTTP API.

<CodeGroup>
  ```typescript Latest readings theme={"theme":"css-variables"}
  const { data, meta } = await client.getLatestObservations({ country: "USA" });
  console.log(data);            // latest public reading per canonical indicator
  console.log(meta.api_version); // "v1"
  ```

  ```typescript Single series theme={"theme":"css-variables"}
  const series = await client.getObservations({
    indicator_id: "cpi_inflation_yoy",
    country: "GBR",
    limit: 24,
  });
  console.log(series.data);
  ```

  ```typescript Coverage theme={"theme":"css-variables"}
  const coverage = await client.coverage();
  console.log(coverage.data); // catalog totals, public indicator categories, covered countries
  ```
</CodeGroup>

Typed methods include `listIndicators`, `listCountries`, `countryIndicators`, `resolveEntity`, `getObservations`, `getLatestObservations`, `getProvenance`, `screen`, `screenerFields`, `crossCountry`, `ratesAnalytics`, `economicCalendar`, `officialEvents`, `coverage`, and `sourceHealth`. The low-level `request(path, params)` escape hatch returns the same envelope for any endpoint not yet wrapped.

## Auto-paginate with the async iterator

`paginate` is an async generator that walks every page of a list endpoint for you, following `meta.pagination.next_cursor` until it is exhausted. It yields one item at a time, so you never touch a cursor.

```typescript theme={"theme":"css-variables"}
for await (const observation of client.paginate("/observations", {
  indicator_id: "cpi_inflation_yoy",
  country: "GBR",
})) {
  // each observation across all pages, in order
  console.log(observation);
}
```

<Tip>
  Set `limit` (1 to 500) in the params to control page size. The iterator still returns every matching item regardless of page size; a larger `limit` just means fewer round trips.
</Tip>

## Build screener filters

The screener takes a `filter` DSL of comma-separated `field:operator:value` clauses that are AND-ed together. `buildScreenerFilter` serializes structured clauses into that string so you do not assemble it by hand. The `screen` method accepts either form.

<CodeGroup>
  ```typescript Structured theme={"theme":"css-variables"}
  import { FinancialDataApiClient, buildScreenerFilter } from "@financialdatapi/client";

  const client = new FinancialDataApiClient({ apiKey: process.env.FINANCIALDATA_API_KEY });

  const filter = buildScreenerFilter([
    { field: "cpi_inflation_yoy", operator: "gt", value: 3 },
    { field: "unemployment_rate", operator: "lt", value: 5 },
  ]);
  // "cpi_inflation_yoy:gt:3,unemployment_rate:lt:5"

  const result = await client.screen(filter);
  ```

  ```typescript Passed to screen() theme={"theme":"css-variables"}
  // screen() accepts structured clauses directly and serializes them for you
  const result = await client.screen([
    { field: "cpi_inflation_yoy", operator: "gt", value: 3 },
    { field: "unemployment_rate", operator: "lt", value: 5 },
  ]);

  // equivalent DSL string
  const same = await client.screen("cpi_inflation_yoy:gt:3,unemployment_rate:lt:5");
  ```
</CodeGroup>

Operators are `gt`, `lt`, `gte`, `lte`, `eq`, and `in`. For `in`, pass an array; `buildScreenerFilter` joins it with the pipe separator the DSL expects. Discover the screenable canonical-indicator fields with `client.screenerFields()`.

<Note>
  The screener screens public canonical-indicator values only. It never exposes any internal scoring.
</Note>

## Handle errors

Non-2xx responses throw a `FinancialDataApiError` carrying the stable `code`, the HTTP `status`, the `message`, the `requestId`, and any `details`. This is the same error contract as the REST API.

```typescript theme={"theme":"css-variables"}
import { FinancialDataApiError } from "@financialdatapi/client";

try {
  await client.screen("oops");
} catch (error) {
  if (error instanceof FinancialDataApiError) {
    console.error(error.code, error.status, error.message, error.requestId);
    // e.g. "bad_request" 400 "..." "<uuid>"
  } else {
    throw error;
  }
}
```

The `code` is one of the stable values shared with the HTTP API: `bad_request`, `unauthorized`, `forbidden`, `not_found`, `rate_limited`, `internal_error`. Branch on `code`, not on the human-readable `message`.

<Warning>
  Unknown query parameters are rejected, not ignored. A typo in a param name throws `FinancialDataApiError` with code `bad_request` rather than silently returning unfiltered data. Catch it early in development.
</Warning>

## Related

<Columns cols={2}>
  <Card title="MCP server" icon="plug" href="/ai-agents/mcp-server">
    Native read-only tools for Claude Code, Claude Desktop, and Cursor.
  </Card>

  <Card title="llms.txt" icon="file-lines" href="/ai-agents/llms-txt">
    The keyless text indexes that describe the API to an agent.
  </Card>
</Columns>
