Image Uploads
Overview
The KOOB API provides a comprehensive attachment system for managing image uploads across various entities in the platform. Understanding how this system works is crucial to avoid accidentally losing existing images when updating entity attachments.
For detailed information about all endpoints, request/response schemas, and additional details, visit our complete API Reference.
Critical
When updating entity images, the API replaces the entire image collection. Any existing images not included in your request will be deleted. Always include all images you want to keep, not just the ones you're adding or updating.
How Image Management Works
The KOOB API uses a synchronization approach for image management, which means:
- Complete Replacement: Each API call replaces the entire image collection for an entity
- Automatic Cleanup: Images not included in the request are automatically removed
- Smart Operations: The system determines whether to create, update, or delete images based on the provided data
Image Retrieval
Accessing Uploaded Images
Once uploaded, images are accessible through the entity's attachments imageUrl field. The URL points to the image stored in our cloud storage.
{
"attachments": [
{
"id": "att-123",
"displayName": "Hotel Exterior.jpg",
"imageUrl": "https://storage.googleapis.com/bucket/attachments/Hotel/uuid.jpg",
"isMainPicture": true
}
]
}Image Upload Methods
On the entity creation (POST)
When creating new entities with images, you only need to provide the new images:
Example - Creating a hotel with images:
{
"attachments": [
{
"displayName": "Hotel Exterior.jpg",
"imageUrl": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQ...",
"kind": "primary"
},
{
"displayName": "Lobby View.jpg",
"imageUrl": "data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUgAAAB...",
"kind": "secondary"
}
],
}On the entity update (PUT/PATCH)
When updating existing entities, you must include all images you want to keep:
Incorrect Approach (Will Delete Existing Images):
{
"attachments": [
{
"displayName": "New Room Photo.jpg",
"imageUrl": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQ..."
}
]
}This will delete all existing images and keep only the new one.
Correct Approach (Preserves Existing Images):
{
"attachments": [
{
"id": "att-123",
"displayName": "Existing Hotel Exterior.jpg"
},
{
"id": "att-456",
"displayName": "Updated Lobby Name.jpg"
},
{
"displayName": "New Room Photo.jpg",
"imageUrl": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQ..."
}
]
}Sync Operations Explained
The API automatically determines the operation based on your request data:
1. Create New Images
Trigger: Attachments without an id field
{
"displayName": "New Image.jpg",
"imageUrl": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQ...",
"kind": "primary"
}2. Update Existing Images
Trigger: Attachments with an id field
{
"id": "existing-attachment-123",
"displayName": "Updated Name.jpg",
"kind": "secondary"
}Image Modification
You cannot change the actual image file, only metadata like display name and kind.
If you need to change the image, you must delete the old image and create a new one with the updated file.
3. Delete Images
Trigger: Existing images not included in the request
If entity has images with IDs: att-123, att-456, att-789, and you only send the following:
{
"attachments": [
{
"id": "att-123",
"displayName": "Keep This Image.jpg"
}
]
}Images att-456 and att-789 will be deleted.
Image Data Formats
Base64 Data URLs (New Uploads)
{
"imageUrl": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQ..."
}Base64 Format Required
The imageUrl must be a valid Base64 data URL. External URLs are not processed and will be skipped.
Existing Images (Updates Only)
{
"id": "att-123"
// No imageUrl needed for existing images
}Supported Image Formats
- JPEG (.jpg, .jpeg)
- PNG (.png)
- GIF (.gif)
- WebP (.webp)
Image Categories
The API supports different image kinds to categorize images based on their usage:
primary: Main entity imagesecondary: Secondary entity image(s)- Custom kinds: Based on specific entity requirements
Custom Kinds
Unless stated otherwise, only primary and secondary kinds are supported for most entities.
These can be specified in the kind field of the attachment object.
Best Practices
1. Always Fetch Current Images Before Updates
# Get current entity images
GET /api/v1/hotels/{hotelId}
# Include all existing images in your update
PATCH /api/v1/hotels/{hotelId}2. Use Meaningful Display Names
{
"displayName": "Hotel Exterior - Main Entrance.jpg", // Good
"displayName": "IMG_001.jpg" // Avoid
}3. Optimize Images Before Upload
- Compress images to reduce upload time and storage costs
- Use appropriate resolution for the intended use case
- Consider using WebP format for better compression
4. Handle Large Image Collections
For entities with many images, consider:
- Paginating image updates
- Processing images in batches
- Implementing client-side preview before upload
Common Pitfalls
❌ Accidentally Deleting All Images
{
"name": "Updated Hotel Name",
"attachments": [] // This deletes all existing images!
}For most entities, the attachments or pictures field is optional, but if you send an empty array, it will delete all existing images.
If you don't need to update images, simply omit the attachments field entirely.
❌ Forgetting Existing Images
{
"attachments": [
{
"displayName": "Only New Image.jpg",
"imageUrl": "data:image/jpeg;base64,..."
}
// Missing existing images - they will be deleted!
]
}✅ Correct Full Update
{
"attachments": [
{
"id": "att-123",
"displayName": "Existing Image 1.jpg"
},
{
"id": "att-456",
"displayName": "Existing Image 2.jpg"
},
{
"displayName": "New Image.jpg",
"imageUrl": "data:image/jpeg;base64,..."
}
]
}