{"openapi":"3.1.0","info":{"title":"Akator Image Matching API","description":"The Akator Image Matching API allows users to manage image collections, search for similar images, and compare two images based on their visual characteristics. It supports uploading images, searching within a collection for matches, and returning scores indicating similarity. The API also provides endpoints for managing image collections, including listing, adding, and deleting images.","contact":{"name":"Akator Support","email":"support@akator.de"},"license":{"name":"Copyright (c) 2024-2026 Akator GmbH","url":"https://akator.de/"},"version":"1.3.0"},"paths":{"/collections/{collection_id}/match":{"post":{"tags":["Match"],"summary":"Match Image in Collection","description":"Find similar images in a collection using advanced image matching techniques.\n\n**Response Metrics:**\n- `match_percent`: Feature match quality (0-100%)\n- `ssim_score`: Structural similarity (0-1, higher = more similar)\n- `wasserstein_distance`: Color distribution distance (lower = more similar)\n- `iou_percent`: Spatial overlap of matched regions (0-100%)\n- `query_match_rect` / `target_match_rect`: Bounding boxes of matched areas (normalized 0-1)","operationId":"match_image_collections__collection_id__match_post","parameters":[{"name":"collection_id","in":"path","required":true,"schema":{"type":"integer","description":"ID of the collection to search in.","title":"Collection Id"},"description":"ID of the collection to search in."},{"name":"min_ssim_score","in":"query","required":false,"schema":{"type":"number","maximum":1,"minimum":0,"description":"Minimum SSIM score threshold (0-1). Only matches with SSIM >= this value are returned. Higher values mean stricter matching.","default":0.5,"title":"Min Ssim Score"},"description":"Minimum SSIM score threshold (0-1). Only matches with SSIM >= this value are returned. Higher values mean stricter matching."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Maximum number of results to return (1-100).","default":10,"title":"Limit"},"description":"Maximum number of results to return (1-100)."}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_match_image_collections__collection_id__match_post"}}}},"responses":{"200":{"description":"Matching completed successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchResponse"}}}},"400":{"description":"Invalid request parameters"},"404":{"description":"Collection not found or not accessible"},"422":{"description":"Image too small (minimum 64x64 pixels) or invalid"},"500":{"description":"Internal server error during processing"}}}},"/compare":{"post":{"tags":["Compare"],"summary":"Compare Two Images","description":"Compare two images and calculate similarity metrics.\n\n**Input Options:**\n- Provide images as file uploads OR as URLs (not both for the same image)\n- Exactly one reference and one target image must be provided\n\n**Response Metrics:**\n- `match_percent`: Feature match quality (0-100%)\n- `ssim_score`: Structural similarity (0-1, higher = more similar)\n- `wasserstein_distance`: Color distribution distance (lower = more similar)\n- `iou_percent`: Spatial overlap of matched regions (0-100%)\n- `query_match_rect` / `target_match_rect`: Bounding boxes of matched areas (normalized 0-1)\n\n**Supported Formats:** JPEG, PNG, WebP, GIF, AVIF, HEIC, JPEG XL, JPEG 2000, TIFF, BMP, ICO, TGA, DDS\n\n**Size Limits:**\n- Maximum image size: 25 MB\n- Minimum image dimensions: 64x64 pixels","operationId":"compare_images_compare_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_compare_images_compare_post"}}}},"responses":{"200":{"description":"Comparison completed successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageComparisonResponse"}}}},"400":{"description":"Invalid input: missing images, invalid URL, or non-image content type"},"422":{"description":"Image too small (minimum 64x64 pixels) or invalid format"},"500":{"description":"Internal server error during comparison"}}}},"/collections":{"get":{"tags":["Collections"],"summary":"List Collections","description":"Retrieves all collections belonging to the authenticated client.","operationId":"list_collections_collections_get","parameters":[],"responses":{"200":{"description":"Collections retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListCollectionsResponse"}}}},"500":{"description":"Database error while listing collections"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Collections"],"summary":"Create a New Collection","description":"Creates a new collection for the authenticated client. Collection names must be unique per client.","operationId":"create_collection_collections_post","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCollectionRequest"}}}},"responses":{"201":{"description":"Collection created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCollectionResponse"}}}},"409":{"description":"Collection with this name already exists"},"422":{"description":"Invalid collection name (empty or too long)"},"500":{"description":"Database error while creating collection"}}}},"/collections/{collection_id}":{"get":{"tags":["Collections"],"summary":"Get Collection Details","description":"Retrieve detailed information for a specific collection, including metadata such as number of images and last image added timestamp.","operationId":"get_collection_with_metadata_collections__collection_id__get","parameters":[{"name":"collection_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"description":"ID of the collection to retrieve.","title":"Collection Id"},"description":"ID of the collection to retrieve."}],"responses":{"200":{"description":"Collection details retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetCollectionResponse"}}}},"404":{"description":"Collection not found or not accessible"},"500":{"description":"Database error while retrieving collection"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Collections"],"summary":"Delete a Collection","description":"Soft deletes a specified collection and all its images. The collection data is marked as deleted but not permanently removed.","operationId":"delete_collection_collections__collection_id__delete","parameters":[{"name":"collection_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"description":"ID of the collection to delete.","title":"Collection Id"},"description":"ID of the collection to delete."}],"responses":{"200":{"description":"Collection deleted successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteCollectionResponse"}}}},"404":{"description":"Collection not found or not accessible"},"500":{"description":"Database error while deleting collection"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/collections/{collection_id}/name":{"put":{"tags":["Collections"],"summary":"Update Collection Name","description":"Update the name of a specific collection. The new name must be unique among the client's collections.","operationId":"update_collection_name_collections__collection_id__name_put","parameters":[{"name":"collection_id","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"description":"ID of the collection to update.","title":"Collection Id"},"description":"ID of the collection to update."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateCollectionNameRequest","description":"The new name for the collection."}}}},"responses":{"200":{"description":"Collection name updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateCollectionNameResponse"}}}},"404":{"description":"Collection not found or not accessible"},"409":{"description":"Collection with this name already exists"},"422":{"description":"Invalid collection name (empty or too long)"},"500":{"description":"Database error while updating collection"}}}},"/collections/{collection_id}/images":{"get":{"tags":["Images"],"summary":"List Images in Collection","description":"Lists images in a collection with pagination support. Returns basic image info including ID, filename, and timestamps.","operationId":"list_images_collections__collection_id__images_get","parameters":[{"name":"collection_id","in":"path","required":true,"schema":{"type":"integer","description":"ID of the collection","title":"Collection Id"},"description":"ID of the collection"},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":100,"title":"Limit"}}],"responses":{"200":{"description":"Images listed successfully","content":{"application/json":{"schema":{}}}},"404":{"description":"Collection not found or not accessible"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Images"],"summary":"Upload Image to Collection","description":"Upload an image to a collection via file upload or URL.\n\n**Input Options:**\n- Provide the image as a file upload OR as a URL (not both)\n- Optionally attach a custom JSON payload to the image\n\n**Processing:**\n- Images are converted to WebP format for storage\n- SIFT features are extracted and stored for matching\n- Perceptual hash (pHash) is computed for fast similarity search\n\n**Supported Formats:** JPEG, PNG, WebP, GIF, AVIF, HEIC, JPEG XL, JPEG 2000, TIFF, BMP, ICO, TGA, DDS\n\n**Size Limits:**\n- Maximum file size: 25 MB\n- Minimum dimensions: 64x64 pixels","operationId":"add_image_collections__collection_id__images_post","parameters":[{"name":"collection_id","in":"path","required":true,"schema":{"type":"integer","description":"ID of the collection to add the image to","title":"Collection Id"},"description":"ID of the collection to add the image to"}],"requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_add_image_collections__collection_id__images_post"}}}},"responses":{"200":{"description":"Image uploaded successfully, returns image UUID","content":{"application/json":{"schema":{}}}},"404":{"description":"Collection not found or not accessible"},"400":{"description":"Invalid input: both/neither image sources, invalid JSON payload, or failed URL fetch"},"413":{"description":"Image file too large (max 25 MB)"},"422":{"description":"Image too small (min 64x64) or invalid format"},"500":{"description":"Server error during image processing or S3 upload"}}}},"/collections/{collection_id}/images/{image_id}":{"get":{"tags":["Images"],"summary":"Get Image Info","description":"Retrieve basic information about a specific image including filename, SHA256 hash, and timestamps.","operationId":"get_image_route_collections__collection_id__images__image_id__get","parameters":[{"name":"image_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Image Id"}},{"name":"collection_id","in":"path","required":true,"schema":{"type":"integer","description":"ID of the collection","title":"Collection Id"},"description":"ID of the collection"}],"responses":{"200":{"description":"Image info retrieved successfully","content":{"application/json":{"schema":{}}}},"404":{"description":"Image or collection not found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Images"],"summary":"Delete Image","description":"Soft delete an image from the collection. The DB row is flagged ``is_deleted=True`` and stamped with ``deleted_at``; the S3 object and SIFT cache entry are retained until the purge job runs past the retention window.","operationId":"delete_image_route_collections__collection_id__images__image_id__delete","parameters":[{"name":"image_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Image Id"}},{"name":"collection_id","in":"path","required":true,"schema":{"type":"integer","description":"ID of the collection","title":"Collection Id"},"description":"ID of the collection"}],"responses":{"200":{"description":"Image deleted successfully","content":{"application/json":{"schema":{}}}},"404":{"description":"Image or collection not found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/collections/{collection_id}/images/{image_id}/metadata":{"get":{"tags":["Images"],"summary":"Get Image Metadata","description":"Retrieve detailed metadata including dimensions, file sizes, perceptual hash, creation date, and storage information.","operationId":"get_image_metadata_collections__collection_id__images__image_id__metadata_get","parameters":[{"name":"image_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Image Id"}},{"name":"collection_id","in":"path","required":true,"schema":{"type":"integer","description":"ID of the collection","title":"Collection Id"},"description":"ID of the collection"}],"responses":{"200":{"description":"Metadata retrieved successfully","content":{"application/json":{"schema":{}}}},"404":{"description":"Image or collection not found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/collections/{collection_id}/images/{image_id}/payload":{"get":{"tags":["Images"],"summary":"Get Image Payload","description":"Retrieve the custom JSON payload attached to an image during upload.","operationId":"get_image_payload_collections__collection_id__images__image_id__payload_get","parameters":[{"name":"image_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Image Id"}},{"name":"collection_id","in":"path","required":true,"schema":{"type":"integer","description":"ID of the collection","title":"Collection Id"},"description":"ID of the collection"}],"responses":{"200":{"description":"Payload retrieved successfully","content":{"application/json":{"schema":{}}}},"404":{"description":"Image or collection not found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/collections/{collection_id}/images/{image_id}/file":{"get":{"tags":["Images"],"summary":"Download Image File","description":"Stream the image file in WebP format. All uploaded images are converted to WebP for storage efficiency.","operationId":"get_image_file_collections__collection_id__images__image_id__file_get","parameters":[{"name":"image_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Image Id"}},{"name":"collection_id","in":"path","required":true,"schema":{"type":"integer","description":"ID of the collection","title":"Collection Id"},"description":"ID of the collection"}],"responses":{"200":{"description":"Image file streamed successfully","content":{"application/json":{"schema":{}},"image/webp":{}}},"404":{"description":"Image or collection not found"},"500":{"description":"Error streaming from S3 storage"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/version":{"get":{"summary":"API Version","description":"Retrieve the current version of the Akator Image Matching API.","operationId":"get_version_version_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"type":"string"},"type":"object","title":"Response Get Version Version Get"}}}}}}},"/":{"get":{"summary":"API Overview","description":"Retrieve basic information about the Akator Image Matching API, including version and status.","operationId":"api_overview__get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"anyOf":[{"type":"string"},{"type":"boolean"},{"items":{"type":"string"},"type":"array"}]},"type":"object","title":"Response Api Overview  Get"}}}}}}}},"components":{"schemas":{"Body_add_image_collections__collection_id__images_post":{"properties":{"image":{"anyOf":[{"type":"string","contentMediaType":"application/octet-stream"},{"type":"null"}],"title":"Image","description":"Image file to upload. Provide either this OR url, not both. Supported: JPEG, PNG, WebP, GIF, AVIF, HEIC, JPEG XL, JPEG 2000, TIFF, BMP, ICO, TGA, DDS. Max: 25 MB."},"url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Url","description":"URL to fetch image from. Provide either this OR image file, not both. Must return an image content type."},"payload":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Payload","description":"Optional custom metadata as JSON string. Can be retrieved later via the /payload endpoint."}},"type":"object","title":"Body_add_image_collections__collection_id__images_post"},"Body_compare_images_compare_post":{"properties":{"reference_image":{"anyOf":[{"type":"string","contentMediaType":"application/octet-stream"},{"type":"null"}],"title":"Reference Image","description":"Reference image file. Provide either this OR reference_url, not both. Supported formats: JPEG, PNG, WebP, GIF, AVIF, HEIC, JPEG XL, JPEG 2000, TIFF, BMP, ICO, TGA, DDS. Max size: 25 MB."},"reference_url":{"anyOf":[{"type":"string","maxLength":2083,"minLength":1,"format":"uri"},{"type":"null"}],"title":"Reference Url","description":"URL to fetch reference image from. Provide either this OR reference_image, not both. Must return an image content type."},"target_image":{"anyOf":[{"type":"string","contentMediaType":"application/octet-stream"},{"type":"null"}],"title":"Target Image","description":"Target image file to compare against reference. Provide either this OR target_url, not both. Supported formats: JPEG, PNG, WebP, GIF, AVIF, HEIC, JPEG XL, JPEG 2000, TIFF, BMP, ICO, TGA, DDS. Max size: 25 MB."},"target_url":{"anyOf":[{"type":"string","maxLength":2083,"minLength":1,"format":"uri"},{"type":"null"}],"title":"Target Url","description":"URL to fetch target image from. Provide either this OR target_image, not both. Must return an image content type."}},"type":"object","title":"Body_compare_images_compare_post"},"Body_match_image_collections__collection_id__match_post":{"properties":{"image":{"type":"string","contentMediaType":"application/octet-stream","title":"Image","description":"Query image file to match against the collection. Supported formats: JPEG, PNG, WebP, GIF, AVIF, HEIC, TIFF, BMP."}},"type":"object","required":["image"],"title":"Body_match_image_collections__collection_id__match_post"},"BoundingBox":{"properties":{"left":{"type":"number","title":"Left"},"right":{"type":"number","title":"Right"},"top":{"type":"number","title":"Top"},"bottom":{"type":"number","title":"Bottom"}},"type":"object","required":["left","right","top","bottom"],"title":"BoundingBox"},"CollectionItem":{"properties":{"id":{"type":"integer","title":"Id","description":"Identifier of the collection"},"name":{"type":"string","maxLength":100,"minLength":1,"title":"Name","description":"Name of the collection item"}},"type":"object","required":["id","name"],"title":"CollectionItem","description":"Model representing a collection item with metadata.","examples":[{"id":1,"name":"Collection Item 1"}]},"CollectionItemWithMetadata":{"properties":{"id":{"type":"integer","title":"Id","description":"Identifier of the collection"},"name":{"type":"string","maxLength":100,"minLength":1,"title":"Name","description":"Name of the collection item"},"created_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Created At","description":"Timestamp when the item was created"},"updated_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Updated At","description":"Timestamp when the item was last updated"},"number_of_images":{"type":"integer","title":"Number Of Images","description":"Number of images in the collection"},"last_image_added_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Image Added At","description":"Timestamp of the last image added"}},"type":"object","required":["id","name","created_at","number_of_images"],"title":"CollectionItemWithMetadata","description":"Model representing a collection item with metadata.","examples":[{"created_at":"2021-09-01T12:00:00Z","id":1,"last_image_added_at":"2021-09-02T15:00:00Z","name":"Collection Item 1","number_of_images":5,"updated_at":"2021-09-01T12:00:00Z"}]},"ComparisonMetrics":{"properties":{"match_percent":{"type":"number","maximum":100.0,"minimum":0.0,"title":"Match Percent","description":"Percentage of SIFT keypoints that matched (0-100%). Higher values indicate more feature overlap between images."},"ssim_score":{"type":"number","maximum":1.0,"minimum":0.0,"title":"Ssim Score","description":"Structural Similarity Index (0-1). 1.0 = identical images, values > 0.8 typically indicate high similarity. Measures luminance, contrast, and structure similarity."},"wasserstein_distance":{"type":"number","minimum":0.0,"title":"Wasserstein Distance","description":"Earth Mover's Distance between color histograms. Lower values indicate more similar color distributions. Typical range: 0-50 for similar images, higher for dissimilar."},"iou_percent":{"type":"number","maximum":100.0,"minimum":0.0,"title":"Iou Percent","description":"Intersection over Union of matched regions (0-100%). Measures spatial overlap between reference and target match areas."},"query_match_rect":{"$ref":"#/components/schemas/BoundingBox","description":"Normalized bounding box (0-1) of the matched area in the reference image."},"target_match_rect":{"$ref":"#/components/schemas/BoundingBox","description":"Normalized bounding box (0-1) of the matched area in the target image."},"mirrored":{"type":"boolean","title":"Mirrored","description":"True if the best match was found against a horizontally mirrored copy of the target image; all metrics then refer to that mirrored orientation.","default":false}},"type":"object","required":["match_percent","ssim_score","wasserstein_distance","iou_percent","query_match_rect","target_match_rect"],"title":"ComparisonMetrics","description":"Similarity metrics from comparing two images.","examples":[{"iou_percent":71.3,"match_percent":82.5,"query_match_rect":{"bottom":0.9,"left":0.05,"right":0.95,"top":0.1},"ssim_score":0.95,"target_match_rect":{"bottom":0.88,"left":0.08,"right":0.92,"top":0.12},"wasserstein_distance":8.7}]},"CreateCollectionRequest":{"properties":{"name":{"type":"string","maxLength":100,"minLength":1,"pattern":"^[A-Za-z0-9 _-]+$","title":"Name","description":"Name of the new collection"}},"type":"object","required":["name"],"title":"CreateCollectionRequest","description":"Request model for creating a new collection."},"CreateCollectionResponse":{"properties":{"status":{"$ref":"#/components/schemas/StatusEnum","description":"Status of the response, e.g., 'success' or 'error'"},"error":{"anyOf":[{"items":{"$ref":"#/components/schemas/ErrorDetail"},"type":"array"},{"type":"null"}],"title":"Error","description":"List of error details, if any"},"result":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Result","description":"Result of the API call"}},"type":"object","required":["status"],"title":"CreateCollectionResponse","description":"Response model for creating a new collection.","examples":[{"result":1,"status":"success"},{"error":[{"code":"INVALID_NAME","message":"The provided collection name is invalid."}],"status":"error"}]},"DeleteCollectionResponse":{"properties":{"status":{"$ref":"#/components/schemas/StatusEnum","description":"Status of the response, e.g., 'success' or 'error'"},"error":{"anyOf":[{"items":{"$ref":"#/components/schemas/ErrorDetail"},"type":"array"},{"type":"null"}],"title":"Error","description":"List of error details, if any"},"result":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Result","description":"Result of the API call"}},"type":"object","required":["status"],"title":"DeleteCollectionResponse","description":"Response model for deleting a collection.","examples":[{"result":"The collection 'Collection 1' has been successfully deleted.","status":"success"}]},"ErrorDetail":{"properties":{"code":{"type":"string","title":"Code","description":"Error code identifier"},"message":{"type":"string","title":"Message","description":"Detailed error message"}},"type":"object","required":["code","message"],"title":"ErrorDetail","description":"Model for error details in API responses."},"GetCollectionResponse":{"properties":{"status":{"$ref":"#/components/schemas/StatusEnum","description":"Status of the response, e.g., 'success' or 'error'"},"error":{"anyOf":[{"items":{"$ref":"#/components/schemas/ErrorDetail"},"type":"array"},{"type":"null"}],"title":"Error","description":"List of error details, if any"},"result":{"anyOf":[{"$ref":"#/components/schemas/CollectionItemWithMetadata"},{"type":"null"}],"description":"Result of the API call"}},"type":"object","required":["status"],"title":"GetCollectionResponse","description":"Response model for retrieving a single collection.","examples":[{"result":{"created_at":"2021-09-01T12:00:00Z","id":1,"last_image_added_at":"2021-09-02T15:00:00Z","name":"Collection 1","number_of_images":5,"updated_at":"2021-09-01T12:00:00Z"},"status":"success"}]},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"ImageComparisonResponse":{"properties":{"status":{"type":"string","enum":["success","error"],"title":"Status","description":"Status of the comparison operation."},"errors":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Errors","description":"List of error messages if status is 'error', null otherwise."},"results":{"anyOf":[{"items":{"$ref":"#/components/schemas/ComparisonMetrics"},"type":"array"},{"type":"null"}],"title":"Results","description":"Comparison metrics if status is 'success', null otherwise. Contains one result comparing the reference to the target image."}},"type":"object","required":["status"],"title":"ImageComparisonResponse","description":"Response from image comparison endpoint.","examples":[{"results":[{"iou_percent":71.3,"match_percent":82.5,"query_match_rect":{"bottom":0.9,"left":0.05,"right":0.95,"top":0.1},"ssim_score":0.95,"target_match_rect":{"bottom":0.88,"left":0.08,"right":0.92,"top":0.12},"wasserstein_distance":8.7}],"status":"success"},{"errors":["Exactly one of 'reference_image' or 'reference_url' must be provided."],"status":"error"}]},"ListCollectionsResponse":{"properties":{"status":{"$ref":"#/components/schemas/StatusEnum","description":"Status of the response, e.g., 'success' or 'error'"},"error":{"anyOf":[{"items":{"$ref":"#/components/schemas/ErrorDetail"},"type":"array"},{"type":"null"}],"title":"Error","description":"List of error details, if any"},"result":{"anyOf":[{"items":{"$ref":"#/components/schemas/CollectionItem"},"type":"array"},{"type":"null"}],"title":"Result","description":"Result of the API call"}},"type":"object","required":["status"],"title":"ListCollectionsResponse","description":"Response model for listing collections.","examples":[{"result":[{"id":1,"name":"Collection 1"},{"id":2,"name":"Collection 2"}],"status":"success"}]},"QueryMatchRect":{"properties":{"left":{"type":"number","title":"Left","description":"Left boundary as normalized coordinate (0 = left edge, 1 = right edge)."},"right":{"type":"number","title":"Right","description":"Right boundary as normalized coordinate (0 = left edge, 1 = right edge)."},"top":{"type":"number","title":"Top","description":"Top boundary as normalized coordinate (0 = top edge, 1 = bottom edge)."},"bottom":{"type":"number","title":"Bottom","description":"Bottom boundary as normalized coordinate (0 = top edge, 1 = bottom edge)."}},"type":"object","required":["left","right","top","bottom"],"title":"QueryMatchRect","description":"Normalized bounding box coordinates for matched region.\n\nValues are normalized relative to image dimensions (1.0 = full width/height).\nValues outside [0,1] indicate the match extends beyond image boundaries,\nwhich can occur when matching image crops or partial overlaps.","examples":[{"bottom":0.85,"left":0.1,"right":0.9,"top":0.15}]},"SearchResponse":{"properties":{"status":{"type":"string","enum":["success","error"],"title":"Status","description":"Status of the matching operation."},"error":{"items":{"type":"string"},"type":"array","title":"Error","description":"List of error messages if status is 'error', empty otherwise."},"result":{"items":{"$ref":"#/components/schemas/SearchResult"},"type":"array","title":"Result","description":"List of matching images sorted by similarity. Empty if no matches found or on error."}},"type":"object","required":["status"],"title":"SearchResponse","description":"Response containing image matching results.","examples":[{"error":[],"result":[{"image_id":"550e8400-e29b-41d4-a716-446655440000","iou_percent":68.2,"match_percent":75.5,"query_match_rect":{"bottom":0.85,"left":0.1,"right":0.9,"top":0.15},"ssim_score":0.92,"target_match_rect":{"bottom":0.9,"left":0.05,"right":0.95,"top":0.1},"wasserstein_distance":12.3}],"status":"success"}]},"SearchResult":{"properties":{"image_id":{"type":"string","title":"Image Id","description":"The unique identifier of the matching image in the collection."},"match_percent":{"type":"number","maximum":100.0,"minimum":0.0,"title":"Match Percent","description":"Percentage of SIFT keypoints that matched (0-100%). Higher values indicate more feature overlap."},"ssim_score":{"type":"number","maximum":1.0,"minimum":0.0,"title":"Ssim Score","description":"Structural Similarity Index (0-1). 1.0 = identical images, values > 0.8 typically indicate high similarity."},"wasserstein_distance":{"type":"number","minimum":0.0,"title":"Wasserstein Distance","description":"Earth Mover's Distance between color histograms. Lower values indicate more similar color distributions. Typical range: 0-50 for similar images."},"iou_percent":{"type":"number","maximum":100.0,"minimum":0.0,"title":"Iou Percent","description":"Intersection over Union of matched regions (0-100%). Measures overlap between query and target match areas."},"query_match_rect":{"$ref":"#/components/schemas/QueryMatchRect","description":"Normalized bounding box (0-1) of the matched area in the query image."},"target_match_rect":{"$ref":"#/components/schemas/QueryMatchRect","description":"Normalized bounding box (0-1) of the matched area in the target image."}},"type":"object","required":["image_id","match_percent","ssim_score","wasserstein_distance","iou_percent","query_match_rect","target_match_rect"],"title":"SearchResult","description":"Result of matching a single image from the collection.","examples":[{"image_id":"550e8400-e29b-41d4-a716-446655440000","iou_percent":68.2,"match_percent":75.5,"query_match_rect":{"bottom":0.85,"left":0.1,"right":0.9,"top":0.15},"ssim_score":0.92,"target_match_rect":{"bottom":0.9,"left":0.05,"right":0.95,"top":0.1},"wasserstein_distance":12.3}]},"StatusEnum":{"type":"string","enum":["success","error"],"title":"StatusEnum","description":"Enumeration for the response status."},"UpdateCollectionNameRequest":{"properties":{"name":{"type":"string","minLength":1,"title":"Name","description":"The new name for the collection."}},"type":"object","required":["name"],"title":"UpdateCollectionNameRequest"},"UpdateCollectionNameResponse":{"properties":{"status":{"$ref":"#/components/schemas/StatusEnum","description":"Status of the response, e.g., 'success' or 'error'"},"error":{"anyOf":[{"items":{"$ref":"#/components/schemas/ErrorDetail"},"type":"array"},{"type":"null"}],"title":"Error","description":"List of error details, if any"},"result":{"anyOf":[{"$ref":"#/components/schemas/CollectionItem"},{"type":"null"}],"description":"Result of the API call"}},"type":"object","required":["status"],"title":"UpdateCollectionNameResponse","description":"Response model for updating the collection name.","examples":[{"result":{"id":1,"name":"Updated Collection Name"},"status":"success"}]},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}},"securitySchemes":{"Auth":{"type":"http","scheme":"bearer","description":"Enter your API token (without 'Bearer ' prefix)."}}},"servers":[{"url":"/api/v1.1"}],"security":[{"Auth":[]}]}