@outfitcanvas/fitview-sdk
v1.0.3
Published
TypeScript SDK for FitView API - virtual try-on service
Maintainers
Readme
FitView TypeScript SDK
Official TypeScript SDK for the FitView API - virtual try-on service.
Installation
npm install @outfitcanvas/fitview-sdk
# or
yarn add @outfitcanvas/fitview-sdk
# or
pnpm add @outfitcanvas/fitview-sdkAPI key
To use the FitView API you need an API key. Purchase and register at https://outfitcanvas.app to acquire your API key. Use it in the client as shown below.
Quick Start
import { FitViewClient, OutfitCanvasModel } from '@outfitcanvas/fitview-sdk';
// Initialize the client
const client = new FitViewClient({
apiKey: 'pk_live_your_api_key_here',
baseURL: 'https://api.fitview.io', // Optional, defaults to production
});
// Generate a virtual try-on
const result = await client.generateFitView({
person_image: 'https://example.com/person.jpg',
garment_image: 'https://example.com/garment.jpg',
model: OutfitCanvasModel.CanvasStandard,
quality: 'high',
});
// Wait for completion
const completed = await result.waitForCompletion();
// Get the result image URL
console.log('FitView URL:', completed.fitviewUrl);Security: Prefer environment variables for your API key (e.g. process.env.FITVIEW_API_KEY). Never embed API keys in client-side or public code—use the SDK only in server-side or trusted environments.
Quick reference: For a one-page TypeScript method/signature overview (IDE autocomplete and LLM code generation), see Quick Reference — TypeScript.
API Reference
FitViewClient
Main client class for interacting with the FitView API.
Constructor
const client = new FitViewClient({
apiKey: string, // Required: Your API key
baseURL?: string, // Optional: API base URL (default: https://api.fitview.io)
timeout?: number, // Optional: Request timeout in ms (default: 300000)
apiVersion?: string, // Optional: API version (default: 'v1')
maxRetries?: number, // Optional: Retries for 429/5xx (default: 3, set 0 to disable)
retryDelay?: number, // Optional: Base delay in ms between retries (default: 1000)
authMethod?: 'bearer' | 'apiKey', // Optional: Bearer token (default) or X-API-Key header
fetch?: typeof fetch, // Optional: Custom fetch implementation
headers?: Record<string, string>, // Optional: Additional headers
validateInputImages?: boolean, // Optional: Validate image format/size before sending (default: true)
optimizeImages?: boolean, // Optional: Optimize base64 images client-side when sharp is available (default: false)
optimizeImageOptions?: { maxDimension?: number; jpegQuality?: number; outputFormat?: 'jpeg' | 'png' | 'webp' | 'original' },
});Methods
generateFitView(request: FitViewRequest): Promise<FitViewResult>
Generate a virtual try-on result.
const result = await client.generateFitView({
person_image: 'https://example.com/person.jpg',
garment_image: 'https://example.com/garment.jpg',
model: OutfitCanvasModel.CanvasStandard,
quality: 'high',
use_case: 'fashion',
idempotency_key: '550e8400-e29b-41d4-a716-446655440000',
webhook_url: 'https://your-app.com/webhook',
});getFitView(jobId: string): Promise<FitViewResult>
Get the status of a FitView job.
const result = await client.getFitView('fv_abc123');
console.log(result.status); // 'queued' | 'processing' | 'completed' | 'failed'batchGenerateFitView(requests: FitViewRequest[]): Promise<FitViewBatchResponse>
Generate multiple virtual try-on results in a batch (max 50).
const batch = await client.batchGenerateFitView([
{ person_image: '...', garment_image: '...' },
{ person_image: '...', garment_image: '...' },
]);
console.log(`Success: ${batch.success_count}, Failed: ${batch.failure_count}`);listModels(): Promise<ModelInfo[]>
List available models for your account tier.
const models = await client.listModels();
models.forEach(model => {
console.log(`${model.displayName}: ${model.creditCost} credits`);
});waitForFitView(jobId: string, options?: WaitOptions): Promise<FitViewResult>
Wait for a job to complete with polling. Defaults (used when you omit options): wait 10 seconds before the first status fetch, then poll every 2 seconds until done.
Warning: Consult FitView support before changing
initialDelayorinterval. Other values may affect rate limits, reliability, and support eligibility.
// Use defaults: 10s before first fetch, 2s between polls (recommended)
const result = await client.waitForFitView('fv_abc123');
// Or customize (consult support before changing polling defaults)
const result = await client.waitForFitView('fv_abc123', {
timeout: 300000,
initialDelay: 10000, // default: 10s before first fetch
interval: 2000, // default: 2s between subsequent polls
onProgress: (result) => console.log(`Status: ${result.status}`),
});getRateLimitAddons(): Promise<RateLimitAddonsResponse>
Get active rate limit add-ons and total boost (billing).
const { active_addons, total_boost } = await client.getRateLimitAddons();healthCheck(): Promise<{ status: string; timestamp?: string }>
Basic health check (no auth). Returns { status, timestamp }.
readinessCheck(): Promise<HealthStatus>
Readiness check with dependency status (no auth). Returns status, version, uptime, checks.
livenessCheck(): Promise<{ status: string }>
Liveness check (no auth). Returns { status: 'alive' }.
verifyWebhook(payload: string | Buffer, signature: string, secret: string): boolean
Verify webhook signature.
const isValid = client.verifyWebhook(
rawBody,
signature,
webhookSecret
);FitViewResult
Wrapper class for FitView API responses with convenient methods.
Properties
jobId: string- Job identifierstatus: 'queued' | 'processing' | 'completed' | 'failed'- Current statusfitviewUrl?: string- URL of the generated image (if completed)thumbnailUrl?: string- URL of the thumbnail (if available)modelUsed?: string- Model used for generationmodelVersion?: string- Model versiongenerationTimeMs?: number- Generation time in millisecondsenrichedData?: EnrichedData- Additional enriched dataerror?: FitViewError- Error information (if failed)metadata: ResponseMetadata- Response metadata
Methods
isCompleted(): boolean
Check if the job is completed.
isFailed(): boolean
Check if the job has failed.
isProcessing(): boolean
Check if the job is still processing.
download(): Promise<Buffer | Blob>
Download the fitview image.
const image = await result.download();
// In Node.js: Buffer
// In browser: Blobrefresh(): Promise<FitViewResult>
Refresh the result by fetching the latest status.
const updated = await result.refresh();waitForCompletion(options?: WaitOptions): Promise<FitViewResult>
Wait for the job to complete. Uses the same defaults as waitForFitView (10s before first fetch, 2s between polls). Consult FitView support before changing initialDelay or interval.
// Defaults (recommended)
const completed = await result.waitForCompletion();
// With options (consult support before changing polling defaults)
const completed = await result.waitForCompletion({
timeout: 300000,
initialDelay: 10000,
interval: 2000,
onProgress: (result) => console.log(result.status),
});Examples
A runnable quick start (same flow as the Python example) is in examples/:
- TypeScript:
npx tsx examples/quickstart.ts(frompackages/sdk-typescript) - JavaScript:
npm run build && node examples/quickstart.mjs
Set FITVIEW_API_KEY and optionally FITVIEW_BASE_URL in the environment.
Basic Generation
import { FitViewClient, OutfitCanvasModel } from '@outfitcanvas/fitview-sdk';
const client = new FitViewClient({
apiKey: process.env.FITVIEW_API_KEY!,
});
// Generate
const result = await client.generateFitView({
person_image: 'https://example.com/person.jpg',
garment_image: 'https://example.com/garment.jpg',
model: OutfitCanvasModel.CanvasStandard,
});
// Wait for completion
const completed = await result.waitForCompletion();
// Use the result
if (completed.isCompleted()) {
console.log('Image URL:', completed.fitviewUrl);
// Download the image
const image = await completed.download();
// Save or process the image...
}Image sources (URLs vs device)
- Images on your servers: Pass a public HTTP or HTTPS URL in
person_imageandgarment_image. FitView fetches the image from that URL; no separate upload step is required. The URL must be reachable by the FitView API (public or allowlisted). - Images on user devices: The API accepts base64 (or data URL) directly in
person_imageandgarment_imagefor generate requests—no upload step required. For very large images or when you prefer to upload once and reuse the URL, use upload first, then generate: callclient.uploadImage(base64)orclient.uploadImageFromFile(filePath)(Node.js) to get a URL, then pass that URL intogenerateFitView.
Using Base64 Images
const result = await client.generateFitView({
person_image: {
type: 'base64',
data: 'data:image/jpeg;base64,/9j/4AAQSkZJRg...',
},
garment_image: {
type: 'base64',
data: 'data:image/jpeg;base64,/9j/4AAQSkZJRg...',
},
});Upload from file (Node.js)
import { FitViewClient } from '@outfitcanvas/fitview-sdk';
const client = new FitViewClient({ apiKey: process.env.FITVIEW_API_KEY! });
// Upload a local file and get a URL for generate
const { url } = await client.uploadImageFromFile('/path/to/person.jpg');
const result = await client.generateFitView({
person_image: url,
garment_image: 'https://example.com/garment.jpg',
});Idempotency key (safe retries)
To retry a create-job request without creating duplicate jobs, send an idempotency_key. Generate a new UUID per logical request:
import { FitViewClient, generateIdempotencyKey } from '@outfitcanvas/fitview-sdk';
const client = new FitViewClient({ apiKey: process.env.FITVIEW_API_KEY! });
const result = await client.generateFitView({
person_image: 'https://example.com/person.jpg',
garment_image: 'https://example.com/garment.jpg',
idempotency_key: generateIdempotencyKey(), // or FitViewClient.generateIdempotencyKey()
});Batch Processing
const batch = await client.batchGenerateFitView([
{
person_image: 'https://example.com/person1.jpg',
garment_image: 'https://example.com/garment1.jpg',
},
{
person_image: 'https://example.com/person2.jpg',
garment_image: 'https://example.com/garment2.jpg',
},
]);
// Process results
batch.results.forEach((item, index) => {
if (item.response) {
console.log(`Request ${index + 1}: ${item.response.job_id}`);
} else if (item.error) {
console.error(`Request ${index + 1} failed:`, item.error.message);
}
});Error Handling
import {
FitViewClient,
FitViewValidationError,
FitViewInsufficientCreditsError,
FitViewRateLimitError,
} from '@outfitcanvas/fitview-sdk';
try {
const result = await client.generateFitView({
person_image: 'invalid-url',
garment_image: 'https://example.com/garment.jpg',
});
} catch (error) {
if (error instanceof FitViewValidationError) {
console.error('Validation error:', error.validationErrors);
} else if (error instanceof FitViewInsufficientCreditsError) {
console.error(`Need ${error.required} credits, have ${error.available}`);
} else if (error instanceof FitViewRateLimitError) {
console.error(`Rate limited. Retry after ${error.retryAfter} seconds`);
} else {
console.error('Unexpected error:', error);
}
}Webhook Verification
import express from 'express';
const app = express();
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
const signature = req.headers['x-fitview-signature'] as string;
const secret = process.env.WEBHOOK_SECRET!;
const isValid = client.verifyWebhook(
req.body,
signature,
secret
);
if (!isValid) {
return res.status(401).send('Invalid signature');
}
const payload = JSON.parse(req.body.toString());
// Process webhook...
res.status(200).send('OK');
});Custom Timeout, Retries, and X-API-Key
const client = new FitViewClient({
apiKey: process.env.FITVIEW_API_KEY!,
timeout: 60000, // 1 minute timeout
maxRetries: 3, // Retry 429 and 5xx (default)
retryDelay: 1000, // Base delay before retry (exponential backoff)
authMethod: 'apiKey', // Use X-API-Key header instead of Bearer
});
// With custom wait options (consult support before changing initialDelay/interval)
const result = await client.waitForFitView('fv_abc123', {
timeout: 600000,
initialDelay: 10000,
interval: 5000,
onProgress: (result) => {
console.log(`Progress: ${result.status}`);
},
});Listing Available Models
const models = await client.listModels();
console.log('Available models:');
models.forEach(model => {
console.log(`
${model.displayName} (${model.id})
Cost: ${model.creditCost} credits
Estimated latency: ${model.estimatedLatencyMs}ms
`);
});Types
FitViewRequest
interface FitViewRequest {
person_image: string | ImageInput;
garment_image: string | ImageInput;
model?: OutfitCanvasModel;
quality?: 'fast' | 'balanced' | 'high';
use_case?: 'casual' | 'fashion' | 'formal';
user_id?: string;
session_id?: string;
product_id?: string;
idempotency_key?: string;
webhook_url?: string;
context?: UserContext;
metadata?: Record<string, any>;
}OutfitCanvasModel
enum OutfitCanvasModel {
CanvasPro = 'canvas-pro',
CanvasProFast = 'canvas-pro-fast',
CanvasStandard = 'canvas-standard',
CanvasPlus = 'canvas-plus',
CanvasExpress = 'canvas-express',
CanvasInstant = 'canvas-instant',
CanvasFashion = 'canvas-fashion',
CanvasCasual = 'canvas-casual',
CanvasFormal = 'canvas-formal',
Canvas4K = 'canvas-4k',
CanvasVideo = 'canvas-video',
}Image validation and optimization
To reduce unnecessary backend compute, the SDK can validate and optionally optimize images on the client:
Validation (default: on)
Before each request, the SDK checks that base64 images are valid, within the 20MB limit, and in a supported format (JPEG, PNG, WebP, HEIC/HEIF). Invalid inputs throwFitViewValidationErrorimmediately, so you get clear errors without calling the API. SetvalidateInputImages: falsein the client to disable.Optimization (default: off)
WithoptimizeImages: true, base64 images are resized (default max 2048px) and recompressed (e.g. JPEG 85%) on the client when sharp is installed. This sends smaller payloads and can reduce backend processing. URL inputs are not optimized. Install sharp optionally:npm install sharp.
Best practices
- Pre-optimize images when possible: max dimension ~2048px, under ~5MB, JPEG/PNG/WebP. The API accepts up to 20MB and the same formats; smaller, well-formatted images are faster and cheaper to process.
- Use validation (default) to fail fast on bad input.
- Enable
optimizeImagesin Node.js if you often send large base64 images and have sharp installed.
import { FitViewClient, validateBase64Image, optimizeBase64Image } from '@outfitcanvas/fitview-sdk';
// Optional: validate or optimize a single image before building the request
const result = validateBase64Image('data:image/jpeg;base64,...');
if (!result.valid) {
console.error(result.message);
}
const optimized = await optimizeBase64Image('data:image/jpeg;base64,...', { maxDimension: 2048, jpegQuality: 85 });
// Client with validation (default) and optional optimization
const client = new FitViewClient({
apiKey: process.env.FITVIEW_API_KEY!,
validateInputImages: true,
optimizeImages: true,
optimizeImageOptions: { maxDimension: 2048, jpegQuality: 85 },
});Error Handling
The SDK provides specific error classes for different scenarios:
FitViewError- Base error classFitViewAPIError- API errors (4xx, 5xx)FitViewValidationError- Validation errors (400)FitViewAuthenticationError- Authentication errors (401)FitViewInsufficientCreditsError- Insufficient credits (402)FitViewRateLimitError- Rate limit errors (429)FitViewTimeoutError- Timeout errorsFitViewNetworkError- Network errors
Troubleshooting
getaddrinfo ENOTFOUND api.fitview.io (or similar)
This means the hostname of the API could not be resolved (DNS failure). Common causes:
Wrong or placeholder base URL – The default
baseURLishttps://api.fitview.io. If your API is hosted elsewhere (e.g. your own Cloud Run URL), set the correct URL when creating the client:const client = new FitViewClient({ apiKey: process.env.FITVIEW_API_KEY!, baseURL: process.env.FITVIEW_BASE_URL || 'https://your-actual-api.run.app', });Or set the
FITVIEW_BASE_URLenvironment variable (e.g.https://fitview-api-xxxxx-uc.a.run.appwithout/api/v1).Network or DNS issues – Firewall, VPN, or local DNS may block or fail to resolve the host. Try from another network or verify the API URL in a browser/curl.
Custom domain not set up – If
api.fitview.iois not yet configured in DNS for your environment, use the actual API URL provided by your dashboard or deployment (e.g. Cloud Run URL) asbaseURL.
Requirements
- Node.js 18.0.0 or higher
- TypeScript 5.0.0 or higher (for TypeScript projects)
Publishing (maintainers)
To publish to npm via GitHub Actions, push a tag matching sdk-ts-v* (e.g. sdk-ts-v1.0.1). Ensure the repository secret NPM_TOKEN is set (npm Automation or Classic token with publish permission). The workflow runs build, type-check, and npm publish --access public.
License
MIT
Support
For issues and questions:
- Documentation: https://docs.fitview.com
- Email: [email protected]
