Images API
Complete reference for the Images endpoint. Learn how to list, upload, and manage images programmatically.
List Images
Retrieve a list of all images across all your collections.
GET https://api.optimage.com/api/v1/images
Response (200 OK)
[
{
"id": "img_1234567890",
"slug": "beach-sunset",
"collectionId": "col_abc123",
"checksum": "a1b2c3d4...",
"createdAt": "2025-12-04T10:30:00Z",
"baseUrl": "https://cdn.optimage.com"
},
{
"id": "img_0987654321",
"slug": "mountain-view",
"collectionId": "col_xyz789",
"checksum": "e5f6g7h8...",
"createdAt": "2025-12-03T15:20:00Z",
"baseUrl": "https://cdn.optimage.com"
}
]Example (JavaScript)
const response = await fetch('https://api.optimage.com/api/v1/images', {
credentials: 'include'
});
const images = await response.json();
console.log(`Total images: ${images.length}`);Upload Image
Upload a new image to a specific collection. The image will be automatically processed and optimized into multiple sizes.
POST https://api.optimage.com/api/v1/images
Request Format
Use multipart/form-data format with the following fields:
- •file (required): The image file (JPEG, PNG, WebP, or GIF)
- •checksum (required): SHA-256 hash of the file for integrity verification
- •collection (required): Collection ID where the image will be stored
- •slug (optional): Custom slug for the image URL (auto-generated if not provided)
Response (201 Created)
{
"id": "img_1234567890",
"slug": "beach-sunset",
"collectionId": "col_abc123",
"checksum": "a1b2c3d4e5f6g7h8...",
"status": "processing",
"createdAt": "2025-12-04T10:30:00Z",
"baseUrl": "https://cdn.optimage.com"
}Error Responses
400 Bad Request - Invalid file format or missing required fields
401 Unauthorized - Not authenticated
403 Forbidden - Collection does not belong to user
429 Too Many Requests - Monthly quota exceeded
SHA-256 Checksum Calculation
Calculate the checksum before uploading:
async function calculateChecksum(file) {
const arrayBuffer = await file.arrayBuffer();
const hashBuffer = await crypto.subtle.digest('SHA-256', arrayBuffer);
const hashArray = Array.from(new Uint8Array(hashBuffer));
const hashHex = hashArray
.map(b => b.toString(16).padStart(2, '0'))
.join('');
return hashHex;
}Complete Upload Example (JavaScript)
async function uploadImage(file, collectionId, customSlug = null) {
// Calculate checksum
const checksum = await calculateChecksum(file);
// Create form data
const formData = new FormData();
formData.append('file', file);
formData.append('checksum', checksum);
formData.append('collection', collectionId);
if (customSlug) {
formData.append('slug', customSlug);
}
// Upload
const response = await fetch('https://api.optimage.com/api/v1/images', {
method: 'POST',
credentials: 'include',
body: formData
});
if (!response.ok) {
const error = await response.json();
throw new Error(error.message || 'Upload failed');
}
const image = await response.json();
console.log('Image uploaded:', image.slug);
return image;
}
// Usage
const fileInput = document.querySelector('input[type="file"]');
const file = fileInput.files[0];
const collectionId = 'col_abc123';
try {
const image = await uploadImage(file, collectionId);
console.log('Upload successful:', image);
} catch (error) {
console.error('Upload failed:', error.message);
}Tip: The upload endpoint returns immediately with status "processing". The image becomes available at its CDN URLs within 5-15 seconds after processing completes.
Image Processing
After upload, OPTIMAGE automatically processes your image through a task pipeline:
- Validation: Verify file format and checksum
- WebP Conversion: Convert original to WebP format (size 0)
- Resize: Generate 11 responsive sizes (320px to 1280px wide)
- Optimization: Compress each size to 80% quality
- CDN Upload: Distribute to Cloudflare R2 CDN
- URL Activation: Images become available at their CDN URLs
Total processing time is typically 5-15 seconds depending on the original image size.
Available Sizes
Each image is automatically processed into these sizes:
| Size Code | Width | Description |
|---|---|---|
| 0 | Original | WebP conversion of original (maintains aspect ratio) |
| 320 | 320px | Mobile portrait, small thumbnails |
| 384 | 384px | Mobile landscape |
| 448 | 448px | Small tablets |
| 512 | 512px | Tablets portrait |
| 576 | 576px | Large mobile, small tablet landscape |
| 672 | 672px | Tablet landscape |
| 768 | 768px | Small desktop, large tablets |
| 896 | 896px | Desktop |
| 1024 | 1024px | Desktop, small retina |
| 1152 | 1152px | Large desktop |
| 1280 | 1280px | Large desktop, retina displays |
Image URLs
All images are served from the OPTIMAGE CDN with the following URL structure:
https://cdn.optimage.com/{collectionId}/{size}/{slug}.webpURL Examples
// Original WebP conversion
https://cdn.optimage.com/col_abc123/0/beach-sunset.webp
// 768px size (default for src)
https://cdn.optimage.com/col_abc123/768/beach-sunset.webp
// 1280px size (largest)
https://cdn.optimage.com/col_abc123/1280/beach-sunset.webpBuilding srcset in Code
function buildSrcset(collectionId, slug) {
const baseUrl = 'https://cdn.optimage.com';
const sizes = [320, 384, 448, 512, 576, 672, 768, 896, 1024, 1152, 1280];
const srcset = sizes
.map(size => `${baseUrl}/${collectionId}/${size}/${slug}.webp ${size}w`)
.join(', ');
const src = `${baseUrl}/${collectionId}/768/${slug}.webp`;
return { src, srcset };
}
// Usage
const { src, srcset } = buildSrcset('col_abc123', 'beach-sunset');
console.log('src:', src);
console.log('srcset:', srcset);Rate Limits
Upload limits are based on your account's monthly quota:
- •Free Plan: 500 images per month
- •Pro Plan: 5,000 images per month
- •Business Plan: 25,000 images per month
Quotas reset on the first day of each month. Once you reach your quota limit, you'll receive a 429 Too Many Requests error until your quota resets.
Tip: Check your remaining quota before uploading by calling the GET /api/v1/config endpoint.