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

# TypeScript SDK

> Complete reference for @blobrouter/sdk — upload, get, delete, retries, and errors.

<Info>
  **BlobRouter v0.1** · Last updated: August 2026 · Architecture version: **2.0**
</Info>

Server-side SDK for Node.js 18+. **Not for browser use** (API keys must stay on the server).

## Install

```bash theme={null}
npm install @blobrouter/sdk
```

## Constructor

```typescript theme={null}
import { BlobRouter } from "@blobrouter/sdk";

const storage = new BlobRouter({
  apiKey: process.env.BLOBROUTER_API_KEY!, // required — br_live_… or br_test_…
  baseUrl: "https://api.blobrouter.com", // optional
  maxRetries: 3, // optional — control-plane retries (default 3)
});
```

| Option       | Type     | Default                      | Description                      |
| ------------ | -------- | ---------------------------- | -------------------------------- |
| `apiKey`     | `string` | —                            | API key from the dashboard       |
| `baseUrl`    | `string` | `https://api.blobrouter.com` | API origin                       |
| `maxRetries` | `number` | `3`                          | Retries for BlobRouter API calls |

## `upload(file, options)`

Uploads via init → **direct PUT to provider** → complete. BlobRouter never sees file bytes.

```typescript theme={null}
import { readFileSync } from "fs";

const file = readFileSync("./report.pdf");

const result = await storage.upload(file, {
  fileName: "report.pdf",
  contentType: "application/pdf",
  fileSizeBytes: file.length,
  priority: "cold", // "hot" | "cold" | "archive"
  region: "us", // optional — e.g. "eu" for residency warnings
});

console.log(result.fileId);
console.log(result.provider);
console.log(result.savedVsAws);
console.log(result.url);
console.log(result.routingWarning); // optional
```

**Parameters**

| Field           | Type                               | Required | Notes                            |
| --------------- | ---------------------------------- | -------- | -------------------------------- |
| `file`          | `Buffer` \| `Readable`             | yes      | File body                        |
| `fileName`      | `string`                           | yes      | Object key / display name        |
| `contentType`   | `string`                           | yes      | MIME type                        |
| `fileSizeBytes` | `number`                           | yes      | Exact size in bytes              |
| `priority`      | `"hot"` \| `"cold"` \| `"archive"` | no       | Default `cold` on API if omitted |
| `region`        | routing region                     | no       | e.g. `"eu"`                      |

**Returns** `UploadResult`

| Field            | Type                                                |
| ---------------- | --------------------------------------------------- |
| `fileId`         | `string`                                            |
| `url`            | `string` — BlobRouter file URL                      |
| `provider`       | `"aws-s3"` \| `"cloudflare-r2"` \| `"backblaze-b2"` |
| `savedVsAws`     | `number` — estimated USD savings vs S3              |
| `routingWarning` | `string` \| `undefined`                             |

### Retry behavior

* Retries **control-plane** calls (`/v1/upload/init`, `/v1/upload/complete`, get, delete) on network failures and `5xx` / `408` / `429` with exponential backoff
* Does **not** retry other `4xx` responses
* Does **not** retry the provider presigned PUT

## `get(fileId)`

Returns a time-limited presigned download URL.

```typescript theme={null}
const { url, expiresAt } = await storage.get(fileId);
console.log(url, expiresAt);
```

## `delete(fileId)`

Deletes the object on the provider and marks the file deleted in BlobRouter.

```typescript theme={null}
const { success } = await storage.delete(fileId);
```

## Errors

```typescript theme={null}
import { BlobRouter, BlobRouterError } from "@blobrouter/sdk";

try {
  await storage.upload(file, options);
} catch (err) {
  if (err instanceof BlobRouterError) {
    console.error(err.message, err.code, err.statusCode);
  }
  throw err;
}
```

Common `code` values:

| Code                        | Meaning                          |
| --------------------------- | -------------------------------- |
| `unauthorized`              | Invalid API key                  |
| `plan_limit`                | Plan / quota gate                |
| `file_too_large`            | Exceeds max size (5GB)           |
| `no_providers` / related    | No providers configured          |
| `rate_limit_exceeded`       | Too many requests                |
| `network_error`             | Transport failure talking to API |
| `upload_to_provider_failed` | Provider PUT failed              |
| `api_error`                 | Other API error                  |

## Local API

```typescript theme={null}
const storage = new BlobRouter({
  apiKey: "br_test_…",
  baseUrl: "http://127.0.0.1:8787",
});
```
