---
title: "PrimitiveApiClient"
canonical: "https://test.abhinandan.one/primitive-api-client"
markdown_url: "https://test.abhinandan.one/primitive-api-client.md"
publisher: "Primitive SDKs"
kind: "reference"
content_type: "reference"
category: "API Core / OpenAPI Generation"
description: "PrimitiveApiClient is the host-aware, authenticated fetch client in @primitivedotdev/api-core, re-exported by the Node SDK and CLI with a typed PrimitiveApiError."
keywords: ["PrimitiveApiClient", "PrimitiveApiError", "@primitivedotdev/api-core", "createPrimitiveApiClient", "DEFAULT_API_BASE_URL", "PrimitiveApiClientOptions"]
last_modified: "2026-08-21T18:22:43.359885+00:00"
published_at: "2026-08-11T18:55:05.581151+00:00"
source_files:
  - "packages/api-core/src/index.ts"
sections:
  - {anchor: "what-primitiveapiclient-is", title: "What PrimitiveApiClient is"}
  - {anchor: "where-it-comes-from", title: "Where it comes from"}
  - {anchor: "constructing-a-client", title: "Constructing a client"}
  - {anchor: "calling-a-generated-operation", title: "Calling a generated operation"}
  - {anchor: "primitiveapierror", title: "PrimitiveApiError"}
  - {anchor: "relationship-to-the-high-level-client", title: "Relationship to the high-level client"}
  - {anchor: "next-steps", title: "Next steps"}
---

> Documentation index: https://test.abhinandan.one/llms.txt

# PrimitiveApiClient

Reference for PrimitiveApiClient, the host-aware, authenticated HTTP client shared by the Node SDK and CLI, plus the shape of the PrimitiveApiError it throws.

## What PrimitiveApiClient is

`PrimitiveApiClient` is the host-aware, authenticated request client that every generated Primitive API operation is called through. It lives in the workspace-internal [api-core](https://test.abhinandan.one/api-core-overview.md) package and is bundled inline into both `@primitivedotdev/sdk` and the `primitive` CLI, so neither package declares a dependency on the other or on `@primitivedotdev/api-core` directly.

> **Note:** This is the **generated API client** layer: the OpenAPI-codegenerated surface that exposes every operation directly. For everyday send/receive/reply/forward code, use the high-level `primitive.client()` / `client.send()` surface described in the [inbound/outbound email model](https://test.abhinandan.one/email-model.md) instead. Reach for `PrimitiveApiClient` for operations the high-level client doesn't cover, such as [Primitive Memories](https://test.abhinandan.one/node-sdk-api-client.md) or account/domain management.

## Where it comes from

`PrimitiveApiClient` is defined and exported from `@primitivedotdev/api-core`, alongside its options type, its error class, and a factory function:

```typescript
export {
  createPrimitiveApiClient,
  DEFAULT_API_BASE_URL,
  PrimitiveApiClient,
  type PrimitiveApiClientOptions,
  PrimitiveApiError,
  type PrimitiveApiErrorDetails,
  type RequestOptions as PrimitiveRequestOptions,
} from "./client.js";
```

Consumers never import `@primitivedotdev/api-core` directly. The Node SDK re-exports the same names from `@primitivedotdev/sdk/api`:

```typescript
import { PrimitiveApiClient, getAccount } from "@primitivedotdev/sdk/api";

const api = new PrimitiveApiClient({ apiKey: process.env.PRIMITIVE_API_KEY });
const result = await getAccount({ client: api.client });
```

The CLI's internal `api-command` plumbing constructs `PrimitiveApiClient` the same way to drive the [generic API access commands](https://test.abhinandan.one/cli-overview/cli-generic-api-access.md) and every task-oriented CLI command.

## Constructing a client

```typescript
new PrimitiveApiClient(options?: PrimitiveApiClientOptions)
```

| Field | Type | Required | Description |
|---|---|---|---|
| `apiKey` | `string` | Yes (for authenticated calls) | Bearer token sent as `Authorization: Bearer <apiKey>` on every request. |

`DEFAULT_API_BASE_URL`, exported alongside the class, is the production host constant the client uses when no base URL is supplied. Production code should rely on that default.

A `createPrimitiveApiClient(...)` factory function is exported as an alternative construction path alongside the `new PrimitiveApiClient(...)` constructor; both produce the same client shape.

## Calling a generated operation

Every generated operation function (`getAccount`, `setMemory`, `getMemory`, `sendEmail`, and so on) takes a `client` option pointing at `apiClient.client`, the underlying generated fetch client `PrimitiveApiClient` wraps:

```typescript
import { PrimitiveApiClient, getAccount } from "@primitivedotdev/sdk/api";

const api = new PrimitiveApiClient({ apiKey: process.env.PRIMITIVE_API_KEY });

const result = await getAccount({ client: api.client });
```

The full list of generated operations is documented in the [operation manifest](https://test.abhinandan.one/operation-manifest.md). Passing `responseStyle: "fields"` returns a `{ data, error, response }`-shaped result; check `error` to detect failure.

## PrimitiveApiError

Failed requests surface as a typed `PrimitiveApiError`, carrying structured detail rather than a bare message:

| Field | Type | Description |
|---|---|---|
| `message` | `string` | Human-readable error message. |
| `status` | `number \| undefined` | The HTTP status code, when the request reached the server. |
| `code` | `string \| undefined` | Machine-readable error code from the API's error envelope. |
| `gates` | `GateDenial[] \| undefined` | Structured gate-denial detail when a send/reply/forward was blocked by a policy gate. |
| `requestId` | `string \| undefined` | The server's request id, useful when filing a support ticket. |
| `retryAfter` | `number \| undefined` | Parsed from the `Retry-After` response header, when present (for example on `429`). |
| `details` | `PrimitiveApiErrorDetails \| undefined` | Additional structured error detail, when the API supplied it. |

`PrimitiveApiErrorDetails` is exported as a type alongside the error class for callers who want to narrow `details` further. `PrimitiveRequestOptions` (the re-exported `RequestOptions` type) is the per-call options shape accepted by the generated client's request layer; the high-level `client.send()` / `client.reply()` surface has its own `RequestOptions`, documented on [Request Options and Idempotency](https://test.abhinandan.one/node-sdk-request-options.md).

The Node SDK's higher-level wrappers (`client.send`, `client.reply`, `client.agent.*`, `client.memories.*`) throw `PrimitiveApiError` directly, so you can catch it with `instanceof`:

```typescript
import primitive from "@primitivedotdev/sdk";
import { PrimitiveApiError } from "@primitivedotdev/sdk/api";

const client = primitive.client({ apiKey: process.env.PRIMITIVE_API_KEY! });

try {
  await client.send({
    from: "Support <support@example.com>",
    to: "alice@example.com",
    subject: "Hello",
    bodyText: "Hi there",
  });
} catch (error) {
  if (error instanceof PrimitiveApiError) {
    console.error(error.status, error.code, error.requestId, error.retryAfter);
  }
}
```

## Relationship to the high-level client

`PrimitiveClient` (the `send` / `reply` / `forward` client returned by `primitive.client(...)`) is built on top of the same generated operations and the same `PrimitiveApiClient` host-aware plumbing, but exposes a smaller, task-shaped surface with its own `SendResult`, `ReplyInput`, and `RequestOptions` types. That high-level surface is documented on [Sending, Replying, and Forwarding Email](https://test.abhinandan.one/node-sdk-sending-email.md) and [Receiving Inbound Email](https://test.abhinandan.one/node-sdk-receiving-email.md); this page covers only the underlying generated-client layer.
