API Documentation
Integrate bitStudio's powerful AI capabilities directly into your applications with our comprehensive API.
Note: API responses express all credit amounts in scaled integer units (1 credit equals 100). Convert these values in your client before displaying them to users.
All API requests require authentication using an API key
Base URL for all API requests:
https://api.bitstudio.ai
Include your API key in the Authorization header:
Authorization: Bearer YOUR_API_KEY
Keep your API keys secure and never share them in public repositories or client-side code.
You can manage your API keys in the API Keys section of your account.
Combine person and outfit images using AI
POST /images/virtual-try-on
Request Parameters
| Parameter | Type | Description | Required |
|---|---|---|---|
person_image_id | string | ID of image with type "virtual-try-on-person" | No |
person_image_url | string | URL of a person image to use | No |
outfit_image_id | string | ID of image with type "virtual-try-on-outfit" | No |
outfit_image_url | string | URL of an outfit image to use | No |
outfit_asset_id | string | ID of an outfit asset to use | No |
model | string | v1, v4, v5, or v6. v6 is allowlisted API-key only. | No |
prompt | string | Optional text description to guide generation | No |
resolution | string | standard or high. For v6, standard is 1K/1MP and high is 2K/2.5MP. | No |
num_images | number | Number of output images (1-4) | No |
seed | int | Seed for reproducible generations | No |
To obtain image IDs, you must first upload images using the with the appropriate type. See the Image Upload tab.
Example Request
{
"person_image_id": "VT_PERSON_123",
"outfit_image_id": "VT_OUTFIT_456",
"prompt": "professional portrait, high quality",
"resolution": "high",
"num_images": 2,
"style": "studio"
} JavaScript Example
const virtualTryOn = async (personImageId, outfitImageId) => {
const response = await fetch('https://api.bitstudio.ai/images/virtual-try-on', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
person_image_id: personImageId,
outfit_image_id: outfitImageId,
resolution: "standard",
num_images: 1
})
});
const results = await response.json();
return results[0]; // Returns the first generated image info
};
// After uploading person and outfit images and getting their IDs
const tryOnResult = await virtualTryOn('IMG_123', 'IMG_456');
console.log('Generation started:', tryOnResult.id);
// Poll for completion
const pollForCompletion = async (imageId) => {
let complete = false;
while (!complete) {
const response = await fetch(`https://api.bitstudio.ai/images/${imageId}`, {
headers: { 'Authorization': 'Bearer YOUR_API_KEY' }
});
const imageData = await response.json();
if (imageData.status === 'completed') {
complete = true;
return imageData;
} else if (imageData.status === 'failed') {
throw new Error('Image generation failed');
}
// Wait 2 seconds before polling again
await new Promise(resolve => setTimeout(resolve, 2000));
}
};
// Get the completed image
const finalImage = await pollForCompletion(tryOnResult.id);
console.log('Image is ready:', finalImage.path); Response Format
[
{
"id": "GEN_789",
"status": "pending",
"task": "virtual-try-on",
"estimated_completion": "2024-02-20T15:00:00Z",
"credits_used": 2,
"source_image_ids": [
"VT_PERSON_123",
"VT_OUTFIT_456"
]
}
] Check image status by polling GET /images/{id}. Status will transition from "pending" → "generating" → "completed".
Once completed, the path field will contain the URL to the generated image.
Tips for Best Results
- Person images: Full body, front-facing photos with neutral pose work best
- Outfit images: Clear, isolated garments on white/transparent background
- Resolution: High-quality input images improve output quality
- Timing: Processing typically takes 15-30 seconds per image
Upload images for processing with specific types
POST /images
Request Format
Images must be uploaded as multipart/form-data with the following fields:
| Parameter | Type | Description | Required |
|---|---|---|---|
file | file | Image file to upload (JPEG, PNG, WebP) | Yes |
type | string | Type of image (see supported types below) | No |
The API accepts image files up to 10MB. For optimal results, use high-quality images with clear subjects.
Supported Image Types
virtual-try-on-personPerson Image
virtual-try-on-outfitOutfit Image
inpaint-baseBase Image
inpaint-maskMask Image
editEdit Image
inpaint-referenceReference Image
image-to-videoImage to Video Base
Example: Upload Person Image for Virtual Try-On
curl -X POST https://api.bitstudio.ai/images \ -H "Authorization: Bearer YOUR_API_KEY" \ -F "[email protected]" \ -F "type=virtual-try-on-person"
JavaScript Example (Browser)
const uploadImage = async (file, type) => {
const formData = new FormData();
formData.append('file', file);
formData.append('type', type);
const response = await fetch('https://api.bitstudio.ai/images', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY'
},
body: formData
});
const result = await response.json();
return result;
};
// Upload person image
const personImg = document.querySelector('#personImageInput').files[0];
const personImageData = await uploadImage(personImg, 'virtual-try-on-person');
// Upload outfit image
const outfitImg = document.querySelector('#outfitImageInput').files[0];
const outfitImageData = await uploadImage(outfitImg, 'virtual-try-on-outfit');
// Now use the returned image IDs for virtual try-on
console.log('Person Image ID:', personImageData.id);
console.log('Outfit Image ID:', outfitImageData.id); Response Format
{
"id": "IMG_123",
"type": "virtual-try-on-person",
"path": "https://media.bitstudio.ai/user-content/u123/image.jpg",
"status": "completed",
"width_px": 1024,
"height_px": 1024,
"is_generated": false,
"for_training": false,
"created_timestamp": "2024-02-20T14:30:00Z",
"versions": []
} Use the returned id value in subsequent API calls, such as virtual try-on.
Create Studio images from prompts, avatar assets, outfit assets, sets, presets, poses, and styles
POST /images/generate
The generate endpoint returns 202 Accepted with pending image rows. Poll GET /images/{id} until each row is completed or failed.
Presets Mode vs Legacy Mode
| Mode | Use it for | How prompts and assets are interpreted |
|---|---|---|
presets | Current asset-based generate requests with model, outfit, preset, pose, set, or style assets. | A preset asset supplies the exact environment, composition, framing, lighting, and background reference. Outfit references define wardrobe, and model assets define the avatar. The prompt and set_text fields refine the selected preset rather than replacing it. |
legacy | Older prompt-first integrations and older set flows that use set_id or plain set_text without a preset asset. | The request behaves like the previous generate API: prompt text is the primary scene instruction, and any set text is treated as supporting scene direction. Prefer presets for new integrations. |
- For new integrations, send generate_mode: "presets" explicitly.
- If generate_mode is omitted, a request with a preset asset is inferred as presets; otherwise it falls back to legacy.
- Preset assets are the recommended way to reuse a shot setup. Legacy set fields remain available for older integrations.
{
"prompt": "full-body ecommerce campaign on a white seamless background",
"generate_mode": "legacy",
"num_images": 1,
"model_version": "nano-banana-2",
"model_text": "adult model, relaxed standing pose",
"outfit_text": "show the jacket clearly",
"set_text": "clean white studio floor, soft shadows"
} Request Parameters
| Parameter | Type | Description | Required |
|---|---|---|---|
prompt | string | In presets mode, scene or refinement text that complements preset/set assets. In legacy mode, the primary text prompt. | Yes |
generate_mode | string | presets for the current asset-based flow, legacy for older prompt/set integrations. If omitted, preset assets infer presets; otherwise legacy. | No |
num_images | number | Number of pending image rows to create | Yes |
aspect_ratio | string | Target frame, validated per model | No |
resolution | string | standard or high | No |
model_version | string | nano-banana-2 or nano-banana-pro | No |
asset_ids | array | Model/avatar, preset, pose, set, or style asset IDs used as generation context. Style assets are prompt-only direction. Include at most one preset or set asset. | No |
model_text | string | Extra avatar or model direction | No |
outfit_text | string | Extra outfit or product direction | No |
style | string | Optional text style direction. For nano-banana-2 and nano-banana-pro this is included in the prompt; it is not a separate model setting. | No |
style_id | string | Optional style asset ID. The style asset characteristics are used as text direction; no style reference image is sent to nano-banana-2 or nano-banana-pro. | No |
set_id | string | Legacy set table ID for older integrations; prefer preset assets in asset_ids | No |
set_text | string | Additional set or preset refinements | No |
outfit_asset_id | string | Single outfit asset reference | No |
outfit_image_id | string | Single uploaded outfit image reference | No |
outfit_image_url | string | Single remote outfit image reference | No |
outfit_asset_ids | array | Multiple outfit asset references, up to three sources | No |
outfit_image_ids | array | Multiple uploaded outfit image references, up to three sources | No |
outfit_image_urls | array | Multiple remote outfit image references, up to three sources | No |
Multi-source outfit fields are supported by nano-banana-2 and nano-banana-pro.
Example Request
{
"prompt": "editorial studio campaign, clean white sweep",
"generate_mode": "presets",
"num_images": 2,
"aspect_ratio": "3:4",
"resolution": "standard",
"model_version": "nano-banana-2",
"asset_ids": [
"MODEL_ASSET_123",
"PRESET_ASSET_456"
],
"model_text": "use the avatar identity, relaxed standing pose",
"outfit_text": "keep the jacket open and the product fully visible",
"outfit_asset_ids": [
"JACKET_ASSET_789",
"TROUSERS_ASSET_012"
]
} Model Assets
Model assets are avatar or model references. Use them by adding the model asset ID to asset_ids and optionally adding model_text for per-request direction.
POST /assets
{
"type": "model",
"alias": "Face Avatar",
"class": "female",
"characteristics": "freckles, dark hair",
"display_image": "https://example.com/avatar.jpg"
} POST /assets/<model_asset_id>/images Content-Type: multipart/form-data file=<image> type=training
- type=training requires an asset ID.
- The first uploaded asset image becomes the display image if the asset does not already have one.
Preset Assets
Preset assets capture the repeatable world of a shot: environment, composition, framing, camera feel, lighting, background tone, and shadow treatment. Create them manually with a description, or use preset analysis to draft the description from one to three reference images.
POST /assets/preset-analysis
{
"image_ids": [
"PRESET_REF_IMAGE_1",
"PRESET_REF_IMAGE_2"
]
} {
"preset_name": "Warm Cyclorama Portrait",
"prompt": "Exact preset. Use a warm seamless cyclorama with soft directional key light, subtle floor shadow, and a centered three-quarter portrait crop."
} Use the analysis response's preset_name as the asset alias and prompt as the preset asset description.
POST /assets
{
"type": "preset",
"alias": "Warm Cyclorama Portrait",
"description": "Exact preset. Use a warm seamless cyclorama with soft directional key light, subtle floor shadow, and a centered three-quarter portrait crop.",
"display_image": "https://example.com/preset-cover.jpg",
"tag_ids": [
"FOLDER_OR_TAG_ID"
]
} POST /assets/<preset_asset_id>/images Content-Type: multipart/form-data file=<image> type=training
POST /images/<image_id>/asset
{
"asset_id": "PRESET_ASSET_456"
} - Preset assets can include up to three reference images.
- To use a preset, include the preset asset ID in asset_ids and send generate_mode: "presets".
- Only one preset or set asset is allowed per generate request.
Outfit Assets
Outfit assets represent products or wardrobe items. Use a single outfit with outfit_asset_id, or combine multiple products with outfit_asset_ids.
POST /assets
{
"type": "outfit",
"alias": "Black leather jacket",
"sku": "JACKET-BLK-001",
"display_image": "https://example.com/jacket-front.jpg",
"tag_ids": [
"FOLDER_OR_TAG_ID"
]
} POST /images Content-Type: multipart/form-data file=<image> type=virtual-try-on-outfit
POST /images/<image_id>/asset
{
"asset_id": "OUTFIT_ASSET_123"
} You can also upload directly to the outfit asset:
POST /assets/<outfit_asset_id>/images Content-Type: multipart/form-data file=<image> type=virtual-try-on-outfit
For a remote product image, link it without uploading binary data:
POST /images/<synthetic_or_missing_id>/asset
{
"asset_id": "OUTFIT_ASSET_123",
"image_url": "https://cdn.example.com/product.jpg",
"image_type": "virtual-try-on-outfit",
"width_px": 1200,
"height_px": 1600
} - Outfit assets can include up to 10 reference images.
- Linked outfit images can be used as product references during generation.
- Use POST /assets/{asset_id}/describe-outfit to generate or refresh an outfit description.
Use Assets In Generate
{
"prompt": "minimal ecommerce studio campaign",
"generate_mode": "presets",
"num_images": 1,
"model_version": "nano-banana-2",
"asset_ids": [
"MODEL_ASSET_123"
],
"outfit_asset_id": "OUTFIT_ASSET_456",
"outfit_text": "make the jacket the hero product"
} Generated image responses include the associated asset IDs, including outfit asset IDs used by the request.
Sets, Presets, Poses, And Styles
- pose assets contribute characteristics as pose text.
- preset assets define a reusable shot setup and can attach up to three reference images.
- set assets are supported for older scene flows; prefer preset assets for new integrations.
- Only one set or preset asset is allowed per generate request.
- style and style_id are prompt-only for nano-banana-2 and nano-banana-pro. A style_id uses the style asset's characteristics as text direction; it does not send a style reference image.
JavaScript Example
const pollImage = async (imageId) => {
while (true) {
const response = await fetch('https://api.bitstudio.ai/images/' + imageId, {
headers: { Authorization: 'Bearer YOUR_API_KEY' }
});
const image = await response.json();
if (image.status === 'completed') return image;
if (image.status === 'failed') throw new Error('Image generation failed');
await new Promise((resolve) => setTimeout(resolve, 2000));
}
};
const generateImage = async () => {
const response = await fetch('https://api.bitstudio.ai/images/generate', {
method: 'POST',
headers: {
Authorization: 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
prompt: 'editorial studio campaign, clean white sweep',
generate_mode: 'presets',
num_images: 1,
aspect_ratio: '3:4',
resolution: 'standard',
model_version: 'nano-banana-2',
asset_ids: ['MODEL_ASSET_123', 'PRESET_ASSET_456'],
outfit_asset_ids: ['JACKET_ASSET_789'],
outfit_text: 'make the jacket the hero product'
})
});
const pendingImages = await response.json();
return pollImage(pendingImages[0].id);
};
const finalImage = await generateImage();
console.log('Image is ready:', finalImage.path); Response Format
[
{
"id": "GEN_456",
"status": "pending",
"task": "generate",
"aspect_ratio": "3:4",
"resolution": "standard",
"asset_ids": [
"MODEL_ASSET_123",
"PRESET_ASSET_456",
"JACKET_ASSET_789"
],
"source_image_ids": [
"OUTFIT_IMAGE_789"
],
"model_text": "use the avatar identity, relaxed standing pose",
"outfit_text": "keep the jacket open and the product fully visible",
"set_text": "editorial studio campaign, clean white sweep"
}
] Check image status by polling GET /images/{id} until the status is completed.
Tips for Effective Generate Requests
- Separate concerns: Put avatar direction in model_text, product direction in outfit_text, and scene or preset direction in prompt or set_text.
- Use assets for repeatability: Prefer model and outfit assets over long repeated prompt text when the same avatar or product is reused.
- Use multiple outfit assets carefully: Keep each source focused on a clear garment or product role.
- Poll the pending rows: The initial response confirms the job was accepted, not that the final image is ready.
Increase image resolution and create new versions
POST /images/{id}/upscale Request Parameters
| Parameter | Type | Description | Required |
|---|---|---|---|
upscale_factor | number | 1, 2 (2x resolution) or 4 (4k) | Yes |
denoise | number | Noise reduction strength (0.05-0.5) - not used for 4k | No |
version_id | string | Specific version to upscale | No |
Example Request
{
"upscale_factor": 2,
"denoise": 0.3
} JavaScript Example
const upscaleImage = async (imageId) => {
const response = await fetch(`https://api.bitstudio.ai/images/${imageId}/upscale`, {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
upscale_factor: 2,
denoise: 0.3
})
});
const result = await response.json();
return result;
};
// Call the function to upscale an image
const upscaleResult = await upscaleImage('IMG_123');
console.log('Upscaling started:', upscaleResult.id);
// Poll for completion
const pollForCompletion = async (imageId) => {
let complete = false;
while (!complete) {
const response = await fetch(`https://api.bitstudio.ai/images/${imageId}`, {
headers: { 'Authorization': 'Bearer YOUR_API_KEY' }
});
const imageData = await response.json();
if (imageData.status === 'completed') {
complete = true;
return imageData;
} else if (imageData.status === 'failed') {
throw new Error('Image upscaling failed');
}
// Wait 2 seconds before polling again
await new Promise(resolve => setTimeout(resolve, 2000));
}
};
// Get the upscaled image details
const finalImage = await pollForCompletion(upscaleResult[0].id);
console.log('Upscaled image is ready:', finalImage); Response Format
[
{
"id": "UPSCALE_123",
"status": "pending",
"task": "upscale",
"source_image_ids": [
"ORIGINAL_123"
],
"base_image_version_id": "VERSION_456"
}
] Successful upscaling adds a new version to the original image's versions array with version_type: "upscaled"
Tips for Best Results
- Input quality: Better results with higher quality source images
- Denoise: Higher values (0.3-0.5) for noisy images, lower (0.05-0.2) for clean images
- Processing time: Can take 30-60 seconds depending on image size
Modify specific parts of an image
POST /images/{id}/inpaint Request Parameters
| Parameter | Type | Description | Required |
|---|---|---|---|
mask_image_id | string | ID of image with type "inpaint-mask" | Yes |
reference_image_id | string | ID of image with type "inpaint-reference" | No |
prompt | string | Description of desired changes | Yes |
denoise | number | Strength of effect (0.05-1.0) | No |
num_images | number | Number of results to generate (1-4) | No |
Example Request
{
"mask_image_id": "MASK_123",
"reference_image_id": "REF_456",
"prompt": "Sunny beach with palm trees",
"denoise": 1,
"num_images": 1
} JavaScript Example
const inpaintImage = async (imageId, maskImageId, prompt) => {
const response = await fetch(`https://api.bitstudio.ai/images/${imageId}/inpaint`, {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
mask_image_id: maskImageId,
prompt: prompt,
denoise: 1.0,
num_images: 1
})
});
const result = await response.json();
return result;
};
// Call the function to inpaint an image
const inpaintResult = await inpaintImage('BASE_123', 'MASK_456', 'Replace with a beautiful beach');
console.log('Inpainting started:', inpaintResult[0].id);
// Poll for completion as in previous examples
const finalImage = await pollForCompletion(inpaintResult[0].id);
console.log('Inpainted image is ready:', finalImage.path); Response Format
[
{
"id": "INPAINT_123",
"status": "pending",
"task": "inpaint",
"source_image_ids": [
"BASE_123",
"MASK_456"
],
"estimated_completion": "2024-02-20T15:30:00Z",
"credits_used": 1
}
] Creating a Mask Image
To create a mask image:
- Start with your base image
- Create a black and white mask where:
- White areas: Parts to be replaced/modified
- Black areas: Parts to keep unchanged
- Upload the mask with type=inpaint-mask
- Use the returned mask ID in your inpainting request
Tips for Best Results
- Clear masks: Use solid white for areas to change, black for areas to preserve
- Descriptive prompts: Be specific about what to add in the masked area
- Denoise values: Higher values (0.8-1.0) for more dramatic changes, lower for subtle edits
- Reference images: Use reference images to guide style and content
Apply text-guided edits to existing images
POST /images/{id}/edit Request Parameters
| Parameter | Type | Description | Required |
|---|---|---|---|
version_id | string | Specific version ID to edit | No |
prompt | string | Edit instructions or description | Yes |
resolution | string | standard or low (high not supported) | Yes |
num_images | number | Number of edited variations (1-4) | Yes |
seed | number | Random seed for reproducibility | Yes |
The edit operation creates a new version of the existing image. High resolution is not supported for edit operations.
Example Request
{
"prompt": "Change the background to a beach scene",
"resolution": "standard",
"num_images": 1,
"seed": 42
} JavaScript Example
const editImage = async (imageId, prompt) => {
const response = await fetch(`https://api.bitstudio.ai/images/${imageId}/edit`, {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
prompt: prompt,
resolution: 'standard',
num_images: 1,
seed: 42
})
});
const result = await response.json();
return result;
};
// Call the function to edit an image
const editResult = await editImage('IMG_123', 'Add a sunset in the background');
console.log('Edit started, updated image:', editResult);
// The response is the parent image snapshot, so editResult.path still points to the original image.
// Find the pending edit version and poll its source_image_id until the job image completes.
const editVersion = editResult.versions.find(v => v.version_type === 'edited');
const finalImage = await pollImage(editVersion.source_image_id);
console.log('Completed edit image URL:', finalImage.path); Response Format
{
"id": "IMG_123",
"status": "pending",
"task": "edit",
"path": "https://media.bitstudio.ai/gen/original.jpg",
"versions": [
{
"id": "VERSION_789",
"version_type": "edited",
"source_image_id": "EDIT_456",
"status": "pending"
}
],
"credits_used": 1,
"created_timestamp": "2024-02-20T14:30:00Z"
} The edit operation returns the parent image, so the top-level path still points to the original image. Poll versions[n].source_image_id until that job image completes, then use the completed response's path or refetch the parent image and read the new version's path.
Tips for Best Results
- Clear instructions: Be specific about what changes you want (e.g., "change the sky to sunset" vs. "make it look different")
- Preserve context: The edit will try to maintain the original image's style and composition
- Multiple variations: Generate multiple versions to get the best result
- Version tracking: Each edit creates a new version, allowing you to maintain history
Transform still images into short video animations
POST /images/{id}/video Request Parameters
| Parameter | Type | Description | Required |
|---|---|---|---|
prompt | string | Description of the desired motion | Yes |
Example Request
{
"prompt": "gentle camera zoom, cinematic lighting"
} JavaScript Example
const imageToVideo = async (imageId, prompt) => {
const response = await fetch(`https://api.bitstudio.ai/images/${imageId}/video`, {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
prompt: prompt,
})
});
const result = await response.json();
return result;
};
// Call the function to create video from an image
const videoResult = await imageToVideo('IMG_123', 'gentle camera zoom in, soft wind in hair');
console.log('Video generation started:', videoResult.id);
// Poll for completion as in previous examples
const finalVideo = await pollForCompletion(videoResult.id);
console.log('Video is ready:', finalVideo.path); Response Format
{
"id": "VIDEO_123",
"status": "pending",
"task": "image-to-video",
"source_image_id": "IMG_123",
"estimated_completion": "2024-02-20T15:45:00Z",
"credits_used": 15
} Once completed, the response will include a video_path field with the URL to the generated video.
Tips for Best Results
- Image composition: Well-framed, clear subjects work best
- Processing time: Typically takes 10 minutes per video
Understanding API errors and how to handle them
Error Response Format
{
"error": "Error message",
"code": "ERROR_CODE",
"details": {}
} Common Error Codes
| Error Code | Description | HTTP Status |
|---|---|---|
insufficient_credits | Not enough credits to perform the operation | 402 |
no_active_subscription | No active subscription found | 402 |
upgrade_required | Feature requires a higher tier plan | 402 |
no_training_found | No training found for the specified asset | 404 |
unauthorized | Invalid API key or missing authentication | 401 |
model_not_found | Requested model not found | 404 |
invalid_aspect_ratio | Invalid aspect ratio specified | 400 |
invalid_resolution | Invalid resolution specified | 400 |
internal_server_error | Server error occurred | 500 |
bad_request | Invalid request parameters | 400 |
forbidden | Access to the resource is forbidden | 403 |
RATE_LIMITED | Too many requests (max 10 per second) | 429 |
Feature Restriction Errors
When attempting to use a feature that requires a higher plan tier, you'll
receive an upgrade_required error with additional context:
{
"error": "upgrade_required",
"feature": "image_to_video",
"current_plan": "Pro",
"required_plan": "Ultra"
} Best Practices for Error Handling
- Always check for error responses and handle them gracefully
- Implement exponential backoff for rate limiting errors
- Validate inputs client-side before sending requests
- Check credit balance before making credit-consuming operations
JavaScript Error Handling Example
const callApi = async (endpoint, method, data) => {
try {
const response = await fetch(`https://api.bitstudio.ai${endpoint}`, {
method: method,
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: data ? JSON.stringify(data) : undefined
});
const result = await response.json();
// Check if the response contains an error
if (response.status >= 400 || result.error) {
throw {
status: response.status,
code: result.code || 'UNKNOWN_ERROR',
message: result.error || 'Unknown error occurred',
details: result.details || {}
};
}
return result;
} catch (error) {
// Handle specific error codes
if (error.code === 'RATE_LIMITED') {
console.log('Rate limited. Retrying after a delay...');
// Implement exponential backoff here
await new Promise(resolve => setTimeout(resolve, 5000));
return callApi(endpoint, method, data);
}
if (error.code === 'INSUFFICIENT_CREDITS') {
console.error('Not enough credits to perform this operation');
// Redirect user to purchase more credits
}
// Log and rethrow the error
console.error('API Error:', error);
throw error;
}
}; Retrieve image details and check generation status
GET /images/{id} Response Format
{
"id": "IMG_123",
"status": "completed",
"task": "virtual-try-on",
"path": "https://media.bitstudio.ai/gen/image.jpg",
"versions": [
{
"id": "VERSION_123",
"version_type": "upscaled",
"path": "https://media.bitstudio.ai/gen/upscaled.jpg"
}
],
"credits_used": 2,
"created_timestamp": "2024-02-20T14:30:00Z",
"finish_timestamp": "2024-02-20T15:00:00Z"
} Polling for Completion
Most API operations that generate images are asynchronous. Use this endpoint to check the status of operations:
const pollForCompletion = async (imageId) => {
let complete = false;
while (!complete) {
const response = await fetch(`https://api.bitstudio.ai/images/${imageId}`, {
headers: { 'Authorization': 'Bearer YOUR_API_KEY' }
});
const imageData = await response.json();
if (imageData.status === 'completed') {
complete = true;
return imageData;
} else if (imageData.status === 'failed') {
throw new Error('Image processing failed');
}
console.log('Current status:', imageData.status);
// Wait 2 seconds before polling again
await new Promise(resolve => setTimeout(resolve, 2000));
}
}; Status Values
| Status | Description |
|---|---|
pending | Request received, waiting to be processed |
generating | Processing has begun |
completed | Processing is complete, result is ready |
failed | Processing failed, check error details |
Best Practices
- Use exponential backoff: Increase the wait time between polls if processing takes longer
- Check for errors: Always handle the "failed" status explicitly
- Timeout: Implement a reasonable timeout for your polling loop (e.g., 2-3 minutes)
Frequently Asked Questions
How do I authenticate my API requests?
Include your API key in the Authorization header: 'Authorization: Bearer YOUR_API_KEY'.
Are there rate limits for the API?
Yes, the API is limited to 10 requests per second. If you exceed this limit, you'll receive a RATE_LIMITED error code.
How are credits deducted when using the API?
Credits are deducted when the request is made. If the operation fails, credits are automatically refunded.
What image formats are supported for upload?
The API accepts JPEG, PNG, and WebP formats with a maximum file size of 10MB.
How do I check the status of a generated image?
Poll the GET /images/{id} endpoint until the status changes from 'pending' to 'completed'.
Ready to integrate our API?
Get started with our API to add powerful AI imaging capabilities to your application.