npm package: @imperial-host/sdk
Description: Official TypeScript SDK for the Imperial media API
Author: @imperial-host
Latest version: 1.2.0

# @imperial-host/sdk

Official TypeScript SDK for the Imperial media API.

`@imperial-host/sdk` gives you a small, typed client for uploading files, listing media, managing folders, changing privacy, and working with private access links from Node.js or modern browser environments.

## Why use it

- Typed request and response models
- One client for both upload keys and full API keys
- Works in Node.js 18+ and browser runtimes with `fetch`, `FormData`, and `Blob`
- Built-in error classes for common API failures
- Rate-limit and usage metadata available after requests

## Installation

```bash
npm install @imperial-host/sdk
```

```bash
pnpm add @imperial-host/sdk
```

```bash
yarn add @imperial-host/sdk
```

```bash
bun add @imperial-host/sdk
```

## Quick start

```ts
import { ImperialClient } from "@imperial-host/sdk";
import { readFile } from "node:fs/promises";

const client = new ImperialClient({
  apiKey: process.env.IMPERIAL_API_KEY!,
});

const file = await readFile("./cat.png");

const upload = await client.upload({
  file,
  filename: "cat.png",
  mimeType: "image/png",
});

console.log(upload.url);
```

## Authentication

The SDK supports two key types:

- `imperial_live_*`
  Full API keys for listing, deleting, folder management, privacy changes, and private access links.
- `imperial_upload_*`
  Upload-only keys. These can upload files, but the SDK will intentionally block management methods like `list()`, `delete()`, `setPrivacy()`, and folder operations.

## Supported operations

### Uploads

```ts
await client.upload({
  file: new Uint8Array([1, 2, 3]),
  filename: "tiny.bin",
  mimeType: "application/octet-stream",
});

await client.uploadBatch([
  { file: fileA, filename: "a.png", mimeType: "image/png" },
  { file: fileB, filename: "b.png", mimeType: "image/png" },
]);
```

Accepted upload payloads:

- `Blob`
- `File`
- `ArrayBuffer`
- `Uint8Array`
- Node.js `Buffer` values also work because they are `Uint8Array`

### Listing and reading media

```ts
const media = await client.list({
  page: 1,
  limit: 50,
  q: "invoice",
  mimePrefix: "image/",
  tags: ["receipts"],
});

const item = await client.get(media.images[0]._id);
console.log(item.url);
```

### Deleting and bulk actions

```ts
await client.delete("67d8f9a1b2c3d4e5f6789012");

await client.deleteBatch([
  "67d8f9a1b2c3d4e5f6789012",
  "67d8f9a1b2c3d4e5f6789013",
]);

await client.bulkTrash(["67d8f9a1b2c3d4e5f6789012"]);
await client.bulkRestore(["67d8f9a1b2c3d4e5f6789012"]);

await client.bulkMetadata({
  ids: ["67d8f9a1b2c3d4e5f6789012"],
  tags: ["reference", "archive"],
  mode: "replace",
});
```

### Privacy and private access links

```ts
await client.setPrivacy("67d8f9a1b2c3d4e5f6789012", "private");

const link = await client.getAccessUrl("67d8f9a1b2c3d4e5f6789012");
console.log(link.accessUrl, link.expiresAt);
```

### Metadata helpers

```ts
await client.moveUpload("67d8f9a1b2c3d4e5f6789012", "folder_id");
await client.addTags("67d8f9a1b2c3d4e5f6789012", ["client", "invoice"]);
await client.removeTags("67d8f9a1b2c3d4e5f6789012", ["invoice"]);
await client.setExpiry("67d8f9a1b2c3d4e5f6789012", 7);
await client.clearExpiry("67d8f9a1b2c3d4e5f6789012");
```

### Folders

```ts
const folders = await client.listFolders();

const folder = await client.createFolder({
  name: "Receipts",
});

await client.updateFolder(folder.id, {
  name: "Archived Receipts",
});
```

```ts
await client.pinFolder(folder.id);
const pinned = await client.listPinnedFolders();
await client.unpinFolder(folder.id);
```

## Browser example

```ts
import { ImperialClient } from "@imperial-host/sdk";

const client = new ImperialClient({
  apiKey: "imperial_upload_xxxxxxxxxxxxx",
});

const input = document.querySelector<HTMLInputElement>("#file-input");
const file = input?.files?.[0];

if (file) {
  const result = await client.upload({
    file,
    filename: file.name,
    mimeType: file.type,
  });

  console.log(result.url);
}
```

## Error handling

The SDK throws typed errors for common failure modes:

- `AuthenticationError`
- `PermissionError`
- `NotFoundError`
- `StorageLimitError`
- `UnsupportedMediaError`
- `RateLimitError`
- `ValidationError`
- `ServerError`
- `NetworkError`

```ts
import {
  ImperialClient,
  AuthenticationError,
  PermissionError,
  RateLimitError,
} from "@imperial-host/sdk";

try {
  await client.list();
} catch (error) {
  if (error instanceof AuthenticationError) {
    console.error("Your API key is invalid.");
  } else if (error instanceof PermissionError) {
    console.error("This key does not have permission for that action.");
  } else if (error instanceof RateLimitError) {
    console.error("Slow down and retry later.", error.retryAfter);
  } else {
    console.error(error);
  }
}
```

## Rate limits and usage

After a request, you can inspect the latest rate-limit and usage headers:

```ts
await client.upload({
  file,
  filename: "cat.png",
  mimeType: "image/png",
});

console.log(client.getRateLimitInfo());
console.log(client.getUsageInfo());
```

## API surface

Main exports:

- `ImperialClient`
- `ImperialError` and specialized error classes
- Type exports including `ImperialConfig`, `UploadOptions`, `UploadResult`, `MediaItem`, `ListMediaResult`, `FolderItem`, `RateLimitInfo`, and `UsageInfo`

## Development

From `packages/sdk`:

```bash
npm run build
npm run test
```

## Repository

This package is maintained in the Imperial monorepo by `@spoodyz`.