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 requires a Pro or Business API key (imperial_live_*).
// 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}`);
});
const media = await client.get("abc123");
console.log(media.filename);
console.log(media.size);
console.log(media.views);
console.log(media.createdAt);
// Delete single file
await client.delete("abc123");
// Delete multiple files
await client.deleteBatch(["abc123", "xyz789"]);
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);
}
}
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" });
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 Class | Status Code | Description |
|---|
AuthenticationError | 401 | Invalid or missing API key |
PermissionError | 403 | Insufficient permissions for operation |
NotFoundError | 404 | Media not found |
StorageLimitError | 413 | Storage limit exceeded |
UnsupportedMediaError | 415 | Unsupported file type |
RateLimitError | 429 | Rate limit exceeded |
ValidationError | 400 | Invalid request parameters |
ServerError | 500+ | 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 });
}
#!/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.