Skip to main content

Installation

Install the SDK using your preferred package manager:
npm install @imperial-host/sdk

Quick Start

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

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

// Upload an image
const result = await client.upload({
  file: fileBuffer, // Buffer / Blob / File
  filename: "image.png",
  mimeType: "image/png",
});
console.log(`Uploaded: ${result.url}`);

Configuration

Basic Configuration

const client = new ImperialClient({
  apiKey: "imperial_live_your_api_key_here",
  baseUrl: "https://api.imperial.gay", // Optional: defaults to production
  timeout: 30000, // Optional: request timeout in ms (default: 30000)
});

Upload Keys vs API Keys

Free & Starter tiers use upload keys (imperial_upload_*) which only support uploads. Pro & Business tiers use API keys (imperial_live_*) which support all operations.
// Upload key (Free/Starter) - upload only
const uploadClient = new ImperialClient({
  apiKey: "imperial_upload_abc123",
});

// API key (Pro/Business) - full access
const fullClient = new ImperialClient({
  apiKey: "imperial_live_xyz789",
});

Upload Methods

Upload Single File

Upload a single image or video file:
const buffer = fs.readFileSync("./photo.jpg");
const result = await client.upload({
  file: buffer,
  filename: "photo.jpg",
  mimeType: "image/jpeg",
});

console.log(result.url); // https://origin.imperial.gay/uploads/...

Upload Options

// Upload options are controlled by your dashboard settings (compression, naming, privacy defaults, etc).
// The SDK upload call itself takes: file, filename, mimeType.
const result = await client.upload({
  file: buffer,
  filename: "custom-name.jpg",
  mimeType: "image/jpeg",
});

Batch Upload

Upload multiple files at once (Pro/Business only):
const results = await client.uploadBatch(["./photo1.jpg", "./photo2.png", "./video.mp4"], {
  compressionLevel: 80,
});

results.forEach((result) => {
  console.log(`Uploaded: ${result.link}`);
});

Media Management

Media management requires a Pro or Business API key (imperial_live_*).

List Media

// List all media
const media = await client.list();

// Paginated list
const media = await client.list({
  limit: 50,
  offset: 0,
});

console.log(`Total: ${media.total}`);
media.items.forEach((item) => {
  console.log(`${item.filename}: ${item.link}`);
});

Get Media Details

const media = await client.get("abc123");

console.log(media.filename);
console.log(media.size);
console.log(media.views);
console.log(media.createdAt);

Delete Media

// Delete single file
await client.delete("abc123");

// Delete multiple files
await client.deleteBatch(["abc123", "xyz789"]);

Usage Information

Track your storage and operations usage:
const usage = await client.getUsage();

console.log(`Storage: ${usage.storageUsed} / ${usage.storageLimit} bytes`);
console.log(`Operations: ${usage.operationsUsed} / ${usage.operationsLimit}`);

Rate Limiting

The SDK automatically handles rate limit headers:
const rateLimits = await client.getRateLimits();

console.log(`Remaining: ${rateLimits.remaining}`);
console.log(`Limit: ${rateLimits.limit}`);
console.log(`Resets at: ${rateLimits.reset}`);

Error Handling

The SDK provides typed error classes for better error handling:
import {
  ImperialClient,
  AuthenticationError,
  RateLimitError,
  StorageLimitError,
  ValidationError,
} from "@imperial-host/sdk";

try {
  const result = await client.upload("./photo.jpg");
} catch (error) {
  if (error instanceof AuthenticationError) {
    console.error("Invalid API key");
  } else if (error instanceof RateLimitError) {
    console.error(`Rate limited. Retry after ${error.retryAfter}ms`);
  } else if (error instanceof StorageLimitError) {
    console.error("Storage limit exceeded. Upgrade your plan.");
  } else if (error instanceof ValidationError) {
    console.error("Validation error:", error.details);
  } else {
    console.error("Unexpected error:", error);
  }
}

Folders, Tags, Privacy (API Keys)

Upload keys (imperial_upload_*) are upload-only. Folders/tags/privacy require an API key (imperial_live_*) with the right scopes.

Scopes You’ll Need

  • Uploads: images:read, images:write, images:delete
  • Folders: folders:read, folders:write

List Folders

const { folders } = await client.listFolders();

Create Folder

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

Move Uploads + Tags (Bulk)

await client.bulkMetadata({
  ids: ["...uploadId1", "...uploadId2"],
  folderId: folder.id,
  tags: ["work", "2026"],
  mode: "add",
});

Set Visibility

await client.setPrivacy("...uploadId", "private");

Create Access URL For Private Upload

const { accessUrl } = await client.getAccessUrl("...uploadId");

Error Types

Error ClassStatus CodeDescription
AuthenticationError401Invalid or missing API key
PermissionError403Insufficient permissions for operation
NotFoundError404Media not found
StorageLimitError413Storage limit exceeded
UnsupportedMediaError415Unsupported file type
RateLimitError429Rate limit exceeded
ValidationError400Invalid request parameters
ServerError500+Server-side error
NetworkError-Network connectivity issue

Advanced Usage

Custom Timeout

const client = new ImperialClient({
  apiKey: "imperial_live_xyz",
  timeout: 60000, // 60 seconds for large files
});

Progress Tracking

// For large uploads, handle timeouts appropriately
const client = new ImperialClient({
  apiKey: "imperial_live_xyz",
  timeout: 120000, // 2 minutes
});

const result = await client.upload("./large-video.mp4");

Retry Logic

async function uploadWithRetry(filePath: string, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await client.upload(filePath);
    } catch (error) {
      if (error instanceof RateLimitError && i < maxRetries - 1) {
        // Wait for the specified retry time
        await new Promise((resolve) => setTimeout(resolve, error.retryAfter || 5000));
        continue;
      }
      throw error;
    }
  }
}

TypeScript Support

The SDK is fully typed with comprehensive TypeScript definitions:
import type {
  ImperialConfig,
  UploadOptions,
  UploadResult,
  MediaItem,
  ListMediaResult,
  UsageInfo,
  RateLimitInfo,
} from "@imperial-host/sdk";

const config: ImperialConfig = {
  apiKey: "imperial_live_xyz",
};

const options: UploadOptions = {
  compressionLevel: 80,
  instantDelete: false,
};

const result: UploadResult = await client.upload("./photo.jpg", options);

Examples

Express.js Integration

import express from "express";
import multer from "multer";
import { ImperialClient } from "@imperial-host/sdk";

const app = express();
const upload = multer({ storage: multer.memoryStorage() });
const imperial = new ImperialClient({
  apiKey: process.env.IMPERIAL_API_KEY!,
});

app.post("/upload", upload.single("file"), async (req, res) => {
  try {
    const result = await imperial.upload(req.file!.buffer, {
      filename: req.file!.originalname,
    });
    res.json({ url: result.link });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

Next.js App Router

// app/api/upload/route.ts
import { ImperialClient } from "@imperial-host/sdk";
import { NextRequest, NextResponse } from "next/server";

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

export async function POST(request: NextRequest) {
  const formData = await request.formData();
  const file = formData.get("file") as File;

  const buffer = Buffer.from(await file.arrayBuffer());
  const result = await imperial.upload(buffer, {
    filename: file.name,
  });

  return NextResponse.json({ url: result.link });
}

CLI Tool

#!/usr/bin/env node
import { ImperialClient } from "@imperial-host/sdk";
import { program } from "commander";

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

program
  .command("upload <file>")
  .description("Upload a file to Imperial")
  .action(async (file) => {
    try {
      const result = await client.upload(file);
      console.log(`✓ Uploaded: ${result.link}`);
    } catch (error) {
      console.error(`✗ Error: ${error.message}`);
      process.exit(1);
    }
  });

program.parse();

Support

License

MIT License - see the LICENSE file for details.