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

# Installation and Quickstart

> Get started with the OMOPHub Node.js / TypeScript SDK - install, authenticate, and run your first concept search, mapping, and FHIR resolve from JavaScript in minutes.

## Prerequisites

* Node.js 22+ (Maintenance LTS)
* [OMOPHub API key](https://dashboard.omophub.com/api-keys)

## Installation

<CodeGroup>
  ```bash npm theme={null}
  npm install @omophub/omophub-node
  ```

  ```bash pnpm theme={null}
  pnpm add @omophub/omophub-node
  ```

  ```bash yarn theme={null}
  yarn add @omophub/omophub-node
  ```
</CodeGroup>

The SDK ships as an ESM-only package with bundled `.d.ts` types. It runs in Node ≥ 22, modern browsers (CORS permitting), and edge runtimes (Cloudflare Workers, Vercel Edge).

## Quick Start

```ts theme={null}
import { OMOPHub } from '@omophub/omophub-node';

const client = new OMOPHub('oh_xxxxxxxxx');

// Get a concept
const { data, error } = await client.concepts.get(201826);
if (error) throw new Error(error.message);
console.log(data.concept_name); // "Type 2 diabetes mellitus"

// Search concepts
const results = await client.search.basic('diabetes', { pageSize: 5 });
if (results.error) throw new Error(results.error.message);
for (const concept of results.data.concepts) {
  console.log(`${concept.concept_id}: ${concept.concept_name}`);
}
```

## Errors Are Return Values, Not Exceptions

Every SDK method returns a discriminated `{ data, error, meta, headers }` union. The SDK never throws on network or API errors - narrow with `if (error) ...` and TypeScript will type `data` correctly in the success branch.

```ts theme={null}
const { data, error } = await client.concepts.get(999_999_999);
if (error) {
  console.error(error.name, error.message, error.statusCode);
  return;
}
// `data` is now typed as Concept
console.log(data.concept_name);
```

See [Error Handling](/sdks/node/error-handling) for the full pattern.

## Configuration

```ts theme={null}
const client = new OMOPHub('oh_xxx', {
  baseUrl: 'https://api.omophub.com/v1',
  timeoutMs: 30_000,
  maxRetries: 3,
  vocabVersion: '2025.1',
});
```

You can also set your API key via environment variable:

```bash theme={null}
export OMOPHUB_API_KEY=oh_xxxxxxxxx
```

```ts theme={null}
// API key is read from process.env.OMOPHUB_API_KEY
const client = new OMOPHub();
```

| Option             | Env var           | Default                         |
| ------------------ | ----------------- | ------------------------------- |
| `apiKey` (1st arg) | `OMOPHUB_API_KEY` | - (required)                    |
| `baseUrl`          | `OMOPHUB_API_URL` | `https://api.omophub.com/v1`    |
| `timeoutMs`        | -                 | `30000` (set to `0` to disable) |
| `maxRetries`       | -                 | `3` (set to `0` to disable)     |
| `vocabVersion`     | -                 | unset (server picks latest)     |
| `userAgent`        | -                 | `omophub-node/<version>`        |
| `fetch`            | -                 | `globalThis.fetch`              |

## Retries

The client automatically retries `429`, `502`, `503`, `504`, and transient network errors with full-jitter exponential backoff (500 ms → 8 s, capped). `Retry-After` is honoured up to 60 s. **POST and PATCH only retry when an `Idempotency-Key` is set** - pass it via `{ idempotencyKey: '...' }` to opt in.

## Next Steps

<CardGroup cols={2}>
  <Card title="Concepts" icon="lightbulb" href="/sdks/node/concepts">
    Get, batch, and explore concepts
  </Card>

  <Card title="Search" icon="magnifying-glass" href="/sdks/node/search">
    Keyword, semantic, autocomplete
  </Card>

  <Card title="Mappings" icon="diagram-project" href="/sdks/node/mappings">
    Map between vocabularies
  </Card>

  <Card title="Error Handling" icon="shield-exclamation" href="/sdks/node/error-handling">
    Discriminated errors, retries, async iterators
  </Card>
</CardGroup>
