Package Exports
- @imperial-host/sdk
Readme
@imperial/sdk
Official TypeScript SDK for the Imperial API. Upload and manage images and videos with zero egress fees.
Features
- ✅ Full TypeScript support with complete type definitions
- 🚀 Modern async/await API for clean, readable code
- 📦 Batch uploads for efficient bulk operations
- 🔄 Automatic retries with exponential backoff
- 📊 Rate limit tracking with usage info
- ⚡ Zero dependencies (except form-data for Node.js)
- 🌐 Works in Node.js and browsers
Installation
npm install @imperial/sdkyarn add @imperial/sdkpnpm add @imperial/sdkQuick Start
import { ImperialClient } from '@imperial/sdk';
// Initialize client
const imperial = new ImperialClient({
apiKey: 'imperial_live_xxxxxxxxxxxxx' // or imperial_upload_ for upload-only access
});
// Upload an image
const result = await imperial.upload({
file: buffer, // Buffer, Blob, or File
filename: 'cat.jpg',
mimeType: 'image/jpeg'
});
console.log(`Uploaded: ${result.url}`);Authentication
API Keys (Pro/Business)
Pro and Business tiers get full API keys with access to all endpoints:
const imperial = new ImperialClient({
apiKey: 'imperial_live_xxxxxxxxxxxxx'
});Upload Keys (Free/Starter)
Free and Starter tiers get upload-only keys:
const imperial = new ImperialClient({
apiKey: 'imperial_upload_xxxxxxxxxxxxx'
});
// Can upload, but cannot list or delete
await imperial.upload({ ... }); // ✅ Works
await imperial.list(); // ❌ Requires Pro/BusinessGet your keys from the Dashboard.
Usage Examples
Upload Single File
import fs from 'fs';
import { ImperialClient } from '@imperial/sdk';
const imperial = new ImperialClient({
apiKey: process.env.IMPERIAL_API_KEY!
});
// From file
const buffer = fs.readFileSync('./image.jpg');
const result = await imperial.upload({
file: buffer,
filename: 'image.jpg',
mimeType: 'image/jpeg'
});
console.log(result.url); // https://cdn.imperial.gay/uploads/...Upload Multiple Files (Batch)
const files = [
{ file: buffer1, filename: 'cat.jpg', mimeType: 'image/jpeg' },
{ file: buffer2, filename: 'dog.jpg', mimeType: 'image/jpeg' },
{ file: buffer3, filename: 'bird.jpg', mimeType: 'image/jpeg' }
];
const result = await imperial.uploadBatch(files);
console.log(`Uploaded ${result.count} files`);
result.uploaded.forEach(file => {
console.log(file.url);
});
if (result.errors) {
console.error('Some uploads failed:', result.errors);
}List Uploaded Media
// Get first page
const media = await imperial.list({
page: 1,
limit: 50
});
console.log(`Total: ${media.pagination.total}`);
console.log(`Page ${media.pagination.page} of ${media.pagination.totalPages}`);
media.images.forEach(item => {
console.log(`${item.prompt} - ${item.url}`);
});Get Specific Media
const item = await imperial.get('67d8f9a1b2c3d4e5f6789012');
console.log(item.url);
console.log(item.mimeType);
console.log(item.createdAt);Delete Media
// Delete single item
await imperial.delete('67d8f9a1b2c3d4e5f6789012');
// Delete multiple items
await imperial.deleteBatch([
'67d8f9a1b2c3d4e5f6789012',
'67d8f9a1b2c3d4e5f6789013',
'67d8f9a1b2c3d4e5f6789014'
]);Monitor Rate Limits
const result = await imperial.upload({ ... });
// Check rate limit info after any request
const rateLimit = imperial.getRateLimitInfo();
console.log(`Requests remaining: ${rateLimit?.remaining}/${rateLimit?.limit}`);
// Check usage info
const usage = imperial.getUsageInfo();
console.log(`Operations: ${usage?.operationsUsed}/${usage?.operationsLimit}`);
console.log(`Storage: ${(usage?.storageUsed / 1024 / 1024 / 1024).toFixed(2)} GB`);Browser Usage
import { ImperialClient } from '@imperial/sdk';
const imperial = new ImperialClient({
apiKey: 'imperial_upload_xxxxxxxxxxxxx'
});
// Upload from file input
const fileInput = document.querySelector<HTMLInputElement>('#file-input');
const file = fileInput.files[0];
const result = await imperial.upload({
file: file,
filename: file.name,
mimeType: file.type
});
console.log(`Uploaded: ${result.url}`);Error Handling
The SDK provides specific error classes for different scenarios:
import {
ImperialClient,
AuthenticationError,
StorageLimitError,
RateLimitError,
ValidationError
} from '@imperial/sdk';
try {
await imperial.upload({ ... });
} catch (error) {
if (error instanceof AuthenticationError) {
console.error('Invalid API key');
} else if (error instanceof StorageLimitError) {
console.error('Storage limit exceeded');
} else if (error instanceof RateLimitError) {
console.error(`Rate limited. Retry after ${error.retryAfter}s`);
} else if (error instanceof ValidationError) {
console.error('Validation failed:', error.details);
} else {
console.error('Unknown error:', error);
}
}Error Types
AuthenticationError(401) - Invalid or missing API keyPermissionError(403) - Insufficient permissionsNotFoundError(404) - Resource not foundStorageLimitError(413) - Storage limit exceededUnsupportedMediaError(415) - Invalid file typeRateLimitError(429) - Rate limit exceededValidationError(400) - Invalid parametersServerError(500+) - Server errorNetworkError- Network/timeout error
Advanced Configuration
const imperial = new ImperialClient({
apiKey: 'imperial_live_xxxxxxxxxxxxx',
baseUrl: 'https://api.imperial.gay', // Custom API URL
timeout: 30000, // Request timeout in ms (default: 30000)
fetch: customFetch // Custom fetch implementation
});TypeScript Support
Full TypeScript support with comprehensive type definitions:
import type {
UploadResult,
MediaItem,
ListMediaResult,
RateLimitInfo
} from '@imperial/sdk';
const result: UploadResult = await imperial.upload({ ... });
const media: ListMediaResult = await imperial.list();
const item: MediaItem = await imperial.get('id');
const rateLimit: RateLimitInfo | undefined = imperial.getRateLimitInfo();Response Types
UploadResult
{
_id: string;
url: string;
thumbnailUrl?: string; // For videos
filename: string;
originalFilename: string;
fileSize: number; // Bytes (after compression)
originalFileSize: number; // Bytes (before compression)
compressed: boolean;
compressionQuality?: number;
mimeType: string;
createdAt: string; // ISO 8601
}MediaItem
{
_id: string;
url: string;
thumbnailUrl?: string | null;
mimeType: string;
prompt: string; // Original filename
modelName: string; // File size (human readable)
size: { width: number; height: number };
createdAt: string;
type: 'upload' | 'ai-image';
}Best Practices
1. Store API Keys Securely
// ✅ Good - Use environment variables
const imperial = new ImperialClient({
apiKey: process.env.IMPERIAL_API_KEY!
});
// ❌ Bad - Hard-coded keys
const imperial = new ImperialClient({
apiKey: 'imperial_live_xxxxxxxxxxxxx' // Don't do this!
});2. Handle Rate Limits
async function uploadWithRetry(file: Buffer, filename: string, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await imperial.upload({ file, filename });
} catch (error) {
if (error instanceof RateLimitError && error.retryAfter) {
await new Promise(resolve => setTimeout(resolve, error.retryAfter * 1000));
continue;
}
throw error;
}
}
}3. Batch Operations
// ✅ Good - Use batch upload
await imperial.uploadBatch(files);
// ❌ Slower - Individual uploads
for (const file of files) {
await imperial.upload(file);
}Links
- 📖 Documentation
- 🌐 Website
- 📊 Dashboard
- 💬 Discord
- 🐙 GitHub
License
MIT © Imperial