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

# Configuration

> Carbon client options, event buffering and flushing, retries, and transports.

## Client options

All options are optional. With no arguments, `Carbon` reads `CARBON_API_KEY` from the environment and sends events to the production ingest API.

```typescript theme={null}
import { Carbon } from "@carbon-js/sdk";

const carbon = new Carbon({
  apiKey: process.env.CARBON_API_KEY,
  baseUrl: "https://ingest.oncarbon.site",
});
```

<ParamField body="apiKey" type="string" default="process.env.CARBON_API_KEY">
  API key used to authenticate with the ingest API. Create one in the dashboard
  under **Settings → API Keys**.
</ParamField>

<ParamField body="baseUrl" type="string" default="https://ingest.oncarbon.site">
  Base URL of the ingest API. Override only when pointing at a non-production
  environment.
</ParamField>

<ParamField body="bufferBatchSize" type="number" default="50">
  Number of buffered events that triggers an immediate flush.
</ParamField>

<ParamField body="bufferMaxBatchBytes" type="number" default="3670016">
  Maximum serialized batch size in bytes (3.5 MiB). A batch flushes before it
  would exceed this size. A single event larger than this limit throws at
  capture time.
</ParamField>

<ParamField body="bufferMaxTimeMs" type="number" default="5000">
  Maximum time in milliseconds an event waits in the buffer before a scheduled
  flush sends it.
</ParamField>

<ParamField body="maxBufferedEvents" type="number" default="5000">
  Maximum number of events held in the buffer. When the cap is exceeded, the
  oldest buffered events are dropped and reported through `onError`, so memory
  stays bounded during extended delivery failures.
</ParamField>

<ParamField body="onError" type="(args: T_CarbonErrorContext) => void">
  Called whenever delivery fails or events are dropped, with `{ error, events,
      disposition }`. `disposition` is `"dropped"` when the events are gone (a
  permanent rejection or buffer overflow) and `"retained"` when they stay
  buffered for retry. When omitted, the SDK logs a throttled `console.warn`
  instead. See [Delivery errors](#delivery-errors).
</ParamField>

<ParamField body="transport" type="T_EventTransport">
  Custom transport for delivering event batches. Defaults to `HttpTransport`.
  See [Transports](#transports).
</ParamField>

## Buffering and flushing

Captured events go into an in-memory buffer. A flush happens when any of these is reached:

* the buffer holds `bufferBatchSize` events (50 by default)
* the next event would push the serialized batch past `bufferMaxBatchBytes`
* an event has waited `bufferMaxTimeMs` (5 seconds by default)

Background flushes retry transient failures automatically and never throw into your application code. Transiently failed batches return to the front of the buffer, so event order is preserved. Permanently rejected batches — for example `402` responses when a space is over its [plan limit](/documentation/dashboard/plans) — are dropped and reported instead of retried, so they cannot block delivery of later events or grow memory.

### Flushing on shutdown

`flushPendingEvents` drains the buffer and resolves once every event is either delivered or deliberately dropped (with the drop reported through `onError`). It rejects only when a transient delivery failure leaves events buffered, so callers can decide how to handle loss at shutdown:

```typescript theme={null}
try {
  await carbon.flushPendingEvents();
} catch (error) {
  console.error("Carbon flush failed", error);
}
```

Call it before exit in serverless functions and other short-lived environments — scripts, CLIs, batch jobs. Long-running servers only need it for graceful shutdown.

## Delivery errors

By default the SDK logs delivery problems with `console.warn`, throttled to one warning per distinct error per minute, so a sustained rejection does not flood logs. Pass `onError` to route every occurrence to your own logging or metrics instead:

```typescript theme={null}
const carbon = new Carbon({
  onError: ({ error, events, disposition }) => {
    metrics.increment(`carbon.events.${disposition}`, events.length);
    logger.warn("Carbon delivery error", { error });
  },
});
```

`error` is a `CarbonIngestError` for HTTP rejections, carrying `status`, `errorId`, and `details` from the [ingest API error body](/api-reference/endpoints/ingest-events) — for example `errorId: "usage_limit_exceeded"` when the space is over its monthly event limit. Callback exceptions are swallowed, so `onError` can never break delivery.

## HTTP delivery and retries

The default `HttpTransport` posts batches to `POST /v1/ingest-events` with your API key as a bearer token.

* Requests time out after 15 seconds.
* Failed requests are retried up to 2 times, within a 30 second overall window.
* Responses with status 408, 409, 425, 429, or any 5xx are retried; other 4xx responses are not.

Delivery failures surface as `CarbonIngestError`, which carries `status` (the HTTP status, when available), `retryable`, and the `errorId` and `details` from the structured ingest error body when one is returned.

```typescript theme={null}
import { HttpTransport } from "@carbon-js/sdk";

const carbon = new Carbon({
  transport: new HttpTransport({
    apiKey: process.env.CARBON_API_KEY,
    timeoutMs: 30_000,
    retryMaxAttempts: 4,
    retryMaxElapsedMs: 60_000,
  }),
});
```

<Note>
  The ingest API deduplicates by event ID, so retried batches never create
  duplicate events. See [Delivery guarantees](/documentation/concepts/delivery).
</Note>

## Transports

A transport implements `sendBatch({ batch })`. Three are built in:

| Transport         | Use                                                         |
| ----------------- | ----------------------------------------------------------- |
| `HttpTransport`   | Production delivery to the ingest API (default)             |
| `MemoryTransport` | Tests — batches accumulate on the in-memory `batches` array |
| `FileTransport`   | Local development — each batch is written as a JSON file    |

```typescript theme={null}
import { Carbon, MemoryTransport } from "@carbon-js/sdk";

const transport = new MemoryTransport();
const carbon = new Carbon({ transport });

// ...exercise your code, then assert on captured events
expect(transport.batches[0].events).toHaveLength(1);
```

`FileTransport` accepts a `dirPath` option and defaults to `.tmp` in the working directory:

```typescript theme={null}
import { Carbon, FileTransport } from "@carbon-js/sdk";

const carbon = new Carbon({
  transport: new FileTransport({ dirPath: "./carbon-events" }),
});
```
