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

# Client

> Main client class for the Mirador SDK

## Overview

`Client` is the main entry point for the Mirador SDK. It handles authentication, plugin registration, sampling, and creates trace builders.

## Import

**Web SDK:**

```typescript theme={null}
import { Client } from '@miradorlabs/web-sdk';
```

**Node.js SDK:**

```typescript theme={null}
import { Client } from '@miradorlabs/nodejs-sdk';
```

## Constructor

**Web SDK:**

```typescript theme={null}
new Client(apiKey: string, options?: ClientOptions)
```

**Node.js SDK:**

```typescript theme={null}
new Client(apiKey?: string, options?: ClientOptions)
```

### Parameters

| Parameter | Type            | Required                 | Description                |
| --------- | --------------- | ------------------------ | -------------------------- |
| `apiKey`  | `string`        | Yes (Web) / No (Node.js) | API key for authentication |
| `options` | `ClientOptions` | No                       | Configuration options      |

### Options

**Web SDK:**

```typescript theme={null}
interface ClientOptions {
  apiUrl?: string;              // Gateway URL (default: ingest.mirador.org:443)
  keepAliveIntervalMs?: number; // Keep-alive ping interval in milliseconds (default: 10000)
  callTimeoutMs?: number;       // Timeout for individual API calls in milliseconds (default: 5000)
  maxTraceLifetimeMs?: number;  // Max trace lifetime in milliseconds (default: 0 / disabled)
  debug?: boolean;              // Enable debug logging (default: false)
  logger?: Logger;              // Custom logger implementation
  callbacks?: TraceCallbacks;   // Lifecycle callbacks for all traces
  sampleRate?: number;          // Sampling rate 0-1 (default: 1)
  sampler?: Function;           // Custom sampler function
  plugins?: MiradorPlugin[];    // Plugins to install on all traces
}
```

**Node.js SDK:**

```typescript theme={null}
interface ClientOptions {
  apiUrl?: string;              // Gateway URL (default: ingest.mirador.org:443)
  keepAliveIntervalMs?: number; // Keep-alive ping interval in milliseconds (default: 10000)
  callTimeoutMs?: number;       // Timeout for individual API calls in milliseconds (default: 5000)
  maxTraceLifetimeMs?: number;  // Max trace lifetime in milliseconds (default: 0 / disabled)
  debug?: boolean;              // Enable debug logging (default: false)
  logger?: Logger;              // Custom logger implementation
  callbacks?: TraceCallbacks;   // Lifecycle callbacks for all traces
  sampleRate?: number;          // Sampling rate 0-1 (default: 1)
  sampler?: Function;           // Custom sampler function
  plugins?: MiradorPlugin[];    // Plugins to install on all traces
  useSsl?: boolean;             // Use SSL for gRPC connection (default: true)
}
```

### Examples

**Basic initialization:**

```typescript theme={null}
const client = new Client('your-api-key');
```

**With custom gateway:**

```typescript theme={null}
const client = new Client('your-api-key', {
  apiUrl: 'https://custom-gateway.example.com:443'
});
```

**With custom keep-alive interval:**

```typescript theme={null}
const client = new Client('your-api-key', {
  keepAliveIntervalMs: 15000  // Ping every 15 seconds
});
```

**With Web3Plugin:**

```typescript theme={null}
import { Client, Web3Plugin } from '@miradorlabs/web-sdk';

const client = new Client('your-api-key', {
  plugins: [Web3Plugin({ provider: window.ethereum })]
});

// All traces have web3 methods available
const trace = client.trace({ name: 'Swap' });
const txHash = await trace.web3.evm.sendTransaction({
  from: userAddress,
  to: contractAddress,
  data: calldata
});
```

## Sampling

Control what percentage of traces are recorded. Unsampled traces return a `NoopTrace` that silently discards all operations, so your code doesn't need any conditional checks.

**Fixed sample rate:**

```typescript theme={null}
const client = new Client('your-api-key', {
  sampleRate: 0.1  // Record 10% of traces
});
```

**Custom sampler function:**

```typescript theme={null}
const client = new Client('your-api-key', {
  sampler: (name, options) => {
    // Always record critical operations
    if (name === 'Payment') return true;
    // Sample everything else at 10%
    return Math.random() < 0.1;
  }
});
```

## Lifecycle Callbacks

Register callbacks to observe trace lifecycle events across all traces. See the [Lifecycle Callbacks](/advanced/lifecycle-callbacks) guide for detailed usage patterns and examples.

```typescript theme={null}
const client = new Client('your-api-key', {
  callbacks: {
    onCreated: (traceId) => console.log('Trace created:', traceId),
    onFlushed: (traceId, itemCount) => console.log(`Flushed ${itemCount} items for ${traceId}`),
    onFlushError: (error, operation) => console.error(`${operation} failed:`, error),
    onClosed: (traceId, reason) => console.log('Trace closed:', traceId, reason),
    onDropped: (count, reason) => console.warn(`Dropped ${count} items: ${reason}`)
  }
});
```

## Methods

### trace()

Creates a new trace builder.

**Web SDK:**

```typescript theme={null}
trace(options?: TraceOptions): Trace
```

**Node.js SDK:**

```typescript theme={null}
trace(options?: TraceOptions): Trace
```

#### Parameters

| Parameter | Type           | Required | Description         |
| --------- | -------------- | -------- | ------------------- |
| `options` | `TraceOptions` | No       | Trace configuration |

#### TraceOptions

**Web SDK:**

| Option            | Type             | Default          | Description                                                                        |
| ----------------- | ---------------- | ---------------- | ---------------------------------------------------------------------------------- |
| `name`            | `string`         | `undefined`      | Name identifying the trace                                                         |
| `traceId`         | `string`         | `undefined`      | Resume an existing trace by ID                                                     |
| `includeUserMeta` | `boolean`        | `true`           | Include browser metadata                                                           |
| `maxRetries`      | `number`         | `2`              | Maximum retry attempts                                                             |
| `retryBackoff`    | `number`         | `500`            | Base backoff delay (ms)                                                            |
| `autoClose`       | `boolean`        | `false`          | Automatically close trace on page unload                                           |
| `autoKeepAlive`   | `boolean`        | `true` / `false` | Auto-start keep-alive timer (`true` for new traces, `false` when `traceId` is set) |
| `maxQueueSize`    | `number`         | `4096`           | Max items in flush queue before dropping                                           |
| `callbacks`       | `TraceCallbacks` | `undefined`      | Per-trace lifecycle callbacks                                                      |

**Node.js SDK:**

| Option              | Type             | Default          | Description                                                                        |
| ------------------- | ---------------- | ---------------- | ---------------------------------------------------------------------------------- |
| `name`              | `string`         | `undefined`      | Name identifying the trace                                                         |
| `traceId`           | `string`         | `undefined`      | Resume an existing trace by ID (e.g., from frontend SDK)                           |
| `captureStackTrace` | `boolean`        | `true`           | Capture stack trace at trace creation                                              |
| `maxRetries`        | `number`         | `2`              | Maximum retry attempts                                                             |
| `retryBackoff`      | `number`         | `500`            | Base backoff delay (ms)                                                            |
| `autoKeepAlive`     | `boolean`        | `true` / `false` | Auto-start keep-alive timer (`true` for new traces, `false` when `traceId` is set) |
| `maxQueueSize`      | `number`         | `4096`           | Max items in flush queue before dropping                                           |
| `callbacks`         | `TraceCallbacks` | `undefined`      | Per-trace lifecycle callbacks                                                      |

#### Returns

`Trace` - A trace builder instance (or `NoopTrace` if the trace is not sampled)

#### Examples

**Web SDK - Basic trace:**

```typescript theme={null}
const trace = client.trace({ name: 'UserAction' });
```

**Web SDK - With full options:**

```typescript theme={null}
const trace = client.trace({
  name: 'CriticalOperation',
  includeUserMeta: true,
  maxRetries: 5,
  retryBackoff: 1000
});
```

**Node.js SDK - Basic trace:**

```typescript theme={null}
const trace = client.trace({ name: 'UserAction' });
```

**Node.js SDK - Without stack trace:**

```typescript theme={null}
const trace = client.trace({ name: 'UserAction', captureStackTrace: false });
```

## Usage Patterns

### Single Client Instance

Create one client instance and reuse it:

**Web SDK:**

```typescript theme={null}
// client.ts
import { Client, Web3Plugin } from '@miradorlabs/web-sdk';

export const mirador = new Client(process.env.MIRADOR_API_KEY, {
  plugins: [Web3Plugin({ provider: window.ethereum })]
});

// component.ts
import { mirador } from './client';

function handleAction() {
  const trace = mirador.trace({ name: 'ComponentAction' });
  // ...
}
```

**Node.js SDK:**

```typescript theme={null}
// client.ts
import { Client } from '@miradorlabs/nodejs-sdk';

export const mirador = new Client(process.env.MIRADOR_API_KEY);

// handler.ts
import { mirador } from './client';

async function handleAction() {
  const trace = mirador.trace({ name: 'ComponentAction' })
    .addAttribute('action', 'process')
    .addEvent('started');
  // → auto-flushed at end of current JS tick

  // ... do work ...

  await trace.close('done');
}
```

### Multiple Traces

A single client can create multiple concurrent traces:

**Web SDK:**

```typescript theme={null}
const client = new Client('api-key');

// User flow trace
const userTrace = client.trace({ name: 'UserSession' });

// Background operation trace
const bgTrace = client.trace({ name: 'BackgroundSync' });

// Both traces operate independently
userTrace.addEvent('user_clicked');
bgTrace.addEvent('sync_started');
```

**Node.js SDK:**

```typescript theme={null}
const client = new Client('api-key');

// Both traces operate independently — auto-flushed
const userTrace = client.trace({ name: 'UserSession' })
  .addEvent('user_clicked');

const bgTrace = client.trace({ name: 'BackgroundSync' })
  .addEvent('sync_started');
```

### Environment-Based Configuration

```typescript theme={null}
const client = new Client(
  process.env.MIRADOR_API_KEY
);
```

## Authentication

The API key is sent with every request in the `x-ingest-api-key` header. Keep your API key secure:

* Don't commit it to version control
* Use environment variables
* Consider using different keys for dev/prod

## Next Steps

<CardGroup cols={2}>
  <Card title="Trace" icon="route" href="/api-reference/trace">
    Trace builder methods
  </Card>

  <Card title="Types" icon="code" href="/api-reference/types">
    TypeScript type definitions
  </Card>
</CardGroup>
