{
  "openapi": "3.0.1",
  "info": {
    "title": "Mars Vista API",
    "description": "Unified API for NASA Mars rover photos with advanced filtering, location queries, and scientific metadata. Access 680,000+ photos from Curiosity, Perseverance, Opportunity, and Spirit rovers.",
    "contact": {
      "name": "Mars Vista API",
      "url": "https://marsvista.dev"
    },
    "version": "v2.0.0"
  },
  "paths": {
    "/api/v2/locations": {
      "get": {
        "tags": [
          "V2 - Advanced Features"
        ],
        "summary": "Get all unique locations visited by rovers",
        "parameters": [
          {
            "name": "rovers",
            "in": "query",
            "description": "Comma-separated list of rover names",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sol_min",
            "in": "query",
            "description": "Minimum sol",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "sol_max",
            "in": "query",
            "description": "Maximum sol",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "min_photos",
            "in": "query",
            "description": "Minimum number of photos at location",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "page",
            "in": "query",
            "description": "Page number (1-indexed)",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 1
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "description": "Items per page (default: 25, max: 100)",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 25
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/LocationResourceListApiResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LocationResourceListApiResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/LocationResourceListApiResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v2/locations/{id}": {
      "get": {
        "tags": [
          "V2 - Advanced Features"
        ],
        "summary": "Get a specific location by ID",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Location ID (e.g., curiosity_79_1204)",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/LocationResource"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LocationResource"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/LocationResource"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v2/panoramas": {
      "get": {
        "tags": [
          "V2 - Advanced Features"
        ],
        "summary": "Get all detected panoramas",
        "parameters": [
          {
            "name": "rovers",
            "in": "query",
            "description": "Comma-separated list of rover names (curiosity, perseverance, etc.)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sol_min",
            "in": "query",
            "description": "Minimum sol",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "sol_max",
            "in": "query",
            "description": "Maximum sol",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "min_photos",
            "in": "query",
            "description": "Minimum number of photos in panorama",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "page",
            "in": "query",
            "description": "Page number (1-indexed)",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 1
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "description": "Items per page (default: 25, max: 100)",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 25
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/PanoramaResourceListApiResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PanoramaResourceListApiResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/PanoramaResourceListApiResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v2/panoramas/{id}": {
      "get": {
        "tags": [
          "V2 - Advanced Features"
        ],
        "summary": "Get a specific panorama by ID",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Panorama ID (e.g., pano_curiosity_1000_14)",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/PanoramaResource"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PanoramaResource"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/PanoramaResource"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v2/cameras": {
      "get": {
        "tags": [
          "V2 - Cameras"
        ],
        "summary": "Get all cameras across all rovers",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/CameraResourceListApiResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CameraResourceListApiResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/CameraResourceListApiResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v2/cameras/{id}": {
      "get": {
        "tags": [
          "V2 - Cameras"
        ],
        "summary": "Get a specific camera by ID (name)",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Camera name (e.g., FHAZ, MAST)",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "rover",
            "in": "query",
            "description": "Optional rover filter",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/CameraResourceApiResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CameraResourceApiResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/CameraResourceApiResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v2/photos": {
      "get": {
        "tags": [
          "V2 - Photos"
        ],
        "parameters": [
          {
            "name": "nasa_id",
            "in": "query",
            "description": "Search by NASA ID (partial match, case-insensitive)\r\nExample: nasa_id=NLB_780234",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "rovers",
            "in": "query",
            "description": "Filter by one or more rovers (comma-separated)\r\nExample: rovers=curiosity,perseverance",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "cameras",
            "in": "query",
            "description": "Filter by one or more cameras (comma-separated)\r\nExample: cameras=FHAZ,NAVCAM,MAST",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sol_min",
            "in": "query",
            "description": "Minimum sol (inclusive)",
            "schema": {
              "maximum": 2147483647,
              "minimum": 0,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "sol_max",
            "in": "query",
            "description": "Maximum sol (inclusive)",
            "schema": {
              "maximum": 2147483647,
              "minimum": 0,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "sol",
            "in": "query",
            "schema": {
              "maximum": 2147483647,
              "minimum": 0,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "date_min",
            "in": "query",
            "description": "Minimum earth date (inclusive, YYYY-MM-DD format)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "date_max",
            "in": "query",
            "description": "Maximum earth date (inclusive, YYYY-MM-DD format)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "earth_date",
            "in": "query",
            "description": "Exact earth date (shorthand, YYYY-MM-DD format)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sort",
            "in": "query",
            "description": "Sort fields (comma-separated, prefix with - for descending)\r\nExample: sort=-earth_date,camera",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "fields",
            "in": "query",
            "description": "Fields to include (comma-separated, for sparse fieldsets)\r\nExample: fields=id,img_src,sol,earth_date",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "include",
            "in": "query",
            "description": "Related resources to include (comma-separated)\r\nExample: include=rover,camera",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "in": "query",
            "description": "Page number (1-indexed, default: 1)",
            "schema": {
              "maximum": 2147483647,
              "minimum": 1,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "description": "Items per page (default: 25, max: 100)",
            "schema": {
              "maximum": 100,
              "minimum": 1,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "description": "Cursor for cursor-based pagination (base64-encoded)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "mars_time_min",
            "in": "query",
            "description": "Minimum Mars local time (format: Mhh:mm:ss or hh:mm:ss)\r\nExample: M06:00:00 for 6 AM Mars time",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "mars_time_max",
            "in": "query",
            "description": "Maximum Mars local time (format: Mhh:mm:ss or hh:mm:ss)\r\nExample: M18:00:00 for 6 PM Mars time",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "mars_time_golden_hour",
            "in": "query",
            "description": "Filter for golden hour photos (sunrise/sunset lighting)",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "site",
            "in": "query",
            "description": "Exact site number",
            "schema": {
              "maximum": 2147483647,
              "minimum": 0,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "site_min",
            "in": "query",
            "description": "Minimum site number (inclusive)",
            "schema": {
              "maximum": 2147483647,
              "minimum": 0,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "site_max",
            "in": "query",
            "description": "Maximum site number (inclusive)",
            "schema": {
              "maximum": 2147483647,
              "minimum": 0,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "drive",
            "in": "query",
            "description": "Exact drive number",
            "schema": {
              "maximum": 2147483647,
              "minimum": 0,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "drive_min",
            "in": "query",
            "description": "Minimum drive number (inclusive)",
            "schema": {
              "maximum": 2147483647,
              "minimum": 0,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "drive_max",
            "in": "query",
            "description": "Maximum drive number (inclusive)",
            "schema": {
              "maximum": 2147483647,
              "minimum": 0,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "location_radius",
            "in": "query",
            "schema": {
              "maximum": 1000,
              "minimum": 0,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "min_width",
            "in": "query",
            "description": "Minimum image width in pixels",
            "schema": {
              "maximum": 10000,
              "minimum": 1,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "min_height",
            "in": "query",
            "description": "Minimum image height in pixels",
            "schema": {
              "maximum": 10000,
              "minimum": 1,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "max_width",
            "in": "query",
            "description": "Maximum image width in pixels",
            "schema": {
              "maximum": 10000,
              "minimum": 1,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "max_height",
            "in": "query",
            "description": "Maximum image height in pixels",
            "schema": {
              "maximum": 10000,
              "minimum": 1,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "sample_type",
            "in": "query",
            "description": "Filter by sample type (e.g., \"Full\", \"Thumbnail\", \"Subframe\")\r\nComma-separated for multiple types",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "aspect_ratio",
            "in": "query",
            "description": "Filter by aspect ratio (e.g., \"16:9\", \"4:3\", \"1:1\")",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "mast_elevation_min",
            "in": "query",
            "description": "Minimum mast elevation angle in degrees\r\nNegative = looking down, Positive = looking up",
            "schema": {
              "maximum": 90,
              "minimum": -90,
              "type": "number",
              "format": "float"
            }
          },
          {
            "name": "mast_elevation_max",
            "in": "query",
            "description": "Maximum mast elevation angle in degrees",
            "schema": {
              "maximum": 90,
              "minimum": -90,
              "type": "number",
              "format": "float"
            }
          },
          {
            "name": "mast_azimuth_min",
            "in": "query",
            "description": "Minimum mast azimuth angle in degrees (0-360)",
            "schema": {
              "maximum": 360,
              "minimum": 0,
              "type": "number",
              "format": "float"
            }
          },
          {
            "name": "mast_azimuth_max",
            "in": "query",
            "description": "Maximum mast azimuth angle in degrees (0-360)",
            "schema": {
              "maximum": 360,
              "minimum": 0,
              "type": "number",
              "format": "float"
            }
          },
          {
            "name": "field_set",
            "in": "query",
            "description": "Field set preset (minimal, standard, extended, scientific, complete)\r\nCan also be comma-separated field names for custom selection",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "image_sizes",
            "in": "query",
            "description": "Specific image sizes to include (comma-separated: small, medium, large, full)\r\nDefault: all sizes",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "exclude_images",
            "in": "query",
            "description": "Exclude images entirely (metadata only)",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "RoverList",
            "in": "query",
            "description": "Parsed rover names (lowercase)",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          {
            "name": "CameraList",
            "in": "query",
            "description": "Parsed camera names (uppercase)",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          {
            "name": "SortFields",
            "in": "query",
            "description": "Parsed sort fields with direction",
            "schema": {
              "type": "array",
              "items": {
                "$ref": "#/components/schemas/SortField"
              }
            }
          },
          {
            "name": "FieldList",
            "in": "query",
            "description": "Parsed field names for sparse fieldsets",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          {
            "name": "IncludeList",
            "in": "query",
            "description": "Parsed include resource names",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          {
            "name": "DateMinParsed",
            "in": "query",
            "description": "Parsed minimum date",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "DateMaxParsed",
            "in": "query",
            "description": "Parsed maximum date",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "PageNumber",
            "in": "query",
            "description": "Effective page number (with default)",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "PageSize",
            "in": "query",
            "description": "Effective page size (with default, capped at 100)",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "MarsTimeMinParsed",
            "in": "query",
            "description": "Parsed Mars time minimum (TimeSpan from midnight)",
            "schema": {
              "type": "string",
              "format": "date-span"
            }
          },
          {
            "name": "MarsTimeMaxParsed",
            "in": "query",
            "description": "Parsed Mars time maximum (TimeSpan from midnight)",
            "schema": {
              "type": "string",
              "format": "date-span"
            }
          },
          {
            "name": "SampleTypeList",
            "in": "query",
            "description": "Parsed sample types list",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          {
            "name": "AspectRatioParsed",
            "in": "query",
            "description": "Parsed aspect ratio (width:height)",
            "schema": {
              "$ref": "#/components/schemas/Int32Int32ValueTuple"
            }
          },
          {
            "name": "FieldSetParsed",
            "in": "query",
            "description": "Parsed field set enum value",
            "schema": {
              "$ref": "#/components/schemas/FieldSetType"
            }
          },
          {
            "name": "ImageSizesList",
            "in": "query",
            "description": "Parsed image sizes list",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/PhotoResourceListApiResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PhotoResourceListApiResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/PhotoResourceListApiResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "304": {
            "description": "Not Modified"
          }
        }
      }
    },
    "/api/v2/photos/{id}": {
      "get": {
        "tags": [
          "V2 - Photos"
        ],
        "summary": "Get a specific photo by ID",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Photo ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "nasa_id",
            "in": "query",
            "description": "Search by NASA ID (partial match, case-insensitive)\r\nExample: nasa_id=NLB_780234",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "rovers",
            "in": "query",
            "description": "Filter by one or more rovers (comma-separated)\r\nExample: rovers=curiosity,perseverance",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "cameras",
            "in": "query",
            "description": "Filter by one or more cameras (comma-separated)\r\nExample: cameras=FHAZ,NAVCAM,MAST",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sol_min",
            "in": "query",
            "description": "Minimum sol (inclusive)",
            "schema": {
              "maximum": 2147483647,
              "minimum": 0,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "sol_max",
            "in": "query",
            "description": "Maximum sol (inclusive)",
            "schema": {
              "maximum": 2147483647,
              "minimum": 0,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "sol",
            "in": "query",
            "schema": {
              "maximum": 2147483647,
              "minimum": 0,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "date_min",
            "in": "query",
            "description": "Minimum earth date (inclusive, YYYY-MM-DD format)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "date_max",
            "in": "query",
            "description": "Maximum earth date (inclusive, YYYY-MM-DD format)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "earth_date",
            "in": "query",
            "description": "Exact earth date (shorthand, YYYY-MM-DD format)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sort",
            "in": "query",
            "description": "Sort fields (comma-separated, prefix with - for descending)\r\nExample: sort=-earth_date,camera",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "fields",
            "in": "query",
            "description": "Fields to include (comma-separated, for sparse fieldsets)\r\nExample: fields=id,img_src,sol,earth_date",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "include",
            "in": "query",
            "description": "Related resources to include (comma-separated)\r\nExample: include=rover,camera",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "in": "query",
            "description": "Page number (1-indexed, default: 1)",
            "schema": {
              "maximum": 2147483647,
              "minimum": 1,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "description": "Items per page (default: 25, max: 100)",
            "schema": {
              "maximum": 100,
              "minimum": 1,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "description": "Cursor for cursor-based pagination (base64-encoded)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "mars_time_min",
            "in": "query",
            "description": "Minimum Mars local time (format: Mhh:mm:ss or hh:mm:ss)\r\nExample: M06:00:00 for 6 AM Mars time",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "mars_time_max",
            "in": "query",
            "description": "Maximum Mars local time (format: Mhh:mm:ss or hh:mm:ss)\r\nExample: M18:00:00 for 6 PM Mars time",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "mars_time_golden_hour",
            "in": "query",
            "description": "Filter for golden hour photos (sunrise/sunset lighting)",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "site",
            "in": "query",
            "description": "Exact site number",
            "schema": {
              "maximum": 2147483647,
              "minimum": 0,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "site_min",
            "in": "query",
            "description": "Minimum site number (inclusive)",
            "schema": {
              "maximum": 2147483647,
              "minimum": 0,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "site_max",
            "in": "query",
            "description": "Maximum site number (inclusive)",
            "schema": {
              "maximum": 2147483647,
              "minimum": 0,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "drive",
            "in": "query",
            "description": "Exact drive number",
            "schema": {
              "maximum": 2147483647,
              "minimum": 0,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "drive_min",
            "in": "query",
            "description": "Minimum drive number (inclusive)",
            "schema": {
              "maximum": 2147483647,
              "minimum": 0,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "drive_max",
            "in": "query",
            "description": "Maximum drive number (inclusive)",
            "schema": {
              "maximum": 2147483647,
              "minimum": 0,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "location_radius",
            "in": "query",
            "schema": {
              "maximum": 1000,
              "minimum": 0,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "min_width",
            "in": "query",
            "description": "Minimum image width in pixels",
            "schema": {
              "maximum": 10000,
              "minimum": 1,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "min_height",
            "in": "query",
            "description": "Minimum image height in pixels",
            "schema": {
              "maximum": 10000,
              "minimum": 1,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "max_width",
            "in": "query",
            "description": "Maximum image width in pixels",
            "schema": {
              "maximum": 10000,
              "minimum": 1,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "max_height",
            "in": "query",
            "description": "Maximum image height in pixels",
            "schema": {
              "maximum": 10000,
              "minimum": 1,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "sample_type",
            "in": "query",
            "description": "Filter by sample type (e.g., \"Full\", \"Thumbnail\", \"Subframe\")\r\nComma-separated for multiple types",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "aspect_ratio",
            "in": "query",
            "description": "Filter by aspect ratio (e.g., \"16:9\", \"4:3\", \"1:1\")",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "mast_elevation_min",
            "in": "query",
            "description": "Minimum mast elevation angle in degrees\r\nNegative = looking down, Positive = looking up",
            "schema": {
              "maximum": 90,
              "minimum": -90,
              "type": "number",
              "format": "float"
            }
          },
          {
            "name": "mast_elevation_max",
            "in": "query",
            "description": "Maximum mast elevation angle in degrees",
            "schema": {
              "maximum": 90,
              "minimum": -90,
              "type": "number",
              "format": "float"
            }
          },
          {
            "name": "mast_azimuth_min",
            "in": "query",
            "description": "Minimum mast azimuth angle in degrees (0-360)",
            "schema": {
              "maximum": 360,
              "minimum": 0,
              "type": "number",
              "format": "float"
            }
          },
          {
            "name": "mast_azimuth_max",
            "in": "query",
            "description": "Maximum mast azimuth angle in degrees (0-360)",
            "schema": {
              "maximum": 360,
              "minimum": 0,
              "type": "number",
              "format": "float"
            }
          },
          {
            "name": "field_set",
            "in": "query",
            "description": "Field set preset (minimal, standard, extended, scientific, complete)\r\nCan also be comma-separated field names for custom selection",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "image_sizes",
            "in": "query",
            "description": "Specific image sizes to include (comma-separated: small, medium, large, full)\r\nDefault: all sizes",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "exclude_images",
            "in": "query",
            "description": "Exclude images entirely (metadata only)",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "RoverList",
            "in": "query",
            "description": "Parsed rover names (lowercase)",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          {
            "name": "CameraList",
            "in": "query",
            "description": "Parsed camera names (uppercase)",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          {
            "name": "SortFields",
            "in": "query",
            "description": "Parsed sort fields with direction",
            "schema": {
              "type": "array",
              "items": {
                "$ref": "#/components/schemas/SortField"
              }
            }
          },
          {
            "name": "FieldList",
            "in": "query",
            "description": "Parsed field names for sparse fieldsets",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          {
            "name": "IncludeList",
            "in": "query",
            "description": "Parsed include resource names",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          {
            "name": "DateMinParsed",
            "in": "query",
            "description": "Parsed minimum date",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "DateMaxParsed",
            "in": "query",
            "description": "Parsed maximum date",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "PageNumber",
            "in": "query",
            "description": "Effective page number (with default)",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "PageSize",
            "in": "query",
            "description": "Effective page size (with default, capped at 100)",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "MarsTimeMinParsed",
            "in": "query",
            "description": "Parsed Mars time minimum (TimeSpan from midnight)",
            "schema": {
              "type": "string",
              "format": "date-span"
            }
          },
          {
            "name": "MarsTimeMaxParsed",
            "in": "query",
            "description": "Parsed Mars time maximum (TimeSpan from midnight)",
            "schema": {
              "type": "string",
              "format": "date-span"
            }
          },
          {
            "name": "SampleTypeList",
            "in": "query",
            "description": "Parsed sample types list",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          {
            "name": "AspectRatioParsed",
            "in": "query",
            "description": "Parsed aspect ratio (width:height)",
            "schema": {
              "$ref": "#/components/schemas/Int32Int32ValueTuple"
            }
          },
          {
            "name": "FieldSetParsed",
            "in": "query",
            "description": "Parsed field set enum value",
            "schema": {
              "$ref": "#/components/schemas/FieldSetType"
            }
          },
          {
            "name": "ImageSizesList",
            "in": "query",
            "description": "Parsed image sizes list",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/PhotoResourceApiResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PhotoResourceApiResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/PhotoResourceApiResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "304": {
            "description": "Not Modified"
          }
        }
      }
    },
    "/api/v2/photos/stats": {
      "get": {
        "tags": [
          "V2 - Photos"
        ],
        "parameters": [
          {
            "name": "nasa_id",
            "in": "query",
            "description": "Search by NASA ID (partial match, case-insensitive)\r\nExample: nasa_id=NLB_780234",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "rovers",
            "in": "query",
            "description": "Filter by one or more rovers (comma-separated)\r\nExample: rovers=curiosity,perseverance",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "cameras",
            "in": "query",
            "description": "Filter by one or more cameras (comma-separated)\r\nExample: cameras=FHAZ,NAVCAM,MAST",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sol_min",
            "in": "query",
            "description": "Minimum sol (inclusive)",
            "schema": {
              "maximum": 2147483647,
              "minimum": 0,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "sol_max",
            "in": "query",
            "description": "Maximum sol (inclusive)",
            "schema": {
              "maximum": 2147483647,
              "minimum": 0,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "sol",
            "in": "query",
            "schema": {
              "maximum": 2147483647,
              "minimum": 0,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "date_min",
            "in": "query",
            "description": "Minimum earth date (inclusive, YYYY-MM-DD format)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "date_max",
            "in": "query",
            "description": "Maximum earth date (inclusive, YYYY-MM-DD format)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "earth_date",
            "in": "query",
            "description": "Exact earth date (shorthand, YYYY-MM-DD format)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sort",
            "in": "query",
            "description": "Sort fields (comma-separated, prefix with - for descending)\r\nExample: sort=-earth_date,camera",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "fields",
            "in": "query",
            "description": "Fields to include (comma-separated, for sparse fieldsets)\r\nExample: fields=id,img_src,sol,earth_date",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "include",
            "in": "query",
            "description": "Related resources to include (comma-separated)\r\nExample: include=rover,camera",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "in": "query",
            "description": "Page number (1-indexed, default: 1)",
            "schema": {
              "maximum": 2147483647,
              "minimum": 1,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "description": "Items per page (default: 25, max: 100)",
            "schema": {
              "maximum": 100,
              "minimum": 1,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "description": "Cursor for cursor-based pagination (base64-encoded)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "mars_time_min",
            "in": "query",
            "description": "Minimum Mars local time (format: Mhh:mm:ss or hh:mm:ss)\r\nExample: M06:00:00 for 6 AM Mars time",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "mars_time_max",
            "in": "query",
            "description": "Maximum Mars local time (format: Mhh:mm:ss or hh:mm:ss)\r\nExample: M18:00:00 for 6 PM Mars time",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "mars_time_golden_hour",
            "in": "query",
            "description": "Filter for golden hour photos (sunrise/sunset lighting)",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "site",
            "in": "query",
            "description": "Exact site number",
            "schema": {
              "maximum": 2147483647,
              "minimum": 0,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "site_min",
            "in": "query",
            "description": "Minimum site number (inclusive)",
            "schema": {
              "maximum": 2147483647,
              "minimum": 0,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "site_max",
            "in": "query",
            "description": "Maximum site number (inclusive)",
            "schema": {
              "maximum": 2147483647,
              "minimum": 0,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "drive",
            "in": "query",
            "description": "Exact drive number",
            "schema": {
              "maximum": 2147483647,
              "minimum": 0,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "drive_min",
            "in": "query",
            "description": "Minimum drive number (inclusive)",
            "schema": {
              "maximum": 2147483647,
              "minimum": 0,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "drive_max",
            "in": "query",
            "description": "Maximum drive number (inclusive)",
            "schema": {
              "maximum": 2147483647,
              "minimum": 0,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "location_radius",
            "in": "query",
            "schema": {
              "maximum": 1000,
              "minimum": 0,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "min_width",
            "in": "query",
            "description": "Minimum image width in pixels",
            "schema": {
              "maximum": 10000,
              "minimum": 1,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "min_height",
            "in": "query",
            "description": "Minimum image height in pixels",
            "schema": {
              "maximum": 10000,
              "minimum": 1,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "max_width",
            "in": "query",
            "description": "Maximum image width in pixels",
            "schema": {
              "maximum": 10000,
              "minimum": 1,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "max_height",
            "in": "query",
            "description": "Maximum image height in pixels",
            "schema": {
              "maximum": 10000,
              "minimum": 1,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "sample_type",
            "in": "query",
            "description": "Filter by sample type (e.g., \"Full\", \"Thumbnail\", \"Subframe\")\r\nComma-separated for multiple types",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "aspect_ratio",
            "in": "query",
            "description": "Filter by aspect ratio (e.g., \"16:9\", \"4:3\", \"1:1\")",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "mast_elevation_min",
            "in": "query",
            "description": "Minimum mast elevation angle in degrees\r\nNegative = looking down, Positive = looking up",
            "schema": {
              "maximum": 90,
              "minimum": -90,
              "type": "number",
              "format": "float"
            }
          },
          {
            "name": "mast_elevation_max",
            "in": "query",
            "description": "Maximum mast elevation angle in degrees",
            "schema": {
              "maximum": 90,
              "minimum": -90,
              "type": "number",
              "format": "float"
            }
          },
          {
            "name": "mast_azimuth_min",
            "in": "query",
            "description": "Minimum mast azimuth angle in degrees (0-360)",
            "schema": {
              "maximum": 360,
              "minimum": 0,
              "type": "number",
              "format": "float"
            }
          },
          {
            "name": "mast_azimuth_max",
            "in": "query",
            "description": "Maximum mast azimuth angle in degrees (0-360)",
            "schema": {
              "maximum": 360,
              "minimum": 0,
              "type": "number",
              "format": "float"
            }
          },
          {
            "name": "field_set",
            "in": "query",
            "description": "Field set preset (minimal, standard, extended, scientific, complete)\r\nCan also be comma-separated field names for custom selection",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "image_sizes",
            "in": "query",
            "description": "Specific image sizes to include (comma-separated: small, medium, large, full)\r\nDefault: all sizes",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "exclude_images",
            "in": "query",
            "description": "Exclude images entirely (metadata only)",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "RoverList",
            "in": "query",
            "description": "Parsed rover names (lowercase)",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          {
            "name": "CameraList",
            "in": "query",
            "description": "Parsed camera names (uppercase)",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          {
            "name": "SortFields",
            "in": "query",
            "description": "Parsed sort fields with direction",
            "schema": {
              "type": "array",
              "items": {
                "$ref": "#/components/schemas/SortField"
              }
            }
          },
          {
            "name": "FieldList",
            "in": "query",
            "description": "Parsed field names for sparse fieldsets",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          {
            "name": "IncludeList",
            "in": "query",
            "description": "Parsed include resource names",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          {
            "name": "DateMinParsed",
            "in": "query",
            "description": "Parsed minimum date",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "DateMaxParsed",
            "in": "query",
            "description": "Parsed maximum date",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "PageNumber",
            "in": "query",
            "description": "Effective page number (with default)",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "PageSize",
            "in": "query",
            "description": "Effective page size (with default, capped at 100)",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "MarsTimeMinParsed",
            "in": "query",
            "description": "Parsed Mars time minimum (TimeSpan from midnight)",
            "schema": {
              "type": "string",
              "format": "date-span"
            }
          },
          {
            "name": "MarsTimeMaxParsed",
            "in": "query",
            "description": "Parsed Mars time maximum (TimeSpan from midnight)",
            "schema": {
              "type": "string",
              "format": "date-span"
            }
          },
          {
            "name": "SampleTypeList",
            "in": "query",
            "description": "Parsed sample types list",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          {
            "name": "AspectRatioParsed",
            "in": "query",
            "description": "Parsed aspect ratio (width:height)",
            "schema": {
              "$ref": "#/components/schemas/Int32Int32ValueTuple"
            }
          },
          {
            "name": "FieldSetParsed",
            "in": "query",
            "description": "Parsed field set enum value",
            "schema": {
              "$ref": "#/components/schemas/FieldSetType"
            }
          },
          {
            "name": "ImageSizesList",
            "in": "query",
            "description": "Parsed image sizes list",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          {
            "name": "group_by",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/PhotoStatisticsResponseApiResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PhotoStatisticsResponseApiResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/PhotoStatisticsResponseApiResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v2/photos/batch": {
      "post": {
        "tags": [
          "V2 - Photos"
        ],
        "summary": "Batch retrieve photos by IDs",
        "description": "Efficiently retrieve multiple photos in a single request.\r\nMaximum 100 IDs per request.",
        "parameters": [
          {
            "name": "nasa_id",
            "in": "query",
            "description": "Search by NASA ID (partial match, case-insensitive)\r\nExample: nasa_id=NLB_780234",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "rovers",
            "in": "query",
            "description": "Filter by one or more rovers (comma-separated)\r\nExample: rovers=curiosity,perseverance",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "cameras",
            "in": "query",
            "description": "Filter by one or more cameras (comma-separated)\r\nExample: cameras=FHAZ,NAVCAM,MAST",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sol_min",
            "in": "query",
            "description": "Minimum sol (inclusive)",
            "schema": {
              "maximum": 2147483647,
              "minimum": 0,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "sol_max",
            "in": "query",
            "description": "Maximum sol (inclusive)",
            "schema": {
              "maximum": 2147483647,
              "minimum": 0,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "sol",
            "in": "query",
            "schema": {
              "maximum": 2147483647,
              "minimum": 0,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "date_min",
            "in": "query",
            "description": "Minimum earth date (inclusive, YYYY-MM-DD format)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "date_max",
            "in": "query",
            "description": "Maximum earth date (inclusive, YYYY-MM-DD format)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "earth_date",
            "in": "query",
            "description": "Exact earth date (shorthand, YYYY-MM-DD format)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sort",
            "in": "query",
            "description": "Sort fields (comma-separated, prefix with - for descending)\r\nExample: sort=-earth_date,camera",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "fields",
            "in": "query",
            "description": "Fields to include (comma-separated, for sparse fieldsets)\r\nExample: fields=id,img_src,sol,earth_date",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "include",
            "in": "query",
            "description": "Related resources to include (comma-separated)\r\nExample: include=rover,camera",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "in": "query",
            "description": "Page number (1-indexed, default: 1)",
            "schema": {
              "maximum": 2147483647,
              "minimum": 1,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "description": "Items per page (default: 25, max: 100)",
            "schema": {
              "maximum": 100,
              "minimum": 1,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "description": "Cursor for cursor-based pagination (base64-encoded)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "mars_time_min",
            "in": "query",
            "description": "Minimum Mars local time (format: Mhh:mm:ss or hh:mm:ss)\r\nExample: M06:00:00 for 6 AM Mars time",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "mars_time_max",
            "in": "query",
            "description": "Maximum Mars local time (format: Mhh:mm:ss or hh:mm:ss)\r\nExample: M18:00:00 for 6 PM Mars time",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "mars_time_golden_hour",
            "in": "query",
            "description": "Filter for golden hour photos (sunrise/sunset lighting)",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "site",
            "in": "query",
            "description": "Exact site number",
            "schema": {
              "maximum": 2147483647,
              "minimum": 0,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "site_min",
            "in": "query",
            "description": "Minimum site number (inclusive)",
            "schema": {
              "maximum": 2147483647,
              "minimum": 0,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "site_max",
            "in": "query",
            "description": "Maximum site number (inclusive)",
            "schema": {
              "maximum": 2147483647,
              "minimum": 0,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "drive",
            "in": "query",
            "description": "Exact drive number",
            "schema": {
              "maximum": 2147483647,
              "minimum": 0,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "drive_min",
            "in": "query",
            "description": "Minimum drive number (inclusive)",
            "schema": {
              "maximum": 2147483647,
              "minimum": 0,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "drive_max",
            "in": "query",
            "description": "Maximum drive number (inclusive)",
            "schema": {
              "maximum": 2147483647,
              "minimum": 0,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "location_radius",
            "in": "query",
            "schema": {
              "maximum": 1000,
              "minimum": 0,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "min_width",
            "in": "query",
            "description": "Minimum image width in pixels",
            "schema": {
              "maximum": 10000,
              "minimum": 1,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "min_height",
            "in": "query",
            "description": "Minimum image height in pixels",
            "schema": {
              "maximum": 10000,
              "minimum": 1,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "max_width",
            "in": "query",
            "description": "Maximum image width in pixels",
            "schema": {
              "maximum": 10000,
              "minimum": 1,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "max_height",
            "in": "query",
            "description": "Maximum image height in pixels",
            "schema": {
              "maximum": 10000,
              "minimum": 1,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "sample_type",
            "in": "query",
            "description": "Filter by sample type (e.g., \"Full\", \"Thumbnail\", \"Subframe\")\r\nComma-separated for multiple types",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "aspect_ratio",
            "in": "query",
            "description": "Filter by aspect ratio (e.g., \"16:9\", \"4:3\", \"1:1\")",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "mast_elevation_min",
            "in": "query",
            "description": "Minimum mast elevation angle in degrees\r\nNegative = looking down, Positive = looking up",
            "schema": {
              "maximum": 90,
              "minimum": -90,
              "type": "number",
              "format": "float"
            }
          },
          {
            "name": "mast_elevation_max",
            "in": "query",
            "description": "Maximum mast elevation angle in degrees",
            "schema": {
              "maximum": 90,
              "minimum": -90,
              "type": "number",
              "format": "float"
            }
          },
          {
            "name": "mast_azimuth_min",
            "in": "query",
            "description": "Minimum mast azimuth angle in degrees (0-360)",
            "schema": {
              "maximum": 360,
              "minimum": 0,
              "type": "number",
              "format": "float"
            }
          },
          {
            "name": "mast_azimuth_max",
            "in": "query",
            "description": "Maximum mast azimuth angle in degrees (0-360)",
            "schema": {
              "maximum": 360,
              "minimum": 0,
              "type": "number",
              "format": "float"
            }
          },
          {
            "name": "field_set",
            "in": "query",
            "description": "Field set preset (minimal, standard, extended, scientific, complete)\r\nCan also be comma-separated field names for custom selection",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "image_sizes",
            "in": "query",
            "description": "Specific image sizes to include (comma-separated: small, medium, large, full)\r\nDefault: all sizes",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "exclude_images",
            "in": "query",
            "description": "Exclude images entirely (metadata only)",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "RoverList",
            "in": "query",
            "description": "Parsed rover names (lowercase)",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          {
            "name": "CameraList",
            "in": "query",
            "description": "Parsed camera names (uppercase)",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          {
            "name": "SortFields",
            "in": "query",
            "description": "Parsed sort fields with direction",
            "schema": {
              "type": "array",
              "items": {
                "$ref": "#/components/schemas/SortField"
              }
            }
          },
          {
            "name": "FieldList",
            "in": "query",
            "description": "Parsed field names for sparse fieldsets",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          {
            "name": "IncludeList",
            "in": "query",
            "description": "Parsed include resource names",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          {
            "name": "DateMinParsed",
            "in": "query",
            "description": "Parsed minimum date",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "DateMaxParsed",
            "in": "query",
            "description": "Parsed maximum date",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "PageNumber",
            "in": "query",
            "description": "Effective page number (with default)",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "PageSize",
            "in": "query",
            "description": "Effective page size (with default, capped at 100)",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "MarsTimeMinParsed",
            "in": "query",
            "description": "Parsed Mars time minimum (TimeSpan from midnight)",
            "schema": {
              "type": "string",
              "format": "date-span"
            }
          },
          {
            "name": "MarsTimeMaxParsed",
            "in": "query",
            "description": "Parsed Mars time maximum (TimeSpan from midnight)",
            "schema": {
              "type": "string",
              "format": "date-span"
            }
          },
          {
            "name": "SampleTypeList",
            "in": "query",
            "description": "Parsed sample types list",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          {
            "name": "AspectRatioParsed",
            "in": "query",
            "description": "Parsed aspect ratio (width:height)",
            "schema": {
              "$ref": "#/components/schemas/Int32Int32ValueTuple"
            }
          },
          {
            "name": "FieldSetParsed",
            "in": "query",
            "description": "Parsed field set enum value",
            "schema": {
              "$ref": "#/components/schemas/FieldSetType"
            }
          },
          {
            "name": "ImageSizesList",
            "in": "query",
            "description": "Parsed image sizes list",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BatchPhotoRequest"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/BatchPhotoRequest"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/BatchPhotoRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/PhotoResourceListApiResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PhotoResourceListApiResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/PhotoResourceListApiResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v2/rovers": {
      "get": {
        "tags": [
          "V2 - Rovers"
        ],
        "summary": "Get all rovers",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/RoverResourceListApiResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RoverResourceListApiResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/RoverResourceListApiResponse"
                }
              }
            }
          },
          "304": {
            "description": "Not Modified"
          }
        }
      }
    },
    "/api/v2/rovers/{slug}": {
      "get": {
        "tags": [
          "V2 - Rovers"
        ],
        "summary": "Get a specific rover by slug",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "description": "Rover slug (curiosity, perseverance, opportunity, spirit)",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/RoverResourceApiResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RoverResourceApiResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/RoverResourceApiResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v2/rovers/{slug}/manifest": {
      "get": {
        "tags": [
          "V2 - Rovers"
        ],
        "summary": "Get rover manifest (photo history by sol)",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "description": "Rover slug",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/RoverManifestApiResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RoverManifestApiResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/RoverManifestApiResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v2/rovers/{slug}/cameras": {
      "get": {
        "tags": [
          "V2 - Rovers"
        ],
        "summary": "Get cameras for a specific rover",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "description": "Rover slug",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/CameraResourceListApiResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CameraResourceListApiResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/CameraResourceListApiResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v2/rovers/{slug}/journey": {
      "get": {
        "tags": [
          "V2 - Rovers"
        ],
        "summary": "Get journey tracking data for a rover",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "description": "Rover slug",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sol_min",
            "in": "query",
            "description": "Minimum sol",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "sol_max",
            "in": "query",
            "description": "Maximum sol",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/JourneyResourceApiResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JourneyResourceApiResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/JourneyResourceApiResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v2/rovers/{slug}/traverse": {
      "get": {
        "tags": [
          "V2 - Rovers"
        ],
        "summary": "Get deduplicated traverse path for a rover",
        "description": "Returns deduplicated coordinates optimized for map visualization.\r\nUnlike the journey endpoint which groups by sol/site/drive (including duplicates),\r\ntraverse returns one point per unique location with actual 3D distance calculations.",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "description": "Rover slug",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sol_min",
            "in": "query",
            "description": "Minimum sol",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "sol_max",
            "in": "query",
            "description": "Maximum sol",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "format",
            "in": "query",
            "description": "Output format: json (default) or geojson",
            "schema": {
              "type": "string",
              "default": "json"
            }
          },
          {
            "name": "simplify",
            "in": "query",
            "description": "Douglas-Peucker tolerance in meters (0 = no simplification)",
            "schema": {
              "type": "number",
              "format": "float",
              "default": 0
            }
          },
          {
            "name": "include_segments",
            "in": "query",
            "description": "Include per-segment distance/bearing data",
            "schema": {
              "type": "boolean",
              "default": false
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/GeoJsonFeatureCollection"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GeoJsonFeatureCollection"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/GeoJsonFeatureCollection"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "ApiError": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "description": "A URI reference that identifies the problem type",
            "nullable": true
          },
          "title": {
            "type": "string",
            "description": "A short, human-readable summary of the problem type",
            "nullable": true
          },
          "status": {
            "type": "integer",
            "description": "The HTTP status code",
            "format": "int32"
          },
          "detail": {
            "type": "string",
            "description": "A human-readable explanation specific to this occurrence of the problem",
            "nullable": true
          },
          "instance": {
            "type": "string",
            "description": "A URI reference that identifies the specific occurrence of the problem",
            "nullable": true
          },
          "errors": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ValidationError"
            },
            "description": "Field-level validation errors",
            "nullable": true
          },
          "timestamp": {
            "type": "string",
            "description": "Response timestamp",
            "format": "date-time"
          }
        },
        "additionalProperties": false,
        "description": "RFC 7807 Problem Details for HTTP APIs\r\nProvides machine-readable error responses with detailed field-level validation errors"
      },
      "BatchPhotoRequest": {
        "type": "object",
        "properties": {
          "Ids": {
            "type": "array",
            "items": {
              "type": "integer",
              "format": "int32"
            },
            "description": "List of photo IDs to retrieve (maximum 100)",
            "nullable": true
          }
        },
        "additionalProperties": false,
        "description": "Request model for batch photo retrieval"
      },
      "CameraAttributes": {
        "type": "object",
        "properties": {
          "full_name": {
            "type": "string",
            "description": "Full camera name",
            "nullable": true
          },
          "photo_count": {
            "type": "integer",
            "description": "Number of photos from this camera (when included in statistics)",
            "format": "int32",
            "nullable": true
          }
        },
        "additionalProperties": false,
        "description": "Camera attributes"
      },
      "CameraReference": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Camera identifier (name like \"FHAZ\", \"MAST\")",
            "nullable": true
          },
          "type": {
            "type": "string",
            "description": "Resource type (always \"camera\")",
            "nullable": true
          },
          "attributes": {
            "$ref": "#/components/schemas/CameraAttributes"
          }
        },
        "additionalProperties": false,
        "description": "Camera reference with attributes"
      },
      "CameraRelationships": {
        "type": "object",
        "properties": {
          "rover": {
            "$ref": "#/components/schemas/ResourceReference"
          }
        },
        "additionalProperties": false,
        "description": "Camera relationships"
      },
      "CameraResource": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Camera identifier (name like \"FHAZ\", \"MAST\")",
            "nullable": true
          },
          "type": {
            "type": "string",
            "description": "Resource type (always \"camera\")",
            "nullable": true
          },
          "attributes": {
            "$ref": "#/components/schemas/CameraResourceAttributes"
          },
          "relationships": {
            "$ref": "#/components/schemas/CameraRelationships"
          }
        },
        "additionalProperties": false,
        "description": "Camera resource in v2 API format"
      },
      "CameraResourceApiResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/CameraResource"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "pagination": {
            "$ref": "#/components/schemas/PaginationInfo"
          },
          "links": {
            "$ref": "#/components/schemas/ResponseLinks"
          }
        },
        "additionalProperties": false,
        "description": "Standardized API response envelope for v2 endpoints\r\nInspired by JSON:API specification for consistency"
      },
      "CameraResourceAttributes": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "Camera name (e.g., \"FHAZ\", \"MAST\")",
            "nullable": true
          },
          "full_name": {
            "type": "string",
            "description": "Full camera name (e.g., \"Front Hazard Avoidance Camera\")",
            "nullable": true
          },
          "photo_count": {
            "type": "integer",
            "description": "Total number of photos from this camera",
            "format": "int32",
            "nullable": true
          },
          "first_photo_sol": {
            "type": "integer",
            "description": "First sol with photos from this camera",
            "format": "int32",
            "nullable": true
          },
          "last_photo_sol": {
            "type": "integer",
            "description": "Last sol with photos from this camera",
            "format": "int32",
            "nullable": true
          }
        },
        "additionalProperties": false,
        "description": "Camera attributes"
      },
      "CameraResourceListApiResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CameraResource"
            },
            "description": "The primary data for this response",
            "nullable": true
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "pagination": {
            "$ref": "#/components/schemas/PaginationInfo"
          },
          "links": {
            "$ref": "#/components/schemas/ResponseLinks"
          }
        },
        "additionalProperties": false,
        "description": "Standardized API response envelope for v2 endpoints\r\nInspired by JSON:API specification for consistency"
      },
      "CursorInfo": {
        "type": "object",
        "properties": {
          "current": {
            "type": "string",
            "description": "Cursor for the current page",
            "nullable": true
          },
          "next": {
            "type": "string",
            "description": "Cursor for the next page",
            "nullable": true
          },
          "previous": {
            "type": "string",
            "description": "Cursor for the previous page",
            "nullable": true
          }
        },
        "additionalProperties": false,
        "description": "Cursor-based pagination pointers"
      },
      "FieldSetType": {
        "enum": [
          0,
          1,
          2,
          3,
          4
        ],
        "type": "integer",
        "description": "Field set types for controlling response data",
        "format": "int32"
      },
      "GeoJsonFeature": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "nullable": true
          },
          "geometry": {
            "$ref": "#/components/schemas/GeoJsonLineString"
          },
          "properties": {
            "$ref": "#/components/schemas/GeoJsonProperties"
          }
        },
        "additionalProperties": false,
        "description": "GeoJSON Feature containing the traverse LineString"
      },
      "GeoJsonFeatureCollection": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "nullable": true
          },
          "features": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/GeoJsonFeature"
            },
            "nullable": true
          }
        },
        "additionalProperties": false,
        "description": "GeoJSON FeatureCollection for traverse path"
      },
      "GeoJsonLineString": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "nullable": true
          },
          "coordinates": {
            "type": "array",
            "items": {
              "type": "array",
              "items": {
                "type": "number",
                "format": "float"
              }
            },
            "description": "Array of [x, y, z] coordinate arrays",
            "nullable": true
          }
        },
        "additionalProperties": false,
        "description": "GeoJSON LineString geometry"
      },
      "GeoJsonProperties": {
        "type": "object",
        "properties": {
          "rover": {
            "type": "string",
            "nullable": true
          },
          "sol_range": {
            "type": "array",
            "items": {
              "type": "integer",
              "format": "int32"
            },
            "nullable": true
          },
          "total_distance_m": {
            "type": "number",
            "format": "float"
          },
          "point_count": {
            "type": "integer",
            "format": "int32"
          }
        },
        "additionalProperties": false,
        "description": "Properties for the GeoJSON feature"
      },
      "Int32Int32ValueTuple": {
        "type": "object",
        "additionalProperties": false
      },
      "JourneyAttributes": {
        "type": "object",
        "properties": {
          "rover": {
            "type": "string",
            "description": "Rover name",
            "nullable": true
          },
          "sol_start": {
            "type": "integer",
            "description": "Starting sol",
            "format": "int32"
          },
          "sol_end": {
            "type": "integer",
            "description": "Ending sol",
            "format": "int32"
          },
          "distance_traveled_km": {
            "type": "number",
            "description": "Approximate distance traveled in kilometers",
            "format": "float",
            "nullable": true
          },
          "locations_visited": {
            "type": "integer",
            "description": "Number of unique locations visited",
            "format": "int32"
          },
          "elevation_change_m": {
            "type": "number",
            "description": "Elevation change in meters (if calculable)",
            "format": "float",
            "nullable": true
          },
          "total_photos": {
            "type": "integer",
            "description": "Total photos taken during journey",
            "format": "int32"
          }
        },
        "additionalProperties": false,
        "description": "Journey attributes and statistics"
      },
      "JourneyLinks": {
        "type": "object",
        "properties": {
          "map_visualization": {
            "type": "string",
            "description": "Link to map visualization (future feature)",
            "nullable": true
          },
          "kml_export": {
            "type": "string",
            "description": "Link to KML export (future feature)",
            "nullable": true
          }
        },
        "additionalProperties": false,
        "description": "Links related to the journey"
      },
      "JourneyResource": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "description": "Resource type (always \"journey\")",
            "nullable": true
          },
          "attributes": {
            "$ref": "#/components/schemas/JourneyAttributes"
          },
          "path": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/JourneyWaypoint"
            },
            "description": "Path waypoints",
            "nullable": true
          },
          "links": {
            "$ref": "#/components/schemas/JourneyLinks"
          }
        },
        "additionalProperties": false,
        "description": "Journey resource representing a rover's path over a sol range"
      },
      "JourneyResourceApiResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/JourneyResource"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "pagination": {
            "$ref": "#/components/schemas/PaginationInfo"
          },
          "links": {
            "$ref": "#/components/schemas/ResponseLinks"
          }
        },
        "additionalProperties": false,
        "description": "Standardized API response envelope for v2 endpoints\r\nInspired by JSON:API specification for consistency"
      },
      "JourneyWaypoint": {
        "type": "object",
        "properties": {
          "sol": {
            "type": "integer",
            "description": "Sol at this waypoint",
            "format": "int32"
          },
          "earth_date": {
            "type": "string",
            "description": "Earth date at this waypoint",
            "nullable": true
          },
          "site": {
            "type": "integer",
            "description": "Site number",
            "format": "int32"
          },
          "drive": {
            "type": "integer",
            "description": "Drive number",
            "format": "int32"
          },
          "coordinates": {
            "$ref": "#/components/schemas/PhotoCoordinates"
          },
          "photos_taken": {
            "type": "integer",
            "description": "Number of photos taken at this waypoint",
            "format": "int32"
          }
        },
        "additionalProperties": false,
        "description": "A waypoint on the rover's journey"
      },
      "LocationAttributes": {
        "type": "object",
        "properties": {
          "rover": {
            "type": "string",
            "description": "Rover name",
            "nullable": true
          },
          "site": {
            "type": "integer",
            "description": "Site number",
            "format": "int32"
          },
          "drive": {
            "type": "integer",
            "description": "Drive number",
            "format": "int32"
          },
          "name": {
            "type": "string",
            "description": "Location name (if known)",
            "nullable": true
          },
          "first_visited": {
            "type": "string",
            "description": "First date this location was visited",
            "nullable": true
          },
          "last_visited": {
            "type": "string",
            "description": "Last date this location was visited",
            "nullable": true
          },
          "first_sol": {
            "type": "integer",
            "description": "First sol this location was visited",
            "format": "int32",
            "nullable": true
          },
          "last_sol": {
            "type": "integer",
            "description": "Last sol this location was visited",
            "format": "int32",
            "nullable": true
          },
          "photo_count": {
            "type": "integer",
            "description": "Total number of photos taken at this location",
            "format": "int32"
          },
          "visit_count": {
            "type": "integer",
            "description": "Number of unique visits to this location",
            "format": "int32",
            "nullable": true
          },
          "coordinates": {
            "$ref": "#/components/schemas/PhotoCoordinates"
          }
        },
        "additionalProperties": false,
        "description": "Location attributes"
      },
      "LocationLinks": {
        "type": "object",
        "properties": {
          "photos": {
            "type": "string",
            "description": "Link to all photos at this location",
            "nullable": true
          },
          "360_view": {
            "type": "string",
            "description": "Link to 360-degree view (future feature)",
            "nullable": true
          },
          "time_lapse": {
            "type": "string",
            "description": "Link to time-lapse of this location (future feature)",
            "nullable": true
          }
        },
        "additionalProperties": false,
        "description": "Links related to the location"
      },
      "LocationResource": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique location identifier (e.g., \"curiosity_79_1204\")",
            "nullable": true
          },
          "type": {
            "type": "string",
            "description": "Resource type (always \"location\")",
            "nullable": true
          },
          "attributes": {
            "$ref": "#/components/schemas/LocationAttributes"
          },
          "links": {
            "$ref": "#/components/schemas/LocationLinks"
          }
        },
        "additionalProperties": false,
        "description": "Location resource representing a unique site/drive location visited by a rover"
      },
      "LocationResourceListApiResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/LocationResource"
            },
            "description": "The primary data for this response",
            "nullable": true
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "pagination": {
            "$ref": "#/components/schemas/PaginationInfo"
          },
          "links": {
            "$ref": "#/components/schemas/ResponseLinks"
          }
        },
        "additionalProperties": false,
        "description": "Standardized API response envelope for v2 endpoints\r\nInspired by JSON:API specification for consistency"
      },
      "ManifestAttributes": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "Rover name",
            "nullable": true
          },
          "landing_date": {
            "type": "string",
            "description": "Landing date (YYYY-MM-DD)",
            "nullable": true
          },
          "launch_date": {
            "type": "string",
            "description": "Launch date (YYYY-MM-DD)",
            "nullable": true
          },
          "status": {
            "type": "string",
            "description": "Mission status",
            "nullable": true
          },
          "max_sol": {
            "type": "integer",
            "description": "Maximum sol",
            "format": "int32"
          },
          "max_date": {
            "type": "string",
            "description": "Most recent photo date",
            "nullable": true
          },
          "total_photos": {
            "type": "integer",
            "description": "Total photos",
            "format": "int32"
          },
          "photos": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PhotosBySol"
            },
            "description": "Photo counts by sol",
            "nullable": true
          }
        },
        "additionalProperties": false,
        "description": "Manifest attributes"
      },
      "PaginationInfo": {
        "type": "object",
        "properties": {
          "page": {
            "type": "integer",
            "description": "Current page number (1-indexed)",
            "format": "int32",
            "nullable": true
          },
          "per_page": {
            "type": "integer",
            "description": "Number of items per page",
            "format": "int32"
          },
          "total_pages": {
            "type": "integer",
            "description": "Total number of pages",
            "format": "int32",
            "nullable": true
          },
          "cursor": {
            "$ref": "#/components/schemas/CursorInfo"
          }
        },
        "additionalProperties": false,
        "description": "Pagination information supporting both page-based and cursor-based pagination"
      },
      "PanoramaAttributes": {
        "type": "object",
        "properties": {
          "rover": {
            "type": "string",
            "description": "Rover name",
            "nullable": true
          },
          "sol": {
            "type": "integer",
            "description": "Sol when panorama was taken",
            "format": "int32"
          },
          "mars_time_start": {
            "type": "string",
            "description": "Mars time when panorama sequence started",
            "nullable": true
          },
          "mars_time_end": {
            "type": "string",
            "description": "Mars time when panorama sequence ended",
            "nullable": true
          },
          "total_photos": {
            "type": "integer",
            "description": "Total number of photos in the panorama",
            "format": "int32"
          },
          "coverage_degrees": {
            "type": "number",
            "description": "Approximate angular coverage in degrees",
            "format": "float",
            "nullable": true
          },
          "location": {
            "$ref": "#/components/schemas/PhotoLocation"
          },
          "camera": {
            "type": "string",
            "description": "Camera used for the panorama",
            "nullable": true
          },
          "avg_elevation": {
            "type": "number",
            "description": "Average elevation angle",
            "format": "float",
            "nullable": true
          },
          "unique_positions": {
            "type": "integer",
            "description": "Number of unique azimuth positions (distinct camera angles)",
            "format": "int32"
          },
          "avg_position_spacing": {
            "type": "number",
            "description": "Average spacing between positions in degrees",
            "format": "float",
            "nullable": true
          },
          "quality": {
            "type": "string",
            "description": "Quality tier based on coverage and positions: partial, half, wide, or full",
            "nullable": true
          }
        },
        "additionalProperties": false,
        "description": "Panorama attributes"
      },
      "PanoramaLinks": {
        "type": "object",
        "properties": {
          "stitched_preview": {
            "type": "string",
            "description": "Link to panorama preview/stitched image (future feature)",
            "nullable": true
          },
          "download_set": {
            "type": "string",
            "description": "Link to download all photos as a set",
            "nullable": true
          }
        },
        "additionalProperties": false,
        "description": "Links related to the panorama"
      },
      "PanoramaResource": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique panorama identifier (e.g., \"pano_curiosity_1000_14\")",
            "nullable": true
          },
          "type": {
            "type": "string",
            "description": "Resource type (always \"panorama\")",
            "nullable": true
          },
          "attributes": {
            "$ref": "#/components/schemas/PanoramaAttributes"
          },
          "photos": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PhotoResource"
            },
            "description": "Photos that make up this panorama",
            "nullable": true
          },
          "links": {
            "$ref": "#/components/schemas/PanoramaLinks"
          }
        },
        "additionalProperties": false,
        "description": "Panorama resource representing an auto-detected panoramic sequence"
      },
      "PanoramaResourceListApiResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PanoramaResource"
            },
            "description": "The primary data for this response",
            "nullable": true
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "pagination": {
            "$ref": "#/components/schemas/PaginationInfo"
          },
          "links": {
            "$ref": "#/components/schemas/ResponseLinks"
          }
        },
        "additionalProperties": false,
        "description": "Standardized API response envelope for v2 endpoints\r\nInspired by JSON:API specification for consistency"
      },
      "PeriodInfo": {
        "type": "object",
        "properties": {
          "from": {
            "type": "string",
            "description": "Start date of the period (YYYY-MM-DD)",
            "nullable": true
          },
          "to": {
            "type": "string",
            "description": "End date of the period (YYYY-MM-DD)",
            "nullable": true
          }
        },
        "additionalProperties": false,
        "description": "Time period information"
      },
      "PhotoAttributes": {
        "type": "object",
        "properties": {
          "nasa_id": {
            "type": "string",
            "description": "NASA's unique identifier for this photo",
            "nullable": true
          },
          "sol": {
            "type": "integer",
            "description": "Mars sol (day) when photo was taken",
            "format": "int32",
            "nullable": true
          },
          "earth_date": {
            "type": "string",
            "description": "Earth date when photo was taken (YYYY-MM-DD)",
            "nullable": true
          },
          "date_taken_utc": {
            "type": "string",
            "description": "UTC timestamp when photo was taken",
            "format": "date-time",
            "nullable": true
          },
          "date_taken_mars": {
            "type": "string",
            "description": "Mars local time when photo was taken (e.g., \"Sol-1000M14:23:45\")",
            "nullable": true
          },
          "images": {
            "$ref": "#/components/schemas/PhotoImages"
          },
          "dimensions": {
            "$ref": "#/components/schemas/PhotoDimensions"
          },
          "sample_type": {
            "type": "string",
            "description": "Sample type (e.g., \"Full\", \"Thumbnail\", \"Subframe\")",
            "nullable": true
          },
          "location": {
            "$ref": "#/components/schemas/PhotoLocation"
          },
          "telemetry": {
            "$ref": "#/components/schemas/PhotoTelemetry"
          },
          "title": {
            "type": "string",
            "description": "Photo title",
            "nullable": true
          },
          "caption": {
            "type": "string",
            "description": "Photo caption/description",
            "nullable": true
          },
          "credit": {
            "type": "string",
            "description": "Photo credit (e.g., \"NASA/JPL-Caltech\")",
            "nullable": true
          },
          "created_at": {
            "type": "string",
            "description": "When this photo was added to our database",
            "format": "date-time",
            "nullable": true
          },
          "img_src": {
            "type": "string",
            "description": "URL to the photo image (legacy field, use images.medium instead)",
            "nullable": true
          },
          "raw_data": {
            "description": "Raw NASA API response data (JSONB). Only included when field_set=complete.\r\nContains all original NASA fields for data validation and debugging.",
            "nullable": true
          }
        },
        "additionalProperties": false,
        "description": "Photo attributes (data fields)"
      },
      "PhotoCoordinates": {
        "type": "object",
        "properties": {
          "x": {
            "type": "number",
            "description": "X coordinate",
            "format": "float"
          },
          "y": {
            "type": "number",
            "description": "Y coordinate",
            "format": "float"
          },
          "z": {
            "type": "number",
            "description": "Z coordinate",
            "format": "float"
          }
        },
        "additionalProperties": false,
        "description": "3D coordinates"
      },
      "PhotoDimensions": {
        "type": "object",
        "properties": {
          "width": {
            "type": "integer",
            "description": "Image width in pixels",
            "format": "int32"
          },
          "height": {
            "type": "integer",
            "description": "Image height in pixels",
            "format": "int32"
          }
        },
        "additionalProperties": false,
        "description": "Image dimensions"
      },
      "PhotoImages": {
        "type": "object",
        "properties": {
          "small": {
            "type": "string",
            "description": "Small size (320px wide) - for thumbnails",
            "nullable": true
          },
          "medium": {
            "type": "string",
            "description": "Medium size (800px wide) - for galleries",
            "nullable": true
          },
          "large": {
            "type": "string",
            "description": "Large size (1200px wide) - for detailed viewing",
            "nullable": true
          },
          "full": {
            "type": "string",
            "description": "Full resolution - for download and analysis",
            "nullable": true
          }
        },
        "additionalProperties": false,
        "description": "Multiple image URLs for different sizes"
      },
      "PhotoLocation": {
        "type": "object",
        "properties": {
          "site": {
            "type": "integer",
            "description": "Site number (geological location marker)",
            "format": "int32",
            "nullable": true
          },
          "drive": {
            "type": "integer",
            "description": "Drive number (rover's drive sequence)",
            "format": "int32",
            "nullable": true
          },
          "coordinates": {
            "$ref": "#/components/schemas/PhotoCoordinates"
          }
        },
        "additionalProperties": false,
        "description": "Location where photo was taken"
      },
      "PhotoMeta": {
        "type": "object",
        "properties": {
          "is_panorama_part": {
            "type": "boolean",
            "description": "Whether this photo is part of a panorama sequence",
            "nullable": true
          },
          "panorama_sequence_id": {
            "type": "string",
            "description": "Panorama sequence identifier if part of a panorama",
            "nullable": true
          },
          "has_stereo_pair": {
            "type": "boolean",
            "description": "Whether this photo has a stereo pair",
            "nullable": true
          },
          "stereo_pair_id": {
            "type": "integer",
            "description": "Stereo pair photo ID if available",
            "format": "int32",
            "nullable": true
          },
          "lighting_conditions": {
            "type": "string",
            "description": "Lighting conditions (e.g., \"golden_hour\", \"midday\", \"evening\")",
            "nullable": true
          },
          "location_visits": {
            "type": "integer",
            "description": "Number of times rover visited this location",
            "format": "int32",
            "nullable": true
          }
        },
        "additionalProperties": false,
        "description": "Photo-specific computed metadata"
      },
      "PhotoRelationships": {
        "type": "object",
        "properties": {
          "rover": {
            "$ref": "#/components/schemas/ResourceReference"
          },
          "camera": {
            "$ref": "#/components/schemas/CameraReference"
          }
        },
        "additionalProperties": false,
        "description": "Photo relationships (related resources)"
      },
      "PhotoResource": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "description": "Unique photo identifier",
            "format": "int32"
          },
          "type": {
            "type": "string",
            "description": "Resource type (always \"photo\")",
            "nullable": true
          },
          "attributes": {
            "$ref": "#/components/schemas/PhotoAttributes"
          },
          "relationships": {
            "$ref": "#/components/schemas/PhotoRelationships"
          },
          "meta": {
            "$ref": "#/components/schemas/PhotoMeta"
          }
        },
        "additionalProperties": false,
        "description": "Photo resource in v2 API format with clear separation of attributes and relationships"
      },
      "PhotoResourceApiResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/PhotoResource"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "pagination": {
            "$ref": "#/components/schemas/PaginationInfo"
          },
          "links": {
            "$ref": "#/components/schemas/ResponseLinks"
          }
        },
        "additionalProperties": false,
        "description": "Standardized API response envelope for v2 endpoints\r\nInspired by JSON:API specification for consistency"
      },
      "PhotoResourceListApiResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PhotoResource"
            },
            "description": "The primary data for this response",
            "nullable": true
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "pagination": {
            "$ref": "#/components/schemas/PaginationInfo"
          },
          "links": {
            "$ref": "#/components/schemas/ResponseLinks"
          }
        },
        "additionalProperties": false,
        "description": "Standardized API response envelope for v2 endpoints\r\nInspired by JSON:API specification for consistency"
      },
      "PhotoStatisticsResponse": {
        "type": "object",
        "properties": {
          "total_photos": {
            "type": "integer",
            "description": "Total count of photos in the period",
            "format": "int32"
          },
          "period": {
            "$ref": "#/components/schemas/PeriodInfo"
          },
          "groups": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/StatisticsGroup"
            },
            "description": "Statistics grouped by the requested dimension (camera, rover, or sol)",
            "nullable": true
          }
        },
        "additionalProperties": false,
        "description": "Response containing photo statistics and analytics"
      },
      "PhotoStatisticsResponseApiResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/PhotoStatisticsResponse"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "pagination": {
            "$ref": "#/components/schemas/PaginationInfo"
          },
          "links": {
            "$ref": "#/components/schemas/ResponseLinks"
          }
        },
        "additionalProperties": false,
        "description": "Standardized API response envelope for v2 endpoints\r\nInspired by JSON:API specification for consistency"
      },
      "PhotoTelemetry": {
        "type": "object",
        "properties": {
          "mast_azimuth": {
            "type": "number",
            "description": "Mast azimuth angle (horizontal rotation in degrees)",
            "format": "float",
            "nullable": true
          },
          "mast_elevation": {
            "type": "number",
            "description": "Mast elevation angle (vertical tilt in degrees)",
            "format": "float",
            "nullable": true
          },
          "spacecraft_clock": {
            "type": "number",
            "description": "Spacecraft clock at time of capture",
            "format": "float",
            "nullable": true
          }
        },
        "additionalProperties": false,
        "description": "Camera telemetry data"
      },
      "PhotosBySol": {
        "type": "object",
        "properties": {
          "sol": {
            "type": "integer",
            "description": "Mars sol number",
            "format": "int32"
          },
          "earth_date": {
            "type": "string",
            "description": "Earth date (YYYY-MM-DD)",
            "nullable": true
          },
          "total_photos": {
            "type": "integer",
            "description": "Total photos taken on this sol",
            "format": "int32"
          },
          "cameras": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Cameras that took photos on this sol",
            "nullable": true
          }
        },
        "additionalProperties": false,
        "description": "Photos taken on a specific sol"
      },
      "ResourceReference": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Resource identifier (slug for rovers, id for others)",
            "nullable": true
          },
          "type": {
            "type": "string",
            "description": "Resource type",
            "nullable": true
          },
          "attributes": {
            "description": "Attributes of the related resource (when included)",
            "nullable": true
          }
        },
        "additionalProperties": false,
        "description": "Reference to a related resource"
      },
      "ResponseLinks": {
        "type": "object",
        "properties": {
          "self": {
            "type": "string",
            "description": "Link to the current resource/page",
            "nullable": true
          },
          "next": {
            "type": "string",
            "description": "Link to the next page",
            "nullable": true
          },
          "previous": {
            "type": "string",
            "description": "Link to the previous page",
            "nullable": true
          },
          "first": {
            "type": "string",
            "description": "Link to the first page",
            "nullable": true
          },
          "last": {
            "type": "string",
            "description": "Link to the last page",
            "nullable": true
          }
        },
        "additionalProperties": false,
        "description": "Related resource links for navigation"
      },
      "ResponseMeta": {
        "type": "object",
        "properties": {
          "total_count": {
            "type": "integer",
            "description": "Total count of resources matching the query (before pagination)",
            "format": "int32",
            "nullable": true
          },
          "returned_count": {
            "type": "integer",
            "description": "Number of resources returned in this response",
            "format": "int32"
          },
          "query": {
            "type": "object",
            "additionalProperties": {},
            "description": "The query parameters that were applied",
            "nullable": true
          },
          "timestamp": {
            "type": "string",
            "description": "Response timestamp",
            "format": "date-time"
          }
        },
        "additionalProperties": false,
        "description": "Metadata about the response"
      },
      "RoverAttributes": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "Rover name (capitalized)",
            "nullable": true
          },
          "landing_date": {
            "type": "string",
            "description": "Landing date on Mars (YYYY-MM-DD)",
            "nullable": true
          },
          "launch_date": {
            "type": "string",
            "description": "Launch date from Earth (YYYY-MM-DD)",
            "nullable": true
          },
          "status": {
            "type": "string",
            "description": "Mission status (active, complete)",
            "nullable": true
          },
          "max_sol": {
            "type": "integer",
            "description": "Maximum sol reached by this rover",
            "format": "int32"
          },
          "max_date": {
            "type": "string",
            "description": "Most recent photo date (YYYY-MM-DD)",
            "nullable": true
          },
          "total_photos": {
            "type": "integer",
            "description": "Total number of photos in our database",
            "format": "int32"
          }
        },
        "additionalProperties": false,
        "description": "Rover attributes"
      },
      "RoverManifest": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Rover identifier (slug)",
            "nullable": true
          },
          "type": {
            "type": "string",
            "description": "Resource type (always \"manifest\")",
            "nullable": true
          },
          "attributes": {
            "$ref": "#/components/schemas/ManifestAttributes"
          }
        },
        "additionalProperties": false,
        "description": "Rover manifest (photo history by sol)"
      },
      "RoverManifestApiResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/RoverManifest"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "pagination": {
            "$ref": "#/components/schemas/PaginationInfo"
          },
          "links": {
            "$ref": "#/components/schemas/ResponseLinks"
          }
        },
        "additionalProperties": false,
        "description": "Standardized API response envelope for v2 endpoints\r\nInspired by JSON:API specification for consistency"
      },
      "RoverRelationships": {
        "type": "object",
        "properties": {
          "cameras": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CameraResource"
            },
            "description": "Cameras on this rover",
            "nullable": true
          }
        },
        "additionalProperties": false,
        "description": "Rover relationships"
      },
      "RoverResource": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Rover identifier (slug: curiosity, perseverance, opportunity, spirit)",
            "nullable": true
          },
          "type": {
            "type": "string",
            "description": "Resource type (always \"rover\")",
            "nullable": true
          },
          "attributes": {
            "$ref": "#/components/schemas/RoverAttributes"
          },
          "relationships": {
            "$ref": "#/components/schemas/RoverRelationships"
          }
        },
        "additionalProperties": false,
        "description": "Rover resource in v2 API format"
      },
      "RoverResourceApiResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/RoverResource"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "pagination": {
            "$ref": "#/components/schemas/PaginationInfo"
          },
          "links": {
            "$ref": "#/components/schemas/ResponseLinks"
          }
        },
        "additionalProperties": false,
        "description": "Standardized API response envelope for v2 endpoints\r\nInspired by JSON:API specification for consistency"
      },
      "RoverResourceListApiResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RoverResource"
            },
            "description": "The primary data for this response",
            "nullable": true
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          },
          "pagination": {
            "$ref": "#/components/schemas/PaginationInfo"
          },
          "links": {
            "$ref": "#/components/schemas/ResponseLinks"
          }
        },
        "additionalProperties": false,
        "description": "Standardized API response envelope for v2 endpoints\r\nInspired by JSON:API specification for consistency"
      },
      "SortDirection": {
        "enum": [
          0,
          1
        ],
        "type": "integer",
        "description": "Sort direction",
        "format": "int32"
      },
      "SortField": {
        "type": "object",
        "properties": {
          "Field": {
            "type": "string",
            "nullable": true
          },
          "Direction": {
            "$ref": "#/components/schemas/SortDirection"
          }
        },
        "additionalProperties": false,
        "description": "Sort field with direction"
      },
      "StatisticsGroup": {
        "type": "object",
        "properties": {
          "key": {
            "type": "string",
            "description": "The grouping key (camera name, rover name, or sol number as string)",
            "nullable": true
          },
          "count": {
            "type": "integer",
            "description": "Number of photos in this group",
            "format": "int32"
          },
          "percentage": {
            "type": "number",
            "description": "Percentage of total photos (0-100)",
            "format": "double",
            "nullable": true
          },
          "avg_per_sol": {
            "type": "number",
            "description": "Average photos per sol (only for rover grouping)",
            "format": "double",
            "nullable": true
          },
          "earth_date": {
            "type": "string",
            "description": "Earth date for this sol (only for sol grouping)",
            "nullable": true
          }
        },
        "additionalProperties": false,
        "description": "A single group in the statistics response"
      },
      "ValidationError": {
        "type": "object",
        "properties": {
          "field": {
            "type": "string",
            "description": "The field/parameter name that failed validation",
            "nullable": true
          },
          "value": {
            "description": "The invalid value that was provided",
            "nullable": true
          },
          "message": {
            "type": "string",
            "description": "A human-readable error message",
            "nullable": true
          },
          "example": {
            "type": "string",
            "description": "An example of a valid value",
            "nullable": true
          }
        },
        "additionalProperties": false,
        "description": "Field-level validation error details"
      }
    },
    "securitySchemes": {
      "ApiKey": {
        "type": "apiKey",
        "description": "API key authentication. Get your key from the dashboard after signing in.",
        "name": "X-API-Key",
        "in": "header"
      }
    }
  },
  "security": [
    {
      "ApiKey": []
    }
  ],
  "servers": [
    {
      "url": "https://api.marsvista.dev",
      "description": "Production API"
    }
  ]
}
