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

# Client options

> Full ClientOptions reference: base URL, timeouts, retries, logging, custom fetch

Every field `createClient(opts)` accepts. Same as the exported `ClientOptions` TypeScript type.

## Required

### `tenant: string`

Workspace id (`t_…`) the client acts under. Can be read from `NORA_TENANT` env if omitted.

## Credentials

### `token?: string`

PAT (`nora_pat_…`) for management calls. Read from `NORA_PAT` env if omitted. Not required if you only call the trigger-secret surfaces (`flows.run`, `feedback`, `signals.report`).

### `triggerSecret?: string`

Per-Flow execution secret. Read from `NORA_TRIGGER_SECRET` env if omitted. Required for `flows.run` and `signals.report`.

### `triggerHeader?: string`

Header the trigger expects its secret on. Matches the trigger block's configured `api_auth_header`. Defaults to `authorization` sent as `Bearer <secret>`.

Override when your trigger is configured to accept a non-standard header:

```ts theme={null}
createClient({
  // …
  triggerHeader: "x-nora-trigger",   // trigger config was set to x-nora-trigger
});
```

## Transport

### `baseUrl?: string`

Server base URL. Defaults to `https://platform.nora.my/api/v1` (or `NORA_BASE_URL` env if set).

Override for self-hosted / staging deployments:

```ts theme={null}
createClient({
  // …
  baseUrl: "https://staging.platform.example.com/api/v1",
});
```

### `timeoutMs?: number`

Per-call default timeout in milliseconds. **Default `30_000`** (30 s).

Individual verbs can override with a `timeoutMs` in their own options object (e.g. `flows.run(slug, input, { timeoutMs: 60_000 })`).

### `maxRetries?: number`

Retry count for server-declared-retryable failures (`NoraProviderError` and `NoraPlatformError` when `.retryable === true`). **Default `2`**.

Every attempt is logged with `attempt` and the failure `code` — no silent retries. See [Errors · Logging](/sdk/errors#logging).

Set to `0` to disable SDK-layer retry (do your own at the application layer):

```ts theme={null}
createClient({
  // …
  maxRetries: 0,
});
```

### `fetchImpl?: typeof fetch`

Custom `fetch` implementation. Defaults to `globalThis.fetch`. Use this for:

* **Test seams** — inject a mock:

  ```ts theme={null}
  createClient({ /* … */ fetchImpl: mockFetch });
  ```

* **Custom runtimes** — Node with `undici`, edge workers with a specific fetch polyfill, HTTP proxy shims.

Signature must match the standard `fetch(input, init?)`.

## Observability

### `logger?: Logger`

Structured logger the SDK pipes internal records into. Compatible with pino, winston, bunyan, or anything matching:

```ts theme={null}
interface Logger {
  debug?(msg: string, meta?: unknown): void;
  info?(msg: string, meta?: unknown): void;
  warn?(msg: string, meta?: unknown): void;
  error?(msg: string, meta?: unknown): void;
}
```

The SDK **redacts by default** — tokens, secrets, `onBehalfOf` values, and request/response bodies do not appear in logs unless `debug: true`.

### `debug?: boolean`

When `true`, request and response **bodies** get logged (via the `logger`). Off by default.

Turn on per-incident only, ideally via a scoped clone rather than the shared client. Bodies can contain PII.

### `onLog?: (event: LogEvent) => void`

Observe SDK-internal events for metrics — request / response / retry / error. Event shape:

```ts theme={null}
interface LogEvent {
  event: "request" | "response" | "retry" | "error";
  traceId?: string;
  flow?: string;      // slug when the event was scoped to a flow
  attempt?: number;   // populated on retries
  durationMs?: number;// populated on response / error
  status?: string;    // HTTP status or "aborted"
  code?: string;      // failure code when error / retry
}
```

Never carries secrets or request bodies — safe to ship to any metrics sink.

Wire it to your metrics stack:

```ts theme={null}
createClient({
  // …
  onLog: (e) => {
    switch (e.event) {
      case "retry":              metrics.increment("nora.retry", { code: e.code }); break;
      case "provider.fallback":  metrics.increment("nora.fallback"); break;
    }
  },
});
```

Retry rate, fallback frequency, and circuit-open rate are leading indicators when something upstream is degrading.

## Full example

```ts theme={null}
import { createClient } from "@conscience-technology/nora-sdk";
import pino from "pino";

const nora = createClient({
  tenant: process.env.NORA_TENANT!,
  token: process.env.NORA_PAT,
  triggerSecret: process.env.NORA_TRIGGER_SECRET,
  baseUrl: process.env.NORA_BASE_URL,     // omit → default platform.nora.my
  timeoutMs: 30_000,
  maxRetries: 2,
  logger: pino({ level: "info", redact: ["*.token", "*.secret"] }),
  debug: false,
  onLog: (e) => metrics.count("nora." + e.event),
});
```

## See also

* [Auth](/sdk/auth) — credentials + PAT scopes.
* [Errors](/sdk/errors) — how transport failures surface and which retry logic applies.
