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

# Node.js SDK

> Track trusted backend events with @datalyr/api.

The Node.js SDK tracks events from servers, jobs, and webhooks. It requires Node.js 14.17 or later.

## Install

```bash theme={null}
npm install @datalyr/api
```

## Initialize

```ts theme={null}
import { Datalyr } from '@datalyr/api'

const datalyr = new Datalyr({
  apiKey: process.env.DATALYR_API_KEY
})
```

## Track an event

```ts theme={null}
await datalyr.track({
  event: 'purchase',
  userId: 'user_123',
  eventId: 'order_1001',
  timestamp: new Date(),
  properties: {
    value: 99.99,
    currency: 'USD'
  }
})
```

Use a stable `eventId` for webhook events. If the source retries the webhook, Datalyr can recognize the duplicate.

## Identify a user

```ts theme={null}
await datalyr.identify('user_123', {
  email: 'person@example.com',
  plan: 'pro'
})
```

## Core methods

| Method                              | Use it to                                     |
| ----------------------------------- | --------------------------------------------- |
| `track(options)`                    | Track a backend event.                        |
| `identify(userId, traits?)`         | Attach traits to a user.                      |
| `alias(newUserId, previousId?)`     | Link two IDs for the same user.               |
| `page(userId, name?, properties?)`  | Track a server-rendered page view.            |
| `trackPurchase(userId, properties)` | Track revenue with a required finite `value`. |
| `flush()`                           | Send queued events immediately.               |
| `close()`                           | Flush events and stop timers before shutdown. |

## Shut down cleanly

```ts theme={null}
await datalyr.close()
```

Call `close()` in short-lived scripts, workers, and graceful shutdown handlers so queued events have time to send.

## Configuration

```ts theme={null}
const datalyr = new Datalyr({
  apiKey: process.env.DATALYR_API_KEY,
  flushAt: 20,
  flushInterval: 10_000,
  timeout: 10_000,
  retryLimit: 3,
  maxQueueSize: 1_000,
  closeTimeout: 30_000,
  onError: (event, error) => console.error(error),
  onDrop: (events, reason) => console.error(reason, events)
})
```

| Option          | Default  | What it controls                               |
| --------------- | -------- | ---------------------------------------------- |
| `apiKey`        | Required | Workspace API key.                             |
| `flushAt`       | `20`     | Events queued before an automatic send.        |
| `flushInterval` | `10000`  | Automatic flush interval in milliseconds.      |
| `timeout`       | `10000`  | Request timeout in milliseconds.               |
| `retryLimit`    | `3`      | Retries during a send attempt.                 |
| `maxQueueSize`  | `1000`   | Maximum queued events.                         |
| `closeTimeout`  | `30000`  | Time allowed for `close()` to drain the queue. |
| `debug`         | `false`  | Development logging.                           |
| `onError`       | —        | Called for every delivery failure.             |
| `onDrop`        | —        | Called when events are permanently dropped.    |

## Event identity

Prefer the object form of `track`:

```ts theme={null}
await datalyr.track({
  event: 'trial_started',
  userId: 'user_123',
  anonymousId: 'anon_from_browser',
  properties: { plan: 'pro' }
})
```

Provide `userId`, `anonymousId`, or both. If you omit both, the SDK creates a new anonymous ID for that call, so separate calls will not form a continuous journey.

## Idempotency and timestamps

For webhooks, pass the source event ID and original timestamp:

```ts theme={null}
await datalyr.track({
  event: 'invoice_paid',
  userId: customer.id,
  eventId: stripeEvent.id,
  timestamp: stripeEvent.created,
  properties: { value: 49, currency: 'USD' }
})
```

`timestamp` accepts an ISO 8601 string, a `Date`, epoch seconds, or epoch milliseconds.

## Identity methods

```ts theme={null}
await datalyr.identify('user_123', { email: 'person@example.com' })
await datalyr.alias('user_123', 'temporary_id')
await datalyr.page('user_123', 'Pricing', { variant: 'A' })
```

## Track revenue

```ts theme={null}
await datalyr.trackPurchase(
  'user_123',
  { value: 99.99, currency: 'USD', product_id: 'pro_yearly' },
  { eventId: 'order_1001', timestamp: new Date() }
)
```

`value` must be a finite number. Currency values are normalized to uppercase.

## Serverless functions

Use `flush()` at the end of an invocation when the SDK instance may be reused:

```ts theme={null}
await datalyr.flush()
```

Use `close()` only when the process is shutting down. Once closed, the instance cannot accept more events.
