Skip to contentSkip to Content
API ReferenceProperty Images

Property Images API

Upload, manage, and reorder property listing images. Images are stored on Cloudflare R2 and served via Image Transformations.

Upload Flow

Image upload is a two-step process:

  1. Presign — get a presigned upload URL from the API
  2. Upload — PUT the file directly to the presigned URL (client → R2, no proxy)
  3. Confirm — tell the API the upload succeeded, creating the database record

List Images

GET /api/v1/properties/:id/images

Returns all images for a property, ordered by display order.

Response:

{ "data": [ { "id": "550e8400-e29b-41d4-a716-446655440000", "url": "https://images.rentalot.ai/images/user123/prop456/img789.jpg", "altText": "Living room with hardwood floors", "order": 0 } ] }

Get Presigned Upload URL

POST /api/v1/properties/:id/images/presign

Request Body:

{ "fileName": "living-room.jpg", "contentType": "image/jpeg", "sizeBytes": 2048576 }
FieldTypeDescription
fileNamestringOriginal filename (used for extension extraction)
contentTypestringimage/jpeg, image/png, image/webp, or image/heic
sizeBytesnumberFile size in bytes (max 10MB)

Response:

{ "uploadUrl": "https://r2.example.com/presigned-put-url...", "r2Key": "images/user123/prop456/abc-def.jpg", "maxImages": 20 }

Upload the file via PUT to the uploadUrl, then call the confirm endpoint.

Confirm Upload

POST /api/v1/properties/:id/images/confirm

Creates the database record after a successful upload. Supports Idempotency-Key header.

Request Body:

{ "r2Key": "images/user123/prop456/abc-def.jpg", "contentType": "image/jpeg", "sizeBytes": 2048576, "altText": "Living room with hardwood floors" }

Returns the created image object.

Delete Images

DELETE /api/v1/properties/:id/images

Delete one or more images by ID. Removes from both database and R2 storage.

Request Body:

{ "imageIds": ["550e8400-e29b-41d4-a716-446655440000"] }

Returns { "deleted": 1 }.

Reorder Images

PATCH /api/v1/properties/:id/images/reorder

Set the display order. The first ID in the array gets order 0, second gets 1, etc.

Request Body:

{ "imageIds": [ "img-id-for-order-0", "img-id-for-order-1", "img-id-for-order-2" ] }

Returns { "ok": true }.

Notes

  • Tier-limited — the number of images per property depends on your plan (check maxImages in the presign response).
  • Allowed types: JPEG, PNG, WebP, HEIC. Max 10MB per image.
  • Images are served via Cloudflare Image Transformations for automatic resizing and format optimization.