Skip to content

Vision API Reference

This document provides complete API reference for vision analysis and image search capabilities.

Search property photos using natural language descriptions.

GET /api/admin/search/images?q={query}&limit={limit}&offset={offset}
Parameter Type Required Default Description
q string Yes — Search query (e.g., “granite countertops”)
limit integer No 20 Results per page (max: 100)
offset integer No 0 Pagination offset
property_id string No — Limit to specific property
{
"results": [
{
"image_id": "img_abc123",
"property_id": "prop_xyz789",
"url": "https://.../photos/kitchen-1.jpg",
"description": "Modern kitchen with white cabinets, granite countertops, and stainless steel appliances",
"room_type": "kitchen",
"score": 0.92,
"features": [
"granite_countertops",
"white_cabinets",
"stainless_appliances"
]
}
],
"total": 45,
"limit": 20,
"offset": 0
}
Code Meaning
200 Success
400 Invalid query parameters
429 Rate limit exceeded

Find photos that look similar using SigLIP embeddings.

GET /api/admin/search/images-visual?q={query}&limit={limit}
Parameter Type Required Default Description
q string Yes — Natural language description of desired visual
limit integer No 20 Results per page (max: 100)
min_score float No 0.5 Minimum similarity score (0.0-1.0)
{
"results": [
{
"image_id": "img_abc123",
"property_id": "prop_xyz789",
"url": "https://.../photos/kitchen-1.jpg",
"similarity_score": 0.89,
"description": "Modern white kitchen with island",
"room_type": "kitchen"
}
],
"total": 32,
"query_embedding": [0.123, 0.456, ...],
"execution_time_ms": 45
}

Combine text and image search for comprehensive results.

POST /api/search/multimodal
Content-Type: application/json
{
"query": "open concept living room with vaulted ceilings",
"include_images": true,
"limit": 20
}
Field Type Required Description
query string Yes Search query
include_images boolean No Include image-level results (default: false)
limit integer No Results per page (default: 20, max: 100)
offset integer No Pagination offset
{
"properties": [
{
"property_id": "prop_xyz789",
"address": "123 Main St",
"city": "Twin Falls",
"text_similarity": 0.85,
"image_similarity": 0.78,
"combined_score": 0.82,
"matching_images": [
{
"image_id": "img_abc123",
"url": "https://.../photos/living-1.jpg",
"description": "Spacious living room with vaulted ceiling",
"score": 0.91
}
]
}
],
"total": 18,
"execution_time_ms": 120
}
combined_score = (text_similarity × 0.6) + (image_similarity × 0.4)

Text is weighted higher because it includes structured listing data.


Retrieve statistics about the vision analysis index.

GET /api/admin/embeddings/images/stats
{
"total_properties": 1250,
"properties_with_images": 1180,
"total_images": 7500,
"description_embeddings": 6800,
"visual_embeddings": 5200,
"avg_images_per_property": 6.4,
"unindexed_images": 700,
"index_coverage": 0.91,
"last_indexed_at": "2024-01-15T10:30:00Z",
"storage_size_mb": 245.6
}
Field Description
total_properties Total properties in database
properties_with_images Properties with at least one photo
total_images Total photo count
description_embeddings Photos with text embeddings
visual_embeddings Photos with visual embeddings
unindexed_images Photos pending analysis
index_coverage Percentage of photos indexed (0.0-1.0)

Process unindexed images or re-process existing images.

POST /api/admin/embeddings/reindex/images?limit={limit}&force={force}
Content-Type: application/json
Parameter Type Required Default Description
limit integer No 100 Max images to process
force boolean No false Re-process already indexed images
{
"property_ids": ["prop_123", "prop_456"],
"room_types": ["kitchen", "bathroom"],
"min_quality_score": 0.8
}
{
"started": true,
"job_id": "job_abc123",
"images_queued": 150,
"estimated_duration_minutes": 5,
"status_url": "/api/admin/embeddings/jobs/job_abc123"
}
Code Meaning
202 Job queued successfully
400 Invalid parameters
429 Another indexing job already running
503 Ollama service unavailable

Monitor progress of an indexing job.

GET /api/admin/embeddings/jobs/{job_id}
{
"job_id": "job_abc123",
"status": "running",
"progress": {
"processed": 75,
"total": 150,
"percentage": 50,
"current_image": "img_xyz789"
},
"started_at": "2024-01-15T10:30:00Z",
"estimated_completion": "2024-01-15T10:35:00Z",
"errors": [
{
"image_id": "img_bad123",
"error": "Image file corrupted"
}
]
}
Status Description
queued Waiting to start
running Currently processing
completed Finished successfully
failed Encountered critical error
partial Completed with some errors

Remove embeddings for specific images.

DELETE /api/admin/embeddings/images
Content-Type: application/json
{
"image_ids": ["img_abc123", "img_xyz789"]
}
Field Type Required Description
image_ids array Yes Image IDs to delete embeddings for
delete_descriptions boolean No Also delete text descriptions (default: false)
{
"deleted": 2,
"failed": 0,
"errors": []
}

Retrieve all photos categorized as a specific room type.

GET /api/admin/images/by-room/{room_type}?limit={limit}&offset={offset}
Parameter Description Values
room_type Room category kitchen, bedroom, bathroom, living_room, exterior, garage, other
{
"room_type": "kitchen",
"results": [
{
"image_id": "img_abc123",
"property_id": "prop_xyz789",
"url": "https://.../photos/kitchen-1.jpg",
"description": "Modern kitchen with granite counters",
"confidence": 0.95,
"features": ["granite_countertops", "island", "stainless_appliances"]
}
],
"total": 320
}

Manually correct an auto-detected room type.

PATCH /api/admin/images/{image_id}/room-type
Content-Type: application/json
{
"room_type": "bathroom",
"confidence": 1.0
}
{
"image_id": "img_abc123",
"room_type": "bathroom",
"previous_room_type": "kitchen",
"confidence": 1.0,
"manually_set": true
}

Retrieve all features detected in an image.

GET /api/admin/images/{image_id}/features
{
"image_id": "img_abc123",
"features": [
{
"key": "granite_countertops",
"label": "Granite Countertops",
"confidence": 0.89,
"category": "material"
},
{
"key": "island",
"label": "Kitchen Island",
"confidence": 0.92,
"category": "feature"
},
{
"key": "stainless_appliances",
"label": "Stainless Steel Appliances",
"confidence": 0.85,
"category": "appliance"
}
]
}

Manually tag a feature that wasn’t auto-detected.

POST /api/admin/images/{image_id}/features
Content-Type: application/json
{
"key": "wine_fridge",
"label": "Wine Refrigerator",
"category": "appliance"
}
{
"feature_id": "feat_abc123",
"key": "wine_fridge",
"label": "Wine Refrigerator",
"confidence": 1.0,
"manually_added": true
}

Analyze all photos for a specific property.

POST /api/admin/properties/{property_id}/analyze-images
{
"property_id": "prop_xyz789",
"images_analyzed": 18,
"features_detected": 127,
"avg_confidence": 0.84,
"execution_time_ms": 35000
}

Export all image descriptions for a property.

GET /api/admin/properties/{property_id}/image-descriptions
{
"property_id": "prop_xyz789",
"address": "123 Main St",
"images": [
{
"image_id": "img_abc123",
"order": 1,
"room_type": "kitchen",
"description": "Modern kitchen with white cabinets and granite countertops",
"features": ["granite_countertops", "white_cabinets"]
}
],
"export_format": "json"
}

Add ?format=csv or ?format=txt for alternate formats.


Endpoint Limit Window Scope
/api/admin/search/images* 100 requests 1 minute Per API key
/api/admin/embeddings/reindex* 5 requests 1 hour Global
/api/search/multimodal 30 requests 1 minute Per session

Rate limit headers:

X-RateLimit-Limit: 100
X-RateLimit-Remaining: 87
X-RateLimit-Reset: 1705329600

Vision analysis triggers webhook events for integration:

Fired when an image analysis completes.

{
"event": "image.analyzed",
"timestamp": "2024-01-15T10:30:00Z",
"data": {
"image_id": "img_abc123",
"property_id": "prop_xyz789",
"room_type": "kitchen",
"features_count": 8,
"confidence_avg": 0.87
}
}

Fired when a batch indexing job finishes.

{
"event": "indexing.completed",
"timestamp": "2024-01-15T10:35:00Z",
"data": {
"job_id": "job_abc123",
"images_processed": 150,
"success_count": 148,
"error_count": 2,
"duration_seconds": 300
}
}

Code Error Meaning
VISION_001 ollama_unavailable Ollama service not responding
VISION_002 model_not_loaded Required vision model not available
VISION_003 image_corrupt Image file is corrupted or invalid
VISION_004 image_too_large Image exceeds max size (10MB)
VISION_005 embedding_failed Failed to generate embedding
VISION_006 description_failed Failed to generate description
VISION_007 index_full Vector index at capacity