{
  "openapi": "3.1.0",
  "info": {
    "title": "Stratis Public API",
    "version": "1.2.0",
    "description": "Public machine and discovery API for Stratis spatial captures.\n\nCurrent live access model:\n- public discovery and retrieval for scenes, objects, and aerial captures\n- API key management for any signed-in Stratis user\n- API-key machine workflows for claim search, object retrieval, aerial retrieval, dataset manifests/exports, upload creation, commit, job polling, and billing visibility\n\nBilling uses API service credits. Credits are purchased separately from wallet custody and runtime calls spend only service credits.\n\nCurrent live charged operations:\n- `POST /apiSearchClaims`: 1 API credit deducted per request\n- `POST /apiCreateJob`: validates the caller has enough available API credits to afford base processing\n- `POST /apiCommitJob` and `POST /apiFinalizeUpload`: 1 API credit held when the submitted capture is public and allows training; 3 API credits held when the submitted capture is private or does not allow training\n\nCurrent operational limits:\n- claim search default limit: 1, maximum: 100\n- upload URL TTL: 1 hour\n- signed result URL TTL: 1 hour\n- signed source video URL TTL: 24 hours\n- maximum uploaded video duration: 10 minutes\n\nPublic discovery endpoints are currently free. Key management uses Firebase user auth. Machine-runtime usage uses API keys and paid actions require sufficient available API credits.\n\nProduct direction goes beyond the live machine endpoints today: Stratis is intended to support paid scene, object, aerial, marketplace, and dataset workflows. The live reference below documents only currently shipped endpoints."
  },
  "servers": [
    {
      "url": "https://us-central1-stratis-wc.cloudfunctions.net",
      "description": "Production Firebase Functions base URL"
    }
  ],
  "tags": [
    {
      "name": "Public Discovery",
      "description": "Public and semi-public retrieval endpoints for map data, captures, community assets, listings, and share links."
    },
    {
      "name": "API Keys",
      "description": "Authenticated user endpoints for creating, listing, and revoking Stratis API keys."
    },
    {
      "name": "Machine API",
      "description": "API-key authenticated machine workflow for claim search, object retrieval, aerial retrieval, dataset manifests/exports, upload creation, processing commit, and job polling."
    }
  ],
  "components": {
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "x-api-key",
        "description": "Primary machine auth. The backend also accepts `Authorization: Bearer <api-key>` and request-body `apiKey`, but `x-api-key` is the canonical public method."
      },
      "FirebaseBearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "Firebase ID token",
        "description": "User auth for dashboard-style endpoints such as API key management. Some discovery endpoints accept this optionally to personalize fields like `isOwn`."
      }
    },
    "schemas": {
      "ErrorResponse": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "description": "Human-readable error message.",
            "example": "Unauthorized"
          }
        },
        "required": [
          "error"
        ]
      },
      "ScanType": {
        "type": "string",
        "enum": [
          "scene",
          "object",
          "drone"
        ],
        "description": "Normalized capture type used across public responses."
      },
      "LatLng": {
        "type": "object",
        "properties": {
          "latitude": {
            "type": "number",
            "description": "Latitude in decimal degrees.",
            "example": 37.7749
          },
          "longitude": {
            "type": "number",
            "description": "Longitude in decimal degrees.",
            "example": -122.4194
          },
          "altitude": {
            "type": "number",
            "description": "Optional altitude in meters when available.",
            "nullable": true,
            "example": 42.5
          }
        },
        "required": [
          "latitude",
          "longitude"
        ]
      },
      "ApiKeySummary": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "API key document identifier.",
            "example": "gY0Yg4yW9d9mQx7b"
          },
          "name": {
            "type": "string",
            "description": "User-defined label.",
            "example": "Acme Mobile App"
          },
          "prefix": {
            "type": "string",
            "description": "Visible prefix for identifying the key without exposing the full secret.",
            "example": "sak_ab12"
          },
          "createdAt": {
            "type": "string",
            "description": "Creation timestamp in ISO-8601 UTC.",
            "nullable": true,
            "format": "date-time"
          },
          "lastUsedAt": {
            "type": "string",
            "description": "Most recent use timestamp in ISO-8601 UTC.",
            "nullable": true,
            "format": "date-time"
          },
          "revokedAt": {
            "type": "string",
            "description": "Revocation timestamp in ISO-8601 UTC.",
            "nullable": true,
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "name",
          "prefix"
        ]
      },
      "ApiKeyListResponse": {
        "type": "object",
        "properties": {
          "keys": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ApiKeySummary"
            }
          }
        },
        "required": [
          "keys"
        ]
      },
      "CreateApiKeyRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "Optional display name for the key.",
            "example": "Acme Mobile App"
          }
        }
      },
      "CreateApiKeyResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "description": "Whether the API key was created.",
            "example": true
          },
          "apiKeyId": {
            "type": "string",
            "description": "API key document identifier.",
            "example": "gY0Yg4yW9d9mQx7b"
          },
          "key": {
            "type": "string",
            "description": "The only time the full secret is returned. Store it securely.",
            "example": "sak_0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
          },
          "name": {
            "type": "string",
            "description": "Stored key name.",
            "example": "Acme Mobile App"
          },
          "prefix": {
            "type": "string",
            "description": "Visible key prefix.",
            "example": "sak_0123"
          }
        },
        "required": [
          "success",
          "apiKeyId",
          "key",
          "name",
          "prefix"
        ]
      },
      "RevokeApiKeyRequest": {
        "type": "object",
        "properties": {
          "apiKeyId": {
            "type": "string",
            "description": "API key document identifier to revoke.",
            "example": "gY0Yg4yW9d9mQx7b"
          }
        },
        "required": [
          "apiKeyId"
        ]
      },
      "SuccessResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "description": "Whether the operation succeeded.",
            "example": true
          }
        },
        "required": [
          "success"
        ]
      },
      "PublicMapCapture": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Capture identifier."
          },
          "name": {
            "type": "string",
            "description": "Display name.",
            "example": "Downtown Block 7"
          },
          "scanType": {
            "$ref": "#/components/schemas/ScanType"
          },
          "status": {
            "type": "string",
            "description": "Capture processing status.",
            "example": "completed"
          },
          "userId": {
            "type": "string",
            "description": "Owner user identifier when exposed.",
            "nullable": true
          },
          "videoUrl": {
            "type": "string",
            "description": "Original or public video URL when available.",
            "nullable": true,
            "format": "uri"
          },
          "resultUrl": {
            "type": "string",
            "description": "Primary renderable result URL when available.",
            "nullable": true,
            "format": "uri"
          },
          "progress": {
            "type": "object",
            "nullable": true,
            "additionalProperties": true,
            "description": "Opaque progress object for non-completed captures."
          },
          "centerPoint": {
            "$ref": "#/components/schemas/LatLng",
            "nullable": true
          },
          "claimStatus": {
            "type": "string",
            "description": "Claim state attached to the capture.",
            "example": "claimed"
          },
          "claimOwnerId": {
            "type": "string",
            "description": "Claim owner identifier when present.",
            "nullable": true
          },
          "source": {
            "type": "string",
            "description": "Origin of the capture such as app, claim, or api.",
            "nullable": true,
            "example": "claim"
          },
          "createdAt": {
            "type": "string",
            "description": "Creation timestamp in ISO-8601 UTC.",
            "nullable": true,
            "format": "date-time"
          },
          "drafts": {
            "type": "array",
            "nullable": true,
            "description": "Draft result variants when present.",
            "items": {
              "type": "object",
              "properties": {
                "version": {
                  "type": "string",
                  "description": "Model version.",
                  "nullable": true
                },
                "iteration": {
                  "type": "number",
                  "description": "Draft iteration number.",
                  "nullable": true
                },
                "resultUrl": {
                  "type": "string",
                  "description": "Draft result URL.",
                  "nullable": true,
                  "format": "uri"
                },
                "camerasUrl": {
                  "type": "string",
                  "description": "Draft camera bundle URL.",
                  "nullable": true,
                  "format": "uri"
                },
                "gaussianCount": {
                  "type": "number",
                  "description": "Draft gaussian count.",
                  "nullable": true
                }
              }
            }
          }
        },
        "required": [
          "id",
          "name",
          "scanType",
          "status",
          "claimStatus"
        ]
      },
      "PublicClaim": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Listing or claim response identifier."
          },
          "captureId": {
            "type": "string",
            "description": "Associated capture identifier."
          },
          "ownerId": {
            "type": "string",
            "description": "Claim owner user identifier.",
            "nullable": true
          },
          "ownerName": {
            "type": "string",
            "description": "Claim owner display name.",
            "nullable": true
          },
          "centerPoint": {
            "$ref": "#/components/schemas/LatLng",
            "nullable": true
          },
          "radiusM": {
            "type": "number",
            "description": "Claim radius in meters.",
            "example": 3.048
          },
          "claimH3Cell": {
            "type": "string",
            "description": "H3 cell identifier for the claim.",
            "nullable": true
          },
          "claimTileSystem": {
            "type": "string",
            "description": "Tile system used for claims.",
            "nullable": true,
            "example": "h3"
          },
          "claimTileResolution": {
            "type": "number",
            "description": "Claim tile resolution.",
            "nullable": true,
            "example": 12
          },
          "claimLayer": {
            "type": "string",
            "description": "Street or aerial claim layer when known.",
            "nullable": true,
            "enum": [
              "street",
              "aerial"
            ]
          },
          "status": {
            "type": "string",
            "description": "Claim status.",
            "example": "claimed"
          },
          "createdAt": {
            "type": "string",
            "description": "Creation/update timestamp in ISO-8601 UTC.",
            "nullable": true,
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "captureId",
          "radiusM",
          "status"
        ]
      },
      "PublicMapCluster": {
        "type": "object",
        "properties": {
          "cell": {
            "type": "string",
            "description": "Parent H3 cell for an aggregate cluster."
          },
          "resolution": {
            "type": "number",
            "description": "Aggregate H3 resolution.",
            "example": 9
          },
          "claimCount": {
            "type": "number",
            "description": "Number of visible claims in the cluster.",
            "example": 12
          },
          "captureCount": {
            "type": "number",
            "description": "Number of visible captures in the cluster.",
            "example": 8
          }
        },
        "required": [
          "cell",
          "resolution",
          "claimCount",
          "captureCount"
        ]
      },
      "PublicMapDataResponse": {
        "type": "object",
        "properties": {
          "captures": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PublicMapCapture"
            }
          },
          "claims": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PublicClaim"
            }
          },
          "clusters": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PublicMapCluster"
            },
            "description": "Aggregate clusters. Present for viewport queries that collapse dense results."
          }
        },
        "required": [
          "captures",
          "claims"
        ]
      },
      "CaptureDraft": {
        "type": "object",
        "properties": {
          "version": {
            "type": "string",
            "description": "Model version.",
            "nullable": true
          },
          "iteration": {
            "type": "number",
            "description": "Draft iteration number.",
            "nullable": true
          },
          "resultUrl": {
            "type": "string",
            "description": "Draft result URL.",
            "nullable": true,
            "format": "uri"
          },
          "camerasUrl": {
            "type": "string",
            "description": "Draft cameras URL.",
            "nullable": true,
            "format": "uri"
          },
          "gaussianCount": {
            "type": "number",
            "description": "Draft gaussian count.",
            "nullable": true
          }
        }
      },
      "ModelHistoryEntry": {
        "type": "object",
        "properties": {
          "version": {
            "type": "string",
            "description": "Model version.",
            "nullable": true
          },
          "resultUrl": {
            "type": "string",
            "description": "Historical result URL.",
            "nullable": true,
            "format": "uri"
          },
          "camerasUrl": {
            "type": "string",
            "description": "Historical cameras URL.",
            "nullable": true,
            "format": "uri"
          },
          "isolatedObjectPlyUrl": {
            "type": "string",
            "description": "Historical isolated object point cloud.",
            "nullable": true,
            "format": "uri"
          },
          "meshObjUrl": {
            "type": "string",
            "description": "Historical OBJ mesh export.",
            "nullable": true,
            "format": "uri"
          },
          "labelingJsonUrl": {
            "type": "string",
            "description": "Historical labeling JSON export.",
            "nullable": true,
            "format": "uri"
          },
          "objectLabels": {
            "type": "array",
            "nullable": true,
            "items": {
              "type": "string"
            },
            "description": "Object labels produced by object processing."
          },
          "objectProcessingStatus": {
            "type": "string",
            "description": "Object-processing state.",
            "nullable": true
          },
          "pipelineProfileName": {
            "type": "string",
            "description": "Pipeline profile used for the run.",
            "nullable": true
          },
          "processedAt": {
            "type": "string",
            "description": "Processing timestamp in ISO-8601 UTC.",
            "nullable": true,
            "format": "date-time"
          }
        }
      },
      "PublicCaptureResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Capture identifier."
          },
          "name": {
            "type": "string",
            "description": "Display name."
          },
          "scanType": {
            "$ref": "#/components/schemas/ScanType"
          },
          "status": {
            "type": "string",
            "description": "Capture processing status."
          },
          "resultUrl": {
            "type": "string",
            "description": "Primary result URL.",
            "nullable": true,
            "format": "uri"
          },
          "camerasUrl": {
            "type": "string",
            "description": "Camera export URL.",
            "nullable": true,
            "format": "uri"
          },
          "isolatedObjectPlyUrl": {
            "type": "string",
            "description": "Object-isolation point cloud URL.",
            "nullable": true,
            "format": "uri"
          },
          "meshObjUrl": {
            "type": "string",
            "description": "Object mesh OBJ URL.",
            "nullable": true,
            "format": "uri"
          },
          "labelingJsonUrl": {
            "type": "string",
            "description": "Object labeling JSON URL.",
            "nullable": true,
            "format": "uri"
          },
          "objectLabels": {
            "type": "array",
            "nullable": true,
            "items": {
              "type": "string"
            },
            "description": "Normalized labels extracted for isolated objects."
          },
          "objectProcessingStatus": {
            "type": "string",
            "description": "Status of the object-processing stage.",
            "nullable": true
          },
          "arDataUrl": {
            "type": "string",
            "description": "AR-oriented export when available.",
            "nullable": true,
            "format": "uri"
          },
          "gaussianCount": {
            "type": "number",
            "description": "Gaussian count for splat outputs.",
            "nullable": true
          },
          "drafts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CaptureDraft"
            }
          },
          "pinnedModelVersion": {
            "type": "string",
            "description": "Pinned preferred model version.",
            "nullable": true
          },
          "modelHistory": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ModelHistoryEntry"
            }
          },
          "gravityVector": {
            "type": "object",
            "nullable": true,
            "additionalProperties": true,
            "description": "Raw gravity vector payload from processing."
          },
          "orientationAdjustment": {
            "type": "object",
            "nullable": true,
            "additionalProperties": true,
            "description": "Orientation adjustment payload used by the viewer."
          },
          "defaultView": {
            "type": "object",
            "nullable": true,
            "additionalProperties": true,
            "description": "Viewer camera defaults when available."
          },
          "centerPoint": {
            "$ref": "#/components/schemas/LatLng",
            "nullable": true
          },
          "createdAt": {
            "type": "string",
            "description": "Creation timestamp in ISO-8601 UTC.",
            "nullable": true,
            "format": "date-time"
          },
          "processedAt": {
            "type": "string",
            "description": "Processing timestamp in ISO-8601 UTC.",
            "nullable": true,
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "name",
          "scanType",
          "status",
          "drafts",
          "modelHistory"
        ]
      },
      "CommunityCapture": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Capture identifier."
          },
          "name": {
            "type": "string",
            "description": "Display name."
          },
          "scanType": {
            "$ref": "#/components/schemas/ScanType"
          },
          "status": {
            "type": "string",
            "description": "Capture status.",
            "example": "completed"
          },
          "srs": {
            "type": "number",
            "description": "Primary quality score.",
            "nullable": true
          },
          "gaussianCount": {
            "type": "number",
            "description": "Gaussian count for splat outputs.",
            "nullable": true
          },
          "resultUrl": {
            "type": "string",
            "description": "Renderable result URL.",
            "nullable": true,
            "format": "uri"
          },
          "videoUrl": {
            "type": "string",
            "description": "Video URL or signed URL when available.",
            "nullable": true,
            "format": "uri"
          },
          "renderVideoUrl": {
            "type": "string",
            "description": "Rendered comparison video URL.",
            "nullable": true,
            "format": "uri"
          },
          "thumbnailVideoUrl": {
            "type": "string",
            "description": "Thumbnail video URL.",
            "nullable": true,
            "format": "uri"
          },
          "compareVideoUrl": {
            "type": "string",
            "description": "Compare video URL.",
            "nullable": true,
            "format": "uri"
          },
          "centerPoint": {
            "$ref": "#/components/schemas/LatLng",
            "nullable": true
          },
          "userId": {
            "type": "string",
            "description": "Owner identifier.",
            "nullable": true
          },
          "isOwn": {
            "type": "boolean",
            "description": "True when the optional caller bearer token matches the capture owner."
          },
          "createdAt": {
            "type": "string",
            "description": "Creation timestamp in ISO-8601 UTC.",
            "nullable": true,
            "format": "date-time"
          },
          "processedAt": {
            "type": "string",
            "description": "Processing timestamp in ISO-8601 UTC.",
            "nullable": true,
            "format": "date-time"
          },
          "pinnedModelVersion": {
            "type": "string",
            "description": "Pinned model version.",
            "nullable": true
          },
          "durationSeconds": {
            "type": "number",
            "description": "Video duration in seconds.",
            "nullable": true
          },
          "isolatedObjectPlyUrl": {
            "type": "string",
            "description": "Object-isolation point cloud URL.",
            "nullable": true,
            "format": "uri"
          },
          "meshObjUrl": {
            "type": "string",
            "description": "Object mesh OBJ URL.",
            "nullable": true,
            "format": "uri"
          },
          "labelingJsonUrl": {
            "type": "string",
            "description": "Object labeling JSON URL.",
            "nullable": true,
            "format": "uri"
          }
        },
        "required": [
          "id",
          "name",
          "scanType",
          "status",
          "isOwn"
        ]
      },
      "CommunityCapturesResponse": {
        "type": "object",
        "properties": {
          "captures": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CommunityCapture"
            }
          },
          "nextCursor": {
            "type": "string",
            "description": "Pagination cursor for the next page.",
            "nullable": true
          }
        },
        "required": [
          "captures",
          "nextCursor"
        ]
      },
      "ShareLinkResponse": {
        "type": "object",
        "properties": {
          "captureId": {
            "type": "string",
            "description": "Associated capture identifier."
          },
          "code": {
            "type": "string",
            "description": "Base58 short code.",
            "example": "8FmH2Q"
          },
          "shortUrl": {
            "type": "string",
            "description": "Short share URL.",
            "format": "uri"
          },
          "captureName": {
            "type": "string",
            "description": "Capture name when resolving a share code.",
            "nullable": true
          },
          "status": {
            "type": "string",
            "description": "Capture status when resolving a share code.",
            "nullable": true
          },
          "viewerUrl": {
            "type": "string",
            "description": "Resolved viewer URL when resolving a share code.",
            "nullable": true,
            "format": "uri"
          }
        },
        "required": [
          "captureId",
          "code",
          "shortUrl"
        ]
      },
      "Location": {
        "type": "object",
        "properties": {
          "city": {
            "type": "string",
            "description": "City.",
            "nullable": true
          },
          "state": {
            "type": "string",
            "description": "State or region.",
            "nullable": true
          },
          "country": {
            "type": "string",
            "description": "Country.",
            "nullable": true
          }
        }
      },
      "ClaimListing": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Listing identifier."
          },
          "claimId": {
            "type": "string",
            "description": "Claim identifier."
          },
          "sellerId": {
            "type": "string",
            "description": "Seller user identifier."
          },
          "sellerName": {
            "type": "string",
            "description": "Seller display name.",
            "nullable": true
          },
          "price": {
            "type": "number",
            "description": "Listing price in ECKO.",
            "example": 250
          },
          "title": {
            "type": "string",
            "description": "Listing title."
          },
          "notes": {
            "type": "string",
            "description": "Optional listing notes.",
            "nullable": true
          },
          "status": {
            "type": "string",
            "description": "Listing status.",
            "example": "active"
          },
          "createdAt": {
            "type": "string",
            "description": "Creation timestamp in ISO-8601 UTC.",
            "nullable": true,
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "description": "Update timestamp in ISO-8601 UTC.",
            "nullable": true,
            "format": "date-time"
          },
          "captureName": {
            "type": "string",
            "description": "Associated capture name.",
            "nullable": true
          },
          "srs": {
            "type": "number",
            "description": "Primary quality score.",
            "nullable": true
          },
          "gaussianCount": {
            "type": "number",
            "description": "Gaussian count.",
            "nullable": true
          },
          "centerPoint": {
            "$ref": "#/components/schemas/LatLng",
            "nullable": true
          },
          "location": {
            "$ref": "#/components/schemas/Location"
          }
        },
        "required": [
          "id",
          "claimId",
          "sellerId",
          "price",
          "title",
          "status",
          "location"
        ]
      },
      "ClaimListingsResponse": {
        "type": "object",
        "properties": {
          "listings": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ClaimListing"
            }
          },
          "nextCursor": {
            "type": "string",
            "description": "Cursor for the next page.",
            "nullable": true
          },
          "indexBuilding": {
            "type": "boolean",
            "description": "Present and true when Firestore indexes are still building.",
            "nullable": true
          },
          "message": {
            "type": "string",
            "description": "Human-readable status message.",
            "nullable": true
          }
        },
        "required": [
          "listings",
          "nextCursor"
        ]
      },
      "ClaimResult": {
        "type": "object",
        "properties": {
          "captureId": {
            "type": "string",
            "description": "Capture identifier."
          },
          "claimOwnerId": {
            "type": "string",
            "description": "Claim owner user identifier.",
            "nullable": true
          },
          "claimRadiusM": {
            "type": "number",
            "description": "Claim radius in meters.",
            "example": 3.048
          },
          "claimH3Cell": {
            "type": "string",
            "description": "Claim H3 cell.",
            "nullable": true
          },
          "claimTileSystem": {
            "type": "string",
            "description": "Claim tile system.",
            "nullable": true,
            "example": "h3"
          },
          "claimTileResolution": {
            "type": "number",
            "description": "Claim tile resolution.",
            "nullable": true,
            "example": 12
          },
          "claimStatus": {
            "type": "string",
            "description": "Claim status.",
            "example": "claimed"
          },
          "centerPoint": {
            "$ref": "#/components/schemas/LatLng",
            "nullable": true
          },
          "distanceM": {
            "type": "number",
            "description": "Distance from requested point in meters.",
            "nullable": true
          },
          "plyUrl": {
            "type": "string",
            "description": "Legacy point cloud URL when available.",
            "nullable": true,
            "format": "uri"
          },
          "videoUrl": {
            "type": "string",
            "description": "Video URL when available.",
            "nullable": true,
            "format": "uri"
          },
          "srs": {
            "type": "number",
            "description": "Primary quality score.",
            "nullable": true
          },
          "gaussianCount": {
            "type": "number",
            "description": "Gaussian count.",
            "nullable": true
          },
          "captureName": {
            "type": "string",
            "description": "Capture display name.",
            "nullable": true
          },
          "viewerUrl": {
            "type": "string",
            "description": "Stratis viewer URL.",
            "format": "uri"
          },
          "updatedAt": {
            "type": "string",
            "description": "Last update timestamp in ISO-8601 UTC.",
            "nullable": true,
            "format": "date-time"
          }
        },
        "required": [
          "captureId",
          "claimRadiusM",
          "claimStatus",
          "viewerUrl"
        ]
      },
      "ApiSearchClaimsRequest": {
        "type": "object",
        "properties": {
          "lat": {
            "type": "number",
            "description": "Latitude in decimal degrees.",
            "example": 37.7749
          },
          "lng": {
            "type": "number",
            "description": "Longitude in decimal degrees.",
            "example": -122.4194
          },
          "distanceM": {
            "type": "number",
            "description": "Optional max search distance in meters.",
            "nullable": true,
            "example": 1000
          },
          "limit": {
            "type": "number",
            "description": "Optional number of results. Default 1, maximum 100.",
            "nullable": true,
            "example": 5
          }
        },
        "required": [
          "lat",
          "lng"
        ]
      },
      "ApiSearchClaimsResponse": {
        "type": "object",
        "properties": {
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ClaimResult"
            }
          },
          "limit": {
            "type": "number",
            "description": "Applied result limit.",
            "example": 5
          },
          "distanceM": {
            "type": "number",
            "description": "Applied search distance in meters, if any.",
            "nullable": true
          },
          "count": {
            "type": "number",
            "description": "Returned result count.",
            "example": 3
          }
        },
        "required": [
          "results",
          "limit",
          "count"
        ]
      },
      "ApiCreateJobRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "Optional human-readable capture name.",
            "example": "Warehouse Aisle 3"
          }
        }
      },
      "ApiCreateJobResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "description": "Whether the upload job was created.",
            "example": true
          },
          "jobId": {
            "type": "string",
            "description": "Capture/job identifier."
          },
          "uploadUrl": {
            "type": "string",
            "description": "Signed V4 upload URL for a `video/mp4` file.",
            "format": "uri"
          },
          "uploadExpiresAt": {
            "type": "string",
            "description": "Upload URL expiration timestamp in ISO-8601 UTC.",
            "format": "date-time"
          },
          "storagePath": {
            "type": "string",
            "description": "Internal storage path reserved for the upload."
          }
        },
        "required": [
          "success",
          "jobId",
          "uploadUrl",
          "uploadExpiresAt",
          "storagePath"
        ]
      },
      "ApiCapturePolicy": {
        "type": "object",
        "description": "Capture visibility and training policy used for API processing pricing. Public captures that allow training use the base processing rate. Private captures or captures that do not allow training use the private processing rate.",
        "properties": {
          "visibility": {
            "type": "string",
            "enum": [
              "public",
              "private"
            ],
            "description": "Preferred visibility. `public` maps to hidden=false; `private` maps to hidden=true.",
            "example": "public"
          },
          "public": {
            "type": "boolean",
            "description": "Alias for visibility=public.",
            "example": true
          },
          "hidden": {
            "type": "boolean",
            "description": "Direct hidden flag. When true, the private/no-training pricing tier is used.",
            "example": false
          },
          "trainingConsent": {
            "type": "boolean",
            "description": "Whether Stratis may use the capture and derived data for training.",
            "example": true
          },
          "allowTraining": {
            "type": "boolean",
            "description": "Alias for trainingConsent.",
            "example": true
          }
        }
      },
      "ApiCommitJobRequest": {
        "type": "object",
        "properties": {
          "jobId": {
            "type": "string",
            "description": "Previously created job identifier."
          },
          "durationSeconds": {
            "type": "number",
            "description": "Video duration in seconds. Maximum 600.",
            "example": 42.3
          },
          "name": {
            "type": "string",
            "description": "Optional updated capture name.",
            "nullable": true,
            "example": "Warehouse Aisle 3"
          },
          "centerPoint": {
            "$ref": "#/components/schemas/LatLng",
            "nullable": true
          },
          "capturePolicy": {
            "$ref": "#/components/schemas/ApiCapturePolicy",
            "description": "Optional capture policy. If omitted, Stratis uses the conservative private/no-training policy and charges the private processing rate."
          }
        },
        "required": [
          "jobId",
          "durationSeconds"
        ]
      },
      "ApiCommitJobResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "description": "Whether the job commit was accepted.",
            "example": true
          },
          "jobId": {
            "type": "string",
            "description": "Committed job identifier."
          },
          "status": {
            "type": "string",
            "description": "Job status after commit.",
            "example": "queued"
          },
          "alreadyCommitted": {
            "type": "boolean",
            "description": "Present and true when the job had already been committed earlier.",
            "nullable": true
          },
          "apiCreditHoldAmount": {
            "type": "number",
            "description": "Service credits reserved for this capture processing job.",
            "nullable": true,
            "example": 1
          },
          "apiCreditPricingTier": {
            "type": "string",
            "enum": [
              "public_training",
              "private_or_no_training"
            ],
            "description": "Pricing tier used for the processing hold.",
            "nullable": true
          }
        },
        "required": [
          "success",
          "jobId",
          "status"
        ]
      },
      "JobStatus": {
        "type": "object",
        "properties": {
          "jobId": {
            "type": "string",
            "description": "Job identifier."
          },
          "status": {
            "type": "string",
            "description": "Current job status.",
            "example": "completed"
          },
          "progress": {
            "type": "object",
            "nullable": true,
            "additionalProperties": true,
            "description": "Opaque progress payload reported by the worker pipeline."
          },
          "captureName": {
            "type": "string",
            "description": "Capture name.",
            "nullable": true
          },
          "durationSeconds": {
            "type": "number",
            "description": "Video duration in seconds.",
            "nullable": true
          },
          "resultUrl": {
            "type": "string",
            "description": "Primary viewer/result URL when available.",
            "nullable": true,
            "format": "uri"
          },
          "downloadUrl": {
            "type": "string",
            "description": "Signed download URL for the archived result bundle.",
            "nullable": true,
            "format": "uri"
          },
          "camerasUrl": {
            "type": "string",
            "description": "Signed download URL for the cameras bundle.",
            "nullable": true,
            "format": "uri"
          },
          "viewerUrl": {
            "type": "string",
            "description": "Viewer URL for the capture.",
            "format": "uri"
          },
          "srs": {
            "type": "number",
            "description": "Primary quality score.",
            "nullable": true
          },
          "ssim": {
            "type": "number",
            "description": "SSIM metric when available.",
            "nullable": true
          },
          "lpips": {
            "type": "number",
            "description": "LPIPS metric when available.",
            "nullable": true
          },
          "processedAt": {
            "type": "string",
            "description": "Processing completion timestamp in ISO-8601 UTC.",
            "nullable": true,
            "format": "date-time"
          },
          "apiResultExpiresAt": {
            "type": "string",
            "description": "Stored result expiration timestamp in ISO-8601 UTC.",
            "nullable": true,
            "format": "date-time"
          },
          "expired": {
            "type": "boolean",
            "description": "Whether the stored API result bundle has expired."
          }
        },
        "required": [
          "jobId",
          "status",
          "viewerUrl",
          "expired"
        ]
      },
      "ApiBalanceResponse": {
        "type": "object",
        "properties": {
          "apiAccountId": {
            "type": "string",
            "description": "API service-credit account charged by this key.",
            "example": "user_abc123"
          },
          "creditBalance": {
            "type": "number",
            "description": "Total service-credit balance on the API account.",
            "example": 12.5
          },
          "creditHeld": {
            "type": "number",
            "description": "Service credits reserved for pending API operations.",
            "example": 1
          },
          "availableCredits": {
            "type": "number",
            "description": "Spendable service credits, effectively `creditBalance - creditHeld`.",
            "example": 11.5
          },
          "apiSearchCost": {
            "type": "number",
            "description": "Current cost of `POST /apiSearchClaims` in service credits.",
            "example": 1
          },
          "apiProcessCost": {
            "type": "number",
            "description": "Base processing hold amount in service credits for public captures that allow training.",
            "example": 1
          },
          "apiPublicTrainingProcessCost": {
            "type": "number",
            "description": "Processing hold amount for captures submitted as public and training-allowed.",
            "example": 1
          },
          "apiPrivateProcessCost": {
            "type": "number",
            "description": "Processing hold amount for captures that are private or not training-allowed.",
            "example": 3
          },
          "apiPrivateProcessMultiplier": {
            "type": "number",
            "description": "Multiplier applied to the base processing rate when the capture is private or not training-allowed.",
            "example": 3
          },
          "apiDatasetExportBaseCost": {
            "type": "number",
            "description": "Current base cost of creating a dataset export in service credits before per-asset charges.",
            "example": 5
          },
          "apiKeyId": {
            "type": "string",
            "description": "Resolved API key identifier.",
            "example": "gY0Yg4yW9d9mQx7b"
          },
          "apiKeyName": {
            "type": "string",
            "nullable": true,
            "description": "Resolved API key name.",
            "example": "Acme Mobile App"
          },
          "apiKeyLastUsedAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Timestamp at which the API key was last touched by this endpoint."
          }
        },
        "required": [
          "apiAccountId",
          "creditBalance",
          "creditHeld",
          "availableCredits",
          "apiSearchCost",
          "apiProcessCost",
          "apiPublicTrainingProcessCost",
          "apiPrivateProcessCost",
          "apiPrivateProcessMultiplier",
          "apiDatasetExportBaseCost",
          "apiKeyId"
        ]
      },
      "ApiUsageTransaction": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "API credit ledger transaction identifier."
          },
          "type": {
            "type": "string",
            "enum": [
              "purchase",
              "hold",
              "spend",
              "hold_release",
              "adjustment"
            ],
            "description": "Underlying API credit ledger transaction type."
          },
          "category": {
            "type": "string",
            "enum": [
              "credit_purchase",
              "claim_search",
              "processing_hold",
              "processing_spend",
              "processing_hold_release",
              "dataset_export"
            ],
            "description": "Normalized API billing category."
          },
          "amount": {
            "type": "number",
            "description": "Amount in API service credits.",
            "example": 1
          },
          "balanceAfter": {
            "type": "number",
            "description": "Balance after the transaction was recorded.",
            "example": 11.5
          },
          "heldAfter": {
            "type": "number",
            "description": "Held amount after the transaction was recorded.",
            "example": 1
          },
          "memo": {
            "type": "string",
            "description": "Ledger memo stored with the transaction."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Transaction timestamp in ISO-8601 UTC."
          },
          "jobId": {
            "type": "string",
            "nullable": true,
            "description": "Associated job identifier when available."
          },
          "captureId": {
            "type": "string",
            "nullable": true,
            "description": "Associated capture identifier when resolvable."
          },
          "captureName": {
            "type": "string",
            "nullable": true,
            "description": "Associated capture name when resolvable."
          },
          "jobStatus": {
            "type": "string",
            "nullable": true,
            "description": "Resolved job status when the endpoint can hydrate it."
          },
          "amountCredits": {
            "type": "number",
            "description": "Amount in API service credits.",
            "example": 1
          },
          "source": {
            "type": "string",
            "description": "Ledger source, such as `api_runtime` or `legacy_ecko_balance`.",
            "example": "api_runtime"
          }
        },
        "required": [
          "id",
          "type",
          "category",
          "amount",
          "amountCredits",
          "balanceAfter",
          "heldAfter",
          "memo",
          "source"
        ]
      },
      "ApiUsageSummary": {
        "type": "object",
        "properties": {
          "spends": {
            "type": "number",
            "description": "Number of spend transactions in the returned page.",
            "example": 2
          },
          "holds": {
            "type": "number",
            "description": "Number of hold transactions in the returned page.",
            "example": 1
          },
          "holdReleases": {
            "type": "number",
            "description": "Number of hold-release transactions in the returned page.",
            "example": 1
          },
          "grossSpend": {
            "type": "number",
            "description": "Sum of spend amounts in the returned page.",
            "example": 2
          },
          "grossHold": {
            "type": "number",
            "description": "Sum of hold amounts in the returned page.",
            "example": 1
          },
          "grossHoldRelease": {
            "type": "number",
            "description": "Sum of hold-release amounts in the returned page.",
            "example": 1
          }
        },
        "required": [
          "spends",
          "holds",
          "holdReleases",
          "grossSpend",
          "grossHold",
          "grossHoldRelease"
        ]
      },
      "ApiUsageResponse": {
        "type": "object",
        "properties": {
          "transactions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ApiUsageTransaction"
            }
          },
          "limit": {
            "type": "number",
            "description": "Applied page limit.",
            "example": 25
          },
          "count": {
            "type": "number",
            "description": "Returned transaction count.",
            "example": 3
          },
          "summary": {
            "$ref": "#/components/schemas/ApiUsageSummary"
          }
        },
        "required": [
          "transactions",
          "limit",
          "count",
          "summary"
        ]
      },
      "ApiObjectSummary": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Object capture identifier."
          },
          "name": {
            "type": "string",
            "description": "Display name for the object capture."
          },
          "scanType": {
            "$ref": "#/components/schemas/ScanType"
          },
          "status": {
            "type": "string",
            "description": "Capture status."
          },
          "resultUrl": {
            "type": "string",
            "nullable": true,
            "format": "uri",
            "description": "Primary splat result URL."
          },
          "isolatedObjectPlyUrl": {
            "type": "string",
            "nullable": true,
            "format": "uri",
            "description": "Isolated object point-cloud URL."
          },
          "meshObjUrl": {
            "type": "string",
            "nullable": true,
            "format": "uri",
            "description": "OBJ mesh URL."
          },
          "labelingJsonUrl": {
            "type": "string",
            "nullable": true,
            "format": "uri",
            "description": "Object labeling JSON URL."
          },
          "objectLabels": {
            "type": "object",
            "nullable": true,
            "additionalProperties": true,
            "description": "Raw object labeling payload produced by the pipeline."
          },
          "objectProcessingStatus": {
            "type": "string",
            "nullable": true,
            "description": "Object-processing stage status."
          },
          "srs": {
            "type": "number",
            "nullable": true,
            "description": "Primary quality score."
          },
          "gaussianCount": {
            "type": "number",
            "nullable": true,
            "description": "Gaussian count for splat outputs."
          },
          "centerPoint": {
            "$ref": "#/components/schemas/LatLng",
            "nullable": true
          },
          "createdAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          },
          "processedAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          },
          "pinnedModelVersion": {
            "type": "string",
            "nullable": true,
            "description": "Pinned model version or identifier."
          },
          "hasSplat": {
            "type": "boolean",
            "description": "Whether a splat result URL is present."
          },
          "hasIsolatedPointCloud": {
            "type": "boolean",
            "description": "Whether an isolated point cloud URL is present."
          },
          "hasMesh": {
            "type": "boolean",
            "description": "Whether a mesh OBJ URL is present."
          },
          "hasLabeling": {
            "type": "boolean",
            "description": "Whether a labeling JSON URL is present."
          },
          "viewerUrl": {
            "type": "string",
            "format": "uri",
            "description": "Viewer URL for the capture."
          }
        },
        "required": [
          "id",
          "name",
          "scanType",
          "status",
          "hasSplat",
          "hasIsolatedPointCloud",
          "hasMesh",
          "hasLabeling",
          "viewerUrl"
        ]
      },
      "ApiObjectDetail": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "scanType": {
            "$ref": "#/components/schemas/ScanType"
          },
          "status": {
            "type": "string"
          },
          "resultUrl": {
            "type": "string",
            "nullable": true,
            "format": "uri"
          },
          "isolatedObjectPlyUrl": {
            "type": "string",
            "nullable": true,
            "format": "uri"
          },
          "meshObjUrl": {
            "type": "string",
            "nullable": true,
            "format": "uri"
          },
          "labelingJsonUrl": {
            "type": "string",
            "nullable": true,
            "format": "uri"
          },
          "camerasUrl": {
            "type": "string",
            "nullable": true,
            "format": "uri"
          },
          "arDataUrl": {
            "type": "string",
            "nullable": true,
            "format": "uri"
          },
          "objectLabels": {
            "type": "object",
            "nullable": true,
            "additionalProperties": true
          },
          "objectProcessingStatus": {
            "type": "string",
            "nullable": true
          },
          "srs": {
            "type": "number",
            "nullable": true
          },
          "gaussianCount": {
            "type": "number",
            "nullable": true
          },
          "centerPoint": {
            "$ref": "#/components/schemas/LatLng",
            "nullable": true
          },
          "createdAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          },
          "processedAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          },
          "pinnedModelVersion": {
            "type": "string",
            "nullable": true
          },
          "hasSplat": {
            "type": "boolean"
          },
          "hasIsolatedPointCloud": {
            "type": "boolean"
          },
          "hasMesh": {
            "type": "boolean"
          },
          "hasLabeling": {
            "type": "boolean"
          },
          "viewerUrl": {
            "type": "string",
            "format": "uri"
          },
          "drafts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CaptureDraft"
            }
          },
          "modelHistory": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ModelHistoryEntry"
            }
          },
          "gravityVector": {
            "type": "object",
            "nullable": true,
            "additionalProperties": true
          },
          "orientationAdjustment": {
            "type": "object",
            "nullable": true,
            "additionalProperties": true
          },
          "defaultView": {
            "type": "object",
            "nullable": true,
            "additionalProperties": true
          }
        },
        "required": [
          "id",
          "name",
          "scanType",
          "status",
          "hasSplat",
          "hasIsolatedPointCloud",
          "hasMesh",
          "hasLabeling",
          "viewerUrl",
          "drafts",
          "modelHistory"
        ]
      },
      "ApiObjectSearchResponse": {
        "type": "object",
        "properties": {
          "objects": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ApiObjectSummary"
            }
          },
          "query": {
            "type": "string",
            "nullable": true,
            "description": "Applied free-text or label query."
          },
          "limit": {
            "type": "number",
            "description": "Applied page limit.",
            "example": 20
          },
          "count": {
            "type": "number",
            "description": "Returned object count.",
            "example": 2
          },
          "nextCursor": {
            "type": "string",
            "nullable": true,
            "description": "Cursor for the next page."
          }
        },
        "required": [
          "objects",
          "limit",
          "count"
        ]
      },
      "ApiSearchBounds": {
        "type": "object",
        "properties": {
          "south": {
            "type": "number"
          },
          "west": {
            "type": "number"
          },
          "north": {
            "type": "number"
          },
          "east": {
            "type": "number"
          }
        },
        "required": [
          "south",
          "west",
          "north",
          "east"
        ]
      },
      "ApiAerialGpsPoint": {
        "type": "object",
        "properties": {
          "latitude": {
            "type": "number",
            "nullable": true,
            "description": "Latitude in decimal degrees."
          },
          "longitude": {
            "type": "number",
            "nullable": true,
            "description": "Longitude in decimal degrees."
          },
          "altitude": {
            "type": "number",
            "nullable": true,
            "description": "Altitude in meters when available."
          },
          "timestamp": {
            "oneOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Original timestamp value when present."
          }
        }
      },
      "ApiAerialHistoryEntry": {
        "type": "object",
        "properties": {
          "version": {
            "type": "string",
            "nullable": true,
            "description": "Model version."
          },
          "resultUrl": {
            "type": "string",
            "nullable": true,
            "format": "uri",
            "description": "Historical splat URL."
          },
          "camerasUrl": {
            "type": "string",
            "nullable": true,
            "format": "uri",
            "description": "Historical cameras URL."
          },
          "renderVideoUrl": {
            "type": "string",
            "nullable": true,
            "format": "uri",
            "description": "Historical render preview URL."
          },
          "pipelineProfileName": {
            "type": "string",
            "nullable": true,
            "description": "Pipeline profile used for the run."
          },
          "processedAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time",
            "description": "Processing timestamp in ISO-8601 UTC."
          }
        }
      },
      "ApiAerialSummary": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Aerial capture identifier."
          },
          "name": {
            "type": "string",
            "description": "Display name for the aerial capture."
          },
          "scanType": {
            "$ref": "#/components/schemas/ScanType"
          },
          "status": {
            "type": "string",
            "description": "Capture status."
          },
          "resultUrl": {
            "type": "string",
            "nullable": true,
            "format": "uri",
            "description": "Primary splat result URL."
          },
          "renderVideoUrl": {
            "type": "string",
            "nullable": true,
            "format": "uri",
            "description": "Rendered preview video URL."
          },
          "thumbnailVideoUrl": {
            "type": "string",
            "nullable": true,
            "format": "uri",
            "description": "Thumbnail preview video URL."
          },
          "compareVideoUrl": {
            "type": "string",
            "nullable": true,
            "format": "uri",
            "description": "Comparison/source preview video URL."
          },
          "srs": {
            "type": "number",
            "nullable": true,
            "description": "Primary quality score."
          },
          "gaussianCount": {
            "type": "number",
            "nullable": true,
            "description": "Gaussian count for splat outputs."
          },
          "durationSeconds": {
            "type": "number",
            "nullable": true,
            "description": "Capture duration in seconds."
          },
          "centerPoint": {
            "$ref": "#/components/schemas/LatLng",
            "nullable": true
          },
          "claimStatus": {
            "type": "string",
            "nullable": true,
            "description": "Current claim status when present."
          },
          "claimOwnerId": {
            "type": "string",
            "nullable": true,
            "description": "Current claim owner ID when present."
          },
          "claimH3Cell": {
            "type": "string",
            "nullable": true,
            "description": "Associated aerial H3 cell when present."
          },
          "claimTileSystem": {
            "type": "string",
            "description": "Spatial tiling system used for aerial claims."
          },
          "claimTileResolution": {
            "type": "integer",
            "description": "Tile resolution used for aerial claims."
          },
          "createdAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          },
          "processedAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          },
          "pinnedModelVersion": {
            "type": "string",
            "nullable": true,
            "description": "Pinned model version or identifier."
          },
          "gpsTrackPointCount": {
            "type": "integer",
            "description": "Number of GPS track points currently attached to the capture."
          },
          "videoPartsCount": {
            "type": "integer",
            "description": "Number of multipart source-video segments when present."
          },
          "hasSplat": {
            "type": "boolean",
            "description": "Whether a splat result URL is present."
          },
          "hasRenderPreview": {
            "type": "boolean",
            "description": "Whether a render preview URL is present."
          },
          "hasGpsTrack": {
            "type": "boolean",
            "description": "Whether GPS track points are present."
          },
          "hasMultipartVideo": {
            "type": "boolean",
            "description": "Whether multipart source video segments are present."
          },
          "viewerUrl": {
            "type": "string",
            "format": "uri",
            "description": "Viewer URL for the aerial capture."
          }
        },
        "required": [
          "id",
          "name",
          "scanType",
          "status",
          "claimTileSystem",
          "claimTileResolution",
          "gpsTrackPointCount",
          "videoPartsCount",
          "hasSplat",
          "hasRenderPreview",
          "hasGpsTrack",
          "hasMultipartVideo",
          "viewerUrl"
        ]
      },
      "ApiAerialDetail": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ApiAerialSummary"
          },
          {
            "type": "object",
            "properties": {
              "videoUrl": {
                "type": "string",
                "nullable": true,
                "format": "uri",
                "description": "Primary source or signed video URL when available."
              },
              "camerasUrl": {
                "type": "string",
                "nullable": true,
                "format": "uri",
                "description": "Camera metadata URL."
              },
              "gpsTrack": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/ApiAerialGpsPoint"
                },
                "description": "GPS track points when available."
              },
              "drafts": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/CaptureDraft"
                },
                "description": "Draft model outputs."
              },
              "modelHistory": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/ApiAerialHistoryEntry"
                },
                "description": "Historical aerial model runs."
              },
              "defaultView": {
                "type": "object",
                "nullable": true,
                "additionalProperties": true,
                "description": "Default viewer camera/view payload when present."
              }
            }
          }
        ]
      },
      "ApiAerialSearchResponse": {
        "type": "object",
        "properties": {
          "captures": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ApiAerialSummary"
            }
          },
          "query": {
            "type": "string",
            "nullable": true,
            "description": "Free-text search query if provided."
          },
          "limit": {
            "type": "integer",
            "description": "Maximum number of results requested."
          },
          "count": {
            "type": "integer",
            "description": "Number of captures returned."
          },
          "nextCursor": {
            "type": "string",
            "nullable": true,
            "description": "Pagination cursor for the next page."
          },
          "bounds": {
            "$ref": "#/components/schemas/ApiSearchBounds",
            "nullable": true
          }
        },
        "required": [
          "captures",
          "limit",
          "count"
        ]
      },
      "DatasetAssetType": {
        "type": "string",
        "enum": [
          "metadata",
          "viewer",
          "splat",
          "cameras",
          "mesh",
          "labeling",
          "isolatedPointCloud",
          "renderVideo",
          "thumbnailVideo",
          "compareVideo",
          "gpsTrack"
        ],
        "description": "Selectable asset classes for dataset exports."
      },
      "DatasetManifestItem": {
        "type": "object",
        "properties": {
          "captureId": {
            "type": "string",
            "description": "Capture identifier."
          },
          "name": {
            "type": "string",
            "description": "Display name for the capture."
          },
          "scanType": {
            "$ref": "#/components/schemas/ScanType"
          },
          "status": {
            "type": "string",
            "description": "Capture status."
          },
          "srs": {
            "type": "number",
            "nullable": true,
            "description": "Primary quality score."
          },
          "gaussianCount": {
            "type": "number",
            "nullable": true,
            "description": "Gaussian count for splat outputs."
          },
          "centerPoint": {
            "$ref": "#/components/schemas/LatLng",
            "nullable": true
          },
          "createdAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          },
          "processedAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          },
          "claimStatus": {
            "type": "string",
            "nullable": true,
            "description": "Claim status when present."
          },
          "objectLabels": {
            "type": "object",
            "nullable": true,
            "additionalProperties": true,
            "description": "Object labeling payload when present."
          },
          "objectProcessingStatus": {
            "type": "string",
            "nullable": true,
            "description": "Object-processing stage status when present."
          },
          "gpsTrackPointCount": {
            "type": "integer",
            "description": "Number of GPS track points currently attached to the capture."
          },
          "availableAssetTypes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DatasetAssetType"
            }
          },
          "viewerUrl": {
            "type": "string",
            "format": "uri",
            "description": "Viewer URL for the capture."
          }
        },
        "required": [
          "captureId",
          "name",
          "scanType",
          "status",
          "gpsTrackPointCount",
          "availableAssetTypes",
          "viewerUrl"
        ]
      },
      "DatasetManifestFilters": {
        "type": "object",
        "properties": {
          "minSrs": {
            "type": "number",
            "nullable": true
          },
          "hasMesh": {
            "type": "boolean"
          },
          "hasLabeling": {
            "type": "boolean"
          },
          "hasGpsTrack": {
            "type": "boolean"
          },
          "claimedOnly": {
            "type": "boolean"
          },
          "bounds": {
            "$ref": "#/components/schemas/ApiSearchBounds",
            "nullable": true
          }
        }
      },
      "DatasetManifestSummary": {
        "type": "object",
        "properties": {
          "scanTypeCounts": {
            "type": "object",
            "properties": {
              "scene": {
                "type": "integer"
              },
              "object": {
                "type": "integer"
              },
              "drone": {
                "type": "integer"
              }
            },
            "required": [
              "scene",
              "object",
              "drone"
            ]
          },
          "assetTypeCounts": {
            "type": "object",
            "additionalProperties": {
              "type": "integer"
            },
            "description": "Count of manifest items supporting each asset type."
          }
        },
        "required": [
          "scanTypeCounts",
          "assetTypeCounts"
        ]
      },
      "CreateDatasetManifestRequest": {
        "type": "object",
        "properties": {
          "scanTypes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ScanType"
            },
            "description": "Requested scan types. Defaults to object + drone when omitted."
          },
          "q": {
            "type": "string",
            "description": "Free-text search query."
          },
          "minSrs": {
            "type": "number",
            "description": "Minimum SRS score required in results."
          },
          "hasMesh": {
            "type": "boolean",
            "description": "Require mesh availability."
          },
          "hasLabeling": {
            "type": "boolean",
            "description": "Require labeling availability."
          },
          "hasGpsTrack": {
            "type": "boolean",
            "description": "Require GPS track availability."
          },
          "claimed": {
            "type": "boolean",
            "description": "Require claimed captures."
          },
          "south": {
            "type": "number"
          },
          "west": {
            "type": "number"
          },
          "north": {
            "type": "number"
          },
          "east": {
            "type": "number"
          },
          "limit": {
            "type": "integer",
            "minimum": 1,
            "maximum": 100,
            "default": 50
          }
        }
      },
      "DatasetManifestResponse": {
        "type": "object",
        "properties": {
          "manifestId": {
            "type": "string"
          },
          "scanTypes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ScanType"
            }
          },
          "query": {
            "type": "string",
            "nullable": true
          },
          "limit": {
            "type": "integer"
          },
          "count": {
            "type": "integer"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time"
          },
          "expired": {
            "type": "boolean",
            "nullable": true
          },
          "filters": {
            "$ref": "#/components/schemas/DatasetManifestFilters"
          },
          "summary": {
            "$ref": "#/components/schemas/DatasetManifestSummary"
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DatasetManifestItem"
            }
          }
        },
        "required": [
          "manifestId",
          "scanTypes",
          "limit",
          "count",
          "createdAt",
          "expiresAt",
          "filters",
          "summary",
          "items"
        ]
      },
      "QuoteDatasetExportRequest": {
        "type": "object",
        "properties": {
          "manifestId": {
            "type": "string"
          },
          "includeAssetTypes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DatasetAssetType"
            }
          }
        },
        "required": [
          "manifestId"
        ]
      },
      "DatasetExportQuoteResponse": {
        "type": "object",
        "properties": {
          "manifestId": {
            "type": "string"
          },
          "includeAssetTypes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DatasetAssetType"
            }
          },
          "itemCount": {
            "type": "integer"
          },
          "baseCost": {
            "type": "number"
          },
          "perAssetType": {
            "type": "object",
            "additionalProperties": {
              "type": "number"
            }
          },
          "totalEckoCost": {
            "type": "number"
          },
          "assetTypeCounts": {
            "type": "object",
            "additionalProperties": {
              "type": "integer"
            }
          }
        },
        "required": [
          "manifestId",
          "includeAssetTypes",
          "itemCount",
          "baseCost",
          "perAssetType",
          "totalEckoCost",
          "assetTypeCounts"
        ]
      },
      "CreateDatasetExportRequest": {
        "type": "object",
        "properties": {
          "manifestId": {
            "type": "string"
          },
          "includeAssetTypes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DatasetAssetType"
            }
          }
        },
        "required": [
          "manifestId"
        ]
      },
      "DatasetExportResponse": {
        "type": "object",
        "properties": {
          "exportId": {
            "type": "string"
          },
          "manifestId": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "example": "completed"
          },
          "count": {
            "type": "integer"
          },
          "scanTypes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ScanType"
            }
          },
          "includeAssetTypes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DatasetAssetType"
            }
          },
          "chargedEcko": {
            "type": "number"
          },
          "createdAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          },
          "completedAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time"
          },
          "expired": {
            "type": "boolean",
            "nullable": true
          },
          "bundleUrl": {
            "type": "string",
            "nullable": true,
            "format": "uri"
          },
          "manifestUrl": {
            "type": "string",
            "nullable": true,
            "format": "uri"
          }
        },
        "required": [
          "exportId",
          "manifestId",
          "status",
          "count",
          "includeAssetTypes",
          "chargedEcko",
          "expiresAt"
        ]
      },
      "ApiPurchaseCreditsRequest": {
        "type": "object",
        "properties": {
          "amountCredits": {
            "type": "number",
            "minimum": 0.01,
            "description": "Number of API service credits to purchase from the caller's legacy ECKO balance.",
            "example": 25
          },
          "apiAccountId": {
            "type": "string",
            "description": "Optional API account id. Defaults to the caller's default API account.",
            "example": "user_abc123"
          }
        },
        "required": [
          "amountCredits"
        ]
      },
      "ApiPurchaseCreditsResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "example": true
          },
          "apiAccountId": {
            "type": "string",
            "example": "user_abc123"
          },
          "purchasedCredits": {
            "type": "number",
            "example": 25
          },
          "creditBalance": {
            "type": "number",
            "example": 40
          },
          "creditHeld": {
            "type": "number",
            "example": 1
          },
          "availableCredits": {
            "type": "number",
            "example": 39
          },
          "legacyEckoBalance": {
            "type": "number",
            "description": "Remaining legacy ECKO balance after this temporary bridge purchase.",
            "example": 75
          }
        },
        "required": [
          "success",
          "apiAccountId",
          "purchasedCredits",
          "creditBalance",
          "creditHeld",
          "availableCredits"
        ]
      },
      "ApiInitUploadRequest": {
        "type": "object",
        "properties": {
          "captureId": {
            "type": "string",
            "description": "Optional caller-stable capture id. Generated if omitted.",
            "example": "cap_package_123"
          },
          "fileSizeBytes": {
            "type": "number",
            "description": "Expected upload size in bytes.",
            "example": 104857600
          },
          "contentType": {
            "type": "string",
            "description": "`application/zip` for image packages or `application/json` for AR data.",
            "example": "application/zip"
          },
          "scanType": {
            "type": "string",
            "enum": [
              "scene",
              "object",
              "drone"
            ],
            "example": "scene"
          },
          "inputKind": {
            "type": "string",
            "enum": [
              "image_package",
              "capture_package"
            ],
            "example": "image_package"
          },
          "isCapturePackage": {
            "type": "boolean",
            "example": true
          },
          "isArData": {
            "type": "boolean",
            "example": false
          }
        },
        "required": [
          "fileSizeBytes",
          "contentType"
        ]
      },
      "ApiInitUploadResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "example": true
          },
          "captureId": {
            "type": "string",
            "example": "cap_package_123"
          },
          "jobId": {
            "type": "string",
            "description": "Public API job id; currently the capture id.",
            "example": "cap_package_123"
          },
          "apiAccountId": {
            "type": "string",
            "example": "user_abc123"
          },
          "sessionUri": {
            "type": "string",
            "format": "uri",
            "description": "GCS resumable upload session URI."
          },
          "storagePath": {
            "type": "string",
            "example": "uploads/api/user_abc123/cap_package_123_capture_package.zip"
          },
          "expiresAt": {
            "type": "number",
            "description": "Unix epoch milliseconds when the resumable session expires."
          },
          "partNumber": {
            "type": "number",
            "example": 1
          }
        },
        "required": [
          "success",
          "captureId",
          "jobId",
          "apiAccountId",
          "sessionUri",
          "storagePath",
          "expiresAt",
          "partNumber"
        ]
      },
      "ApiFinalizeUploadRequest": {
        "type": "object",
        "properties": {
          "captureId": {
            "type": "string",
            "example": "cap_package_123"
          },
          "parts": {
            "type": "array",
            "minItems": 1,
            "maxItems": 1,
            "items": {
              "type": "object",
              "properties": {
                "storagePath": {
                  "type": "string",
                  "example": "uploads/api/user_abc123/cap_package_123_capture_package.zip"
                },
                "partNumber": {
                  "type": "number",
                  "example": 1
                },
                "fileSize": {
                  "type": "number",
                  "example": 104857600
                },
                "crc32c": {
                  "type": "string",
                  "nullable": true
                }
              },
              "required": [
                "storagePath",
                "partNumber"
              ]
            }
          },
          "arDataStoragePath": {
            "type": "string",
            "nullable": true
          },
          "metadata": {
            "type": "object",
            "description": "Capture metadata from the mobile image-package capture path, including scanType, name, pose/intrinsics/GPS/device metadata where available. Add `visibility: \"public\"` plus `trainingConsent: true` or `allowTraining: true` for the base processing rate. If omitted, Stratis uses the conservative private/no-training policy and charges the private processing rate.",
            "additionalProperties": true
          }
        },
        "required": [
          "captureId",
          "parts"
        ]
      },
      "ApiFinalizeUploadResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "example": true
          },
          "captureId": {
            "type": "string",
            "example": "cap_package_123"
          },
          "jobId": {
            "type": "string",
            "description": "Public API job id; currently the capture id.",
            "example": "cap_package_123"
          },
          "processingJobId": {
            "type": "string",
            "nullable": true,
            "description": "Internal worker job id when a processing job was queued."
          },
          "status": {
            "type": "string",
            "example": "queued"
          },
          "inputKind": {
            "type": "string",
            "example": "image_package"
          },
          "alreadyFinalized": {
            "type": "boolean",
            "description": "Present when a finalize retry found the capture already finalized."
          },
          "apiCreditHoldAmount": {
            "type": "number",
            "description": "Service credits reserved for this capture processing job.",
            "example": 1
          },
          "apiCreditPricingTier": {
            "type": "string",
            "enum": [
              "public_training",
              "private_or_no_training"
            ],
            "description": "Pricing tier used for the processing hold."
          }
        },
        "required": [
          "success",
          "captureId",
          "jobId",
          "status",
          "inputKind"
        ]
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Bad request or invalid parameters.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Missing, invalid, or revoked credentials.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "Forbidden": {
        "description": "Caller is authenticated but not allowed to access the resource.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "NotFound": {
        "description": "Requested resource was not found.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "PaymentRequired": {
        "description": "Insufficient API service credits for a charged operation.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "InternalServerError": {
        "description": "Unexpected server error.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "Conflict": {
        "description": "Conflict with current resource state or uploaded object metadata.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      }
    }
  },
  "paths": {
    "/createApiKey": {
      "post": {
        "tags": [
          "API Keys"
        ],
        "operationId": "createApiKey",
        "summary": "Create an API key",
        "description": "Creates a new API key for a signed-in Stratis user. This endpoint uses Firebase user auth, not API-key auth. Creating a key is account setup and is not currently a charged machine operation.",
        "security": [
          {
            "FirebaseBearerAuth": []
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateApiKeyRequest"
              },
              "examples": {
                "namedKey": {
                  "summary": "Create a named API key",
                  "value": {
                    "name": "Acme Mobile App"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "API key created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreateApiKeyResponse"
                },
                "examples": {
                  "created": {
                    "summary": "Successful API key creation",
                    "value": {
                      "success": true,
                      "apiKeyId": "gY0Yg4yW9d9mQx7b",
                      "key": "sak_0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
                      "name": "Acme Mobile App",
                      "prefix": "sak_0123"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/getApiKeys": {
      "get": {
        "tags": [
          "API Keys"
        ],
        "operationId": "getApiKeys",
        "summary": "List API keys",
        "description": "Lists API keys for the authenticated user. This endpoint uses Firebase user auth and is not a charged machine operation.",
        "security": [
          {
            "FirebaseBearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "API keys for the caller.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiKeyListResponse"
                },
                "examples": {
                  "list": {
                    "summary": "Existing keys for the signed-in user",
                    "value": {
                      "keys": [
                        {
                          "id": "gY0Yg4yW9d9mQx7b",
                          "name": "Acme Mobile App",
                          "prefix": "sak_0123",
                          "createdAt": "2026-03-28T14:22:01.000Z",
                          "lastUsedAt": "2026-03-28T15:10:45.000Z",
                          "revokedAt": null
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/revokeApiKey": {
      "post": {
        "tags": [
          "API Keys"
        ],
        "operationId": "revokeApiKey",
        "summary": "Revoke an API key",
        "description": "Revokes an API key owned by the authenticated user. This endpoint uses Firebase user auth and is not a charged machine operation.",
        "security": [
          {
            "FirebaseBearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RevokeApiKeyRequest"
              },
              "examples": {
                "revoke": {
                  "summary": "Revoke a key",
                  "value": {
                    "apiKeyId": "gY0Yg4yW9d9mQx7b"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "API key revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SuccessResponse"
                },
                "examples": {
                  "revoked": {
                    "summary": "Successful revocation",
                    "value": {
                      "success": true
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/getPublicMapData": {
      "get": {
        "tags": [
          "Public Discovery"
        ],
        "operationId": "getPublicMapData",
        "summary": "Get public map captures and claims",
        "description": "Returns public map captures plus visible claims.\n\nUse viewport parameters (`south`, `west`, `north`, `east`, `zoom`) for map-driven queries. Dense viewport queries may return aggregate `clusters` instead of full claim detail.",
        "parameters": [
          {
            "name": "south",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number"
            },
            "description": "Viewport south latitude."
          },
          {
            "name": "west",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number"
            },
            "description": "Viewport west longitude."
          },
          {
            "name": "north",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number"
            },
            "description": "Viewport north latitude."
          },
          {
            "name": "east",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number"
            },
            "description": "Viewport east longitude."
          },
          {
            "name": "zoom",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number"
            },
            "description": "Map zoom level used to decide whether to cluster responses."
          },
          {
            "name": "layer",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "all",
                "street",
                "aerial"
              ],
              "default": "all"
            },
            "description": "Restrict results to street claims/captures, aerial claims/captures, or both."
          }
        ],
        "responses": {
          "200": {
            "description": "Public map response.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicMapDataResponse"
                },
                "examples": {
                  "aerialViewport": {
                    "summary": "Aerial viewport query",
                    "value": {
                      "captures": [
                        {
                          "id": "capture_drone_456",
                          "name": "Solar Site East Parcel",
                          "scanType": "drone",
                          "status": "completed",
                          "userId": "user_456",
                          "videoUrl": null,
                          "resultUrl": "https://storage.googleapis.com/example/drone.ksplat",
                          "progress": null,
                          "centerPoint": {
                            "latitude": 35.1321,
                            "longitude": -106.6124
                          },
                          "claimStatus": "claimed",
                          "claimOwnerId": "user_456",
                          "source": "claim",
                          "createdAt": "2026-03-18T15:40:00.000Z",
                          "drafts": null
                        }
                      ],
                      "claims": [
                        {
                          "id": "capture_drone_456",
                          "captureId": "capture_drone_456",
                          "ownerId": "user_456",
                          "ownerName": "Site Ops",
                          "centerPoint": {
                            "latitude": 35.1321,
                            "longitude": -106.6124
                          },
                          "radiusM": 3.048,
                          "claimH3Cell": "8b2681d7571ffff",
                          "claimTileSystem": "h3",
                          "claimTileResolution": 11,
                          "claimLayer": "aerial",
                          "status": "claimed",
                          "createdAt": "2026-03-18T16:00:00.000Z"
                        }
                      ],
                      "clusters": []
                    }
                  }
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/getPublicCapture": {
      "get": {
        "tags": [
          "Public Discovery"
        ],
        "operationId": "getPublicCapture",
        "summary": "Get a public capture",
        "description": "Returns the public viewer payload for a single capture, including scene outputs and object-specific exports when available.",
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Capture identifier."
          }
        ],
        "responses": {
          "200": {
            "description": "Public capture payload.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicCaptureResponse"
                },
                "examples": {
                  "objectCapture": {
                    "summary": "Public object capture with object exports",
                    "value": {
                      "id": "capture_object_123",
                      "name": "Industrial Valve Assembly",
                      "scanType": "object",
                      "status": "completed",
                      "resultUrl": "https://storage.googleapis.com/example/result.ksplat",
                      "camerasUrl": "https://storage.googleapis.com/example/cameras.json",
                      "isolatedObjectPlyUrl": "https://storage.googleapis.com/example/object.ply",
                      "meshObjUrl": "https://storage.googleapis.com/example/object.obj",
                      "labelingJsonUrl": "https://storage.googleapis.com/example/labels.json",
                      "objectLabels": [
                        "valve",
                        "pipe_fitting"
                      ],
                      "objectProcessingStatus": "completed",
                      "arDataUrl": null,
                      "gaussianCount": 184223,
                      "drafts": [],
                      "pinnedModelVersion": "v2.3",
                      "modelHistory": [],
                      "gravityVector": null,
                      "orientationAdjustment": null,
                      "defaultView": null,
                      "centerPoint": {
                        "latitude": 29.7604,
                        "longitude": -95.3698,
                        "altitude": 8.2
                      },
                      "createdAt": "2026-03-20T18:12:10.000Z",
                      "processedAt": "2026-03-20T18:19:33.000Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/getCommunityCaptures": {
      "get": {
        "tags": [
          "Public Discovery"
        ],
        "operationId": "getCommunityCaptures",
        "summary": "List community captures",
        "description": "Lists completed captures visible to the community.\n\nThis endpoint is public, but an optional Firebase bearer token may be supplied to populate the `isOwn` field.",
        "parameters": [
          {
            "name": "scanType",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "scene",
                "object",
                "drone"
              ],
              "default": "scene"
            },
            "description": "Capture type filter."
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "newest",
                "oldest",
                "srs_desc",
                "srs_asc"
              ],
              "default": "newest"
            },
            "description": "Sort order."
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 48
            },
            "description": "Requested page size."
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Pagination cursor from a previous response."
          }
        ],
        "responses": {
          "200": {
            "description": "Community captures page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CommunityCapturesResponse"
                },
                "examples": {
                  "objects": {
                    "summary": "Community object captures",
                    "value": {
                      "captures": [
                        {
                          "id": "capture_object_123",
                          "name": "Industrial Valve Assembly",
                          "scanType": "object",
                          "status": "completed",
                          "srs": 88,
                          "gaussianCount": 184223,
                          "resultUrl": "https://storage.googleapis.com/example/result.ksplat",
                          "videoUrl": "https://storage.googleapis.com/example/source.mp4",
                          "renderVideoUrl": null,
                          "thumbnailVideoUrl": null,
                          "compareVideoUrl": null,
                          "centerPoint": {
                            "latitude": 29.7604,
                            "longitude": -95.3698
                          },
                          "userId": "user_123",
                          "isOwn": false,
                          "createdAt": "2026-03-20T18:12:10.000Z",
                          "processedAt": "2026-03-20T18:19:33.000Z",
                          "pinnedModelVersion": "v2.3",
                          "durationSeconds": 24.8,
                          "isolatedObjectPlyUrl": "https://storage.googleapis.com/example/object.ply",
                          "meshObjUrl": "https://storage.googleapis.com/example/object.obj",
                          "labelingJsonUrl": "https://storage.googleapis.com/example/labels.json"
                        }
                      ],
                      "nextCursor": "capture_object_123"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/createCaptureShareLink": {
      "post": {
        "tags": [
          "Public Discovery"
        ],
        "operationId": "createCaptureShareLink",
        "summary": "Create or fetch a capture share link",
        "description": "Creates a short share link for a capture.\n\nCompleted captures can usually be shared without auth. For incomplete captures, the caller must be the owner or an admin.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "captureId": {
                    "type": "string",
                    "description": "Capture identifier to share.",
                    "example": "capture_123"
                  }
                },
                "required": [
                  "captureId"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Short share link payload.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShareLinkResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/resolveCaptureShareLink": {
      "get": {
        "tags": [
          "Public Discovery"
        ],
        "operationId": "resolveCaptureShareLink",
        "summary": "Resolve a share code",
        "description": "Resolves a short share code to its underlying capture and viewer URL.",
        "parameters": [
          {
            "name": "code",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Base58 short code."
          }
        ],
        "responses": {
          "200": {
            "description": "Resolved share-link payload.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShareLinkResponse"
                },
                "examples": {
                  "resolved": {
                    "summary": "Resolved share code",
                    "value": {
                      "captureId": "capture_scene_123",
                      "code": "8FmH2Q",
                      "shortUrl": "https://stratis.example/s/8FmH2Q",
                      "captureName": "Market Street Corner",
                      "status": "completed",
                      "viewerUrl": "https://stratis.example/viewer?id=capture_scene_123"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/getClaimListings": {
      "get": {
        "tags": [
          "Public Discovery"
        ],
        "operationId": "getClaimListings",
        "summary": "List marketplace claim listings",
        "description": "Returns active marketplace claim listings. If required Firestore indexes are still building, the response may return `indexBuilding: true` with an empty list instead of a hard failure.",
        "parameters": [
          {
            "name": "sortBy",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "newest",
                "price_low",
                "price_high",
                "srs_high"
              ],
              "default": "newest"
            },
            "description": "Listing sort order."
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50,
              "default": 24
            },
            "description": "Requested page size."
          },
          {
            "name": "minPrice",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number"
            },
            "description": "Minimum listing price in ECKO."
          },
          {
            "name": "maxPrice",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number"
            },
            "description": "Maximum listing price in ECKO."
          },
          {
            "name": "country",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Country filter."
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Base64 pagination cursor from a previous response."
          }
        ],
        "responses": {
          "200": {
            "description": "Marketplace listing page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ClaimListingsResponse"
                },
                "examples": {
                  "listings": {
                    "summary": "Active claim listings",
                    "value": {
                      "listings": [
                        {
                          "id": "listing_123",
                          "claimId": "claim_456",
                          "sellerId": "user_789",
                          "sellerName": "Geo Capture Co",
                          "price": 250,
                          "title": "Downtown Rooftop Coverage",
                          "notes": "High-SRS aerial capture with strong rooftop visibility.",
                          "status": "active",
                          "createdAt": "2026-03-10T12:00:00.000Z",
                          "updatedAt": "2026-03-12T12:00:00.000Z",
                          "captureName": "Downtown Rooftop Coverage",
                          "srs": 92,
                          "gaussianCount": 412555,
                          "centerPoint": {
                            "latitude": 40.7128,
                            "longitude": -74.006
                          },
                          "location": {
                            "city": "New York",
                            "state": "NY",
                            "country": "US"
                          }
                        }
                      ],
                      "nextCursor": "eyJzb3J0VmFsdWUiOjI1MCwiaWQiOiJsaXN0aW5nXzEyMyJ9"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/apiSearchClaims": {
      "post": {
        "tags": [
          "Machine API"
        ],
        "operationId": "apiSearchClaims",
        "summary": "Search nearby claims",
        "description": "Searches for nearby claimed captures using an API key.\n\nCurrent price: 1 ECKO per request.\nDefault limit: 1 result. Maximum limit: 100 results.\n\nThe backend also accepts the same fields as query parameters, but JSON request bodies are the canonical documented form.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ApiSearchClaimsRequest"
              },
              "examples": {
                "downtownSearch": {
                  "summary": "Search nearby claims",
                  "value": {
                    "lat": 37.7749,
                    "lng": -122.4194,
                    "distanceM": 1000,
                    "limit": 5
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Nearby claim results.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiSearchClaimsResponse"
                },
                "examples": {
                  "results": {
                    "summary": "Nearby claim matches",
                    "value": {
                      "results": [
                        {
                          "captureId": "capture_scene_123",
                          "claimOwnerId": "user_abc",
                          "claimRadiusM": 3.048,
                          "claimH3Cell": "8c28308280b1dff",
                          "claimTileSystem": "h3",
                          "claimTileResolution": 12,
                          "claimStatus": "claimed",
                          "centerPoint": {
                            "latitude": 37.7751,
                            "longitude": -122.4188
                          },
                          "distanceM": 58.2,
                          "plyUrl": "https://storage.googleapis.com/example/scene.ply",
                          "videoUrl": "https://storage.googleapis.com/example/source.mp4",
                          "srs": 89,
                          "gaussianCount": 221034,
                          "captureName": "Market Street Corner",
                          "viewerUrl": "https://stratis.example/viewer?id=capture_scene_123",
                          "updatedAt": "2026-03-27T10:15:00.000Z"
                        }
                      ],
                      "limit": 5,
                      "distanceM": 1000,
                      "count": 1
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/apiSearchObjects": {
      "get": {
        "tags": [
          "Machine API"
        ],
        "operationId": "apiSearchObjects",
        "summary": "Search object captures",
        "description": "Searches completed object captures using an API key. This is a retrieval-focused endpoint for object inventory, not a processing endpoint, and it is not currently documented as a charged operation.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Free-text object search query. `label` is accepted as an alias."
          },
          {
            "name": "label",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Alias for `q`."
          },
          {
            "name": "minSrs",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number"
            },
            "description": "Minimum SRS score required in results."
          },
          {
            "name": "hasMesh",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean"
            },
            "description": "Require that the object has a mesh OBJ URL."
          },
          {
            "name": "hasLabeling",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean"
            },
            "description": "Require that the object has a labeling JSON URL."
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 24
            },
            "description": "Maximum number of results."
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Pagination cursor from a previous response."
          }
        ],
        "responses": {
          "200": {
            "description": "Matching object captures.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiObjectSearchResponse"
                },
                "examples": {
                  "objects": {
                    "summary": "Search objects with a mesh requirement",
                    "value": {
                      "objects": [
                        {
                          "id": "capture_object_123",
                          "name": "Industrial Valve Assembly",
                          "scanType": "object",
                          "status": "completed",
                          "resultUrl": "https://storage.googleapis.com/example/result.ksplat",
                          "isolatedObjectPlyUrl": "https://storage.googleapis.com/example/object.ply",
                          "meshObjUrl": "https://storage.googleapis.com/example/object.obj",
                          "labelingJsonUrl": "https://storage.googleapis.com/example/labels.json",
                          "objectLabels": {
                            "title": "Industrial Valve Assembly",
                            "category": "valve",
                            "tags": [
                              "industrial",
                              "pipe_fitting"
                            ]
                          },
                          "objectProcessingStatus": "completed",
                          "srs": 88,
                          "gaussianCount": 184223,
                          "centerPoint": {
                            "latitude": 29.7604,
                            "longitude": -95.3698
                          },
                          "createdAt": "2026-03-20T18:12:10.000Z",
                          "processedAt": "2026-03-20T18:19:33.000Z",
                          "pinnedModelVersion": "v2.3",
                          "hasSplat": true,
                          "hasIsolatedPointCloud": true,
                          "hasMesh": true,
                          "hasLabeling": true,
                          "viewerUrl": "https://stratis.example/viewer?id=capture_object_123&embed=1"
                        }
                      ],
                      "query": "valve",
                      "limit": 20,
                      "count": 1,
                      "nextCursor": "capture_object_123"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/apiGetObject": {
      "get": {
        "tags": [
          "Machine API"
        ],
        "operationId": "apiGetObject",
        "summary": "Get object detail",
        "description": "Returns a dedicated object detail payload for a completed or in-progress object capture using an API key. This gives third parties a stable object-oriented contract instead of relying on the general public capture endpoint.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Object capture identifier. `captureId` is accepted as an alias."
          },
          {
            "name": "captureId",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Alias for `id`."
          }
        ],
        "responses": {
          "200": {
            "description": "Object detail payload.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiObjectDetail"
                },
                "examples": {
                  "detail": {
                    "summary": "Detailed object capture payload",
                    "value": {
                      "id": "capture_object_123",
                      "name": "Industrial Valve Assembly",
                      "scanType": "object",
                      "status": "completed",
                      "resultUrl": "https://storage.googleapis.com/example/result.ksplat",
                      "isolatedObjectPlyUrl": "https://storage.googleapis.com/example/object.ply",
                      "meshObjUrl": "https://storage.googleapis.com/example/object.obj",
                      "labelingJsonUrl": "https://storage.googleapis.com/example/labels.json",
                      "camerasUrl": "https://storage.googleapis.com/example/cameras.json",
                      "arDataUrl": null,
                      "objectLabels": {
                        "title": "Industrial Valve Assembly",
                        "category": "valve",
                        "tags": [
                          "industrial",
                          "pipe_fitting"
                        ]
                      },
                      "objectProcessingStatus": "completed",
                      "srs": 88,
                      "gaussianCount": 184223,
                      "centerPoint": {
                        "latitude": 29.7604,
                        "longitude": -95.3698,
                        "altitude": 8.2
                      },
                      "createdAt": "2026-03-20T18:12:10.000Z",
                      "processedAt": "2026-03-20T18:19:33.000Z",
                      "pinnedModelVersion": "v2.3",
                      "hasSplat": true,
                      "hasIsolatedPointCloud": true,
                      "hasMesh": true,
                      "hasLabeling": true,
                      "viewerUrl": "https://stratis.example/viewer?id=capture_object_123&embed=1",
                      "drafts": [],
                      "modelHistory": [],
                      "gravityVector": null,
                      "orientationAdjustment": null,
                      "defaultView": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/apiSearchAerial": {
      "get": {
        "tags": [
          "Machine API"
        ],
        "operationId": "apiSearchAerial",
        "summary": "Search aerial captures",
        "description": "Searches completed drone captures using an API key. This is a retrieval-focused endpoint for aerial inventory and preview workflows, and it is not currently documented as a charged operation.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Free-text aerial search query. `name` is accepted as an alias."
          },
          {
            "name": "name",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Alias for `q`."
          },
          {
            "name": "minSrs",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number"
            },
            "description": "Minimum SRS score required in results."
          },
          {
            "name": "hasRenderVideo",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean"
            },
            "description": "Require that the capture has a render preview URL."
          },
          {
            "name": "hasGpsTrack",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean"
            },
            "description": "Require that the capture has GPS track points."
          },
          {
            "name": "claimed",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean"
            },
            "description": "Require that the capture is currently claimed."
          },
          {
            "name": "south",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number"
            },
            "description": "Viewport south latitude bound."
          },
          {
            "name": "west",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number"
            },
            "description": "Viewport west longitude bound."
          },
          {
            "name": "north",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number"
            },
            "description": "Viewport north latitude bound."
          },
          {
            "name": "east",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number"
            },
            "description": "Viewport east longitude bound."
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 24
            },
            "description": "Maximum number of results."
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Pagination cursor from a previous response."
          }
        ],
        "responses": {
          "200": {
            "description": "Matching aerial captures.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiAerialSearchResponse"
                },
                "examples": {
                  "aerial": {
                    "summary": "Search claimed aerial captures in a site viewport",
                    "value": {
                      "captures": [
                        {
                          "id": "capture_drone_456",
                          "name": "Downtown Substation West Pass",
                          "scanType": "drone",
                          "status": "completed",
                          "resultUrl": "https://storage.googleapis.com/example/aerial.ksplat",
                          "renderVideoUrl": "https://storage.googleapis.com/example/aerial-render.mp4",
                          "thumbnailVideoUrl": "https://storage.googleapis.com/example/aerial-thumb.mp4",
                          "compareVideoUrl": "https://storage.googleapis.com/example/aerial-compare.mp4",
                          "srs": 84,
                          "gaussianCount": 612004,
                          "durationSeconds": 318.4,
                          "centerPoint": {
                            "latitude": 37.7749,
                            "longitude": -122.4194,
                            "altitude": 92.1
                          },
                          "claimStatus": "claimed",
                          "claimOwnerId": "user_abc123",
                          "claimH3Cell": "8b28308280d1fff",
                          "claimTileSystem": "h3",
                          "claimTileResolution": 11,
                          "createdAt": "2026-03-19T14:20:00.000Z",
                          "processedAt": "2026-03-19T14:41:12.000Z",
                          "pinnedModelVersion": "v2.3",
                          "gpsTrackPointCount": 824,
                          "videoPartsCount": 3,
                          "hasSplat": true,
                          "hasRenderPreview": true,
                          "hasGpsTrack": true,
                          "hasMultipartVideo": true,
                          "viewerUrl": "https://stratis.example/viewer?id=capture_drone_456&embed=1"
                        }
                      ],
                      "query": "substation",
                      "limit": 20,
                      "count": 1,
                      "nextCursor": "capture_drone_456",
                      "bounds": {
                        "south": 37.7,
                        "west": -122.55,
                        "north": 37.85,
                        "east": -122.35
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/apiGetAerial": {
      "get": {
        "tags": [
          "Machine API"
        ],
        "operationId": "apiGetAerial",
        "summary": "Get aerial capture detail",
        "description": "Returns a dedicated aerial-capture detail payload for a completed drone capture.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Aerial capture identifier. `captureId` is accepted as an alias."
          },
          {
            "name": "captureId",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Alias for `id`."
          }
        ],
        "responses": {
          "200": {
            "description": "Aerial detail payload.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiAerialDetail"
                },
                "examples": {
                  "aerial": {
                    "summary": "Aerial detail with GPS track and history",
                    "value": {
                      "id": "capture_drone_456",
                      "name": "Downtown Substation West Pass",
                      "scanType": "drone",
                      "status": "completed",
                      "resultUrl": "https://storage.googleapis.com/example/aerial.ksplat",
                      "renderVideoUrl": "https://storage.googleapis.com/example/aerial-render.mp4",
                      "thumbnailVideoUrl": "https://storage.googleapis.com/example/aerial-thumb.mp4",
                      "compareVideoUrl": "https://storage.googleapis.com/example/aerial-compare.mp4",
                      "videoUrl": "https://storage.googleapis.com/example/aerial-source.mp4",
                      "camerasUrl": "https://storage.googleapis.com/example/aerial-cameras.json",
                      "srs": 84,
                      "gaussianCount": 612004,
                      "durationSeconds": 318.4,
                      "centerPoint": {
                        "latitude": 37.7749,
                        "longitude": -122.4194,
                        "altitude": 92.1
                      },
                      "claimStatus": "claimed",
                      "claimOwnerId": "user_abc123",
                      "claimH3Cell": "8b28308280d1fff",
                      "claimTileSystem": "h3",
                      "claimTileResolution": 11,
                      "createdAt": "2026-03-19T14:20:00.000Z",
                      "processedAt": "2026-03-19T14:41:12.000Z",
                      "pinnedModelVersion": "v2.3",
                      "gpsTrackPointCount": 824,
                      "videoPartsCount": 3,
                      "hasSplat": true,
                      "hasRenderPreview": true,
                      "hasGpsTrack": true,
                      "hasMultipartVideo": true,
                      "viewerUrl": "https://stratis.example/viewer?id=capture_drone_456&embed=1",
                      "gpsTrack": [
                        {
                          "latitude": 37.7741,
                          "longitude": -122.4202,
                          "altitude": 88.5,
                          "timestamp": "2026-03-19T14:20:02.000Z"
                        },
                        {
                          "latitude": 37.7744,
                          "longitude": -122.4198,
                          "altitude": 90.2,
                          "timestamp": "2026-03-19T14:20:05.000Z"
                        }
                      ],
                      "drafts": [
                        {
                          "version": "draft-v2.3-1",
                          "iteration": 1,
                          "resultUrl": "https://storage.googleapis.com/example/aerial-draft.ksplat",
                          "camerasUrl": "https://storage.googleapis.com/example/aerial-draft-cameras.json",
                          "gaussianCount": 402113
                        }
                      ],
                      "modelHistory": [
                        {
                          "version": "v2.2",
                          "resultUrl": "https://storage.googleapis.com/example/aerial-v22.ksplat",
                          "camerasUrl": "https://storage.googleapis.com/example/aerial-v22-cameras.json",
                          "renderVideoUrl": "https://storage.googleapis.com/example/aerial-v22-render.mp4",
                          "pipelineProfileName": "drone-default",
                          "processedAt": "2026-03-11T09:15:00.000Z"
                        }
                      ],
                      "defaultView": {
                        "position": [
                          12.4,
                          8.1,
                          4.7
                        ],
                        "target": [
                          0.2,
                          0.1,
                          0
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/apiCreateDatasetManifest": {
      "post": {
        "tags": [
          "Machine API"
        ],
        "operationId": "apiCreateDatasetManifest",
        "summary": "Create a dataset manifest",
        "description": "Creates a saved shortlist of captures for later quoting and export. This is not currently documented as a charged operation.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateDatasetManifestRequest"
              },
              "examples": {
                "manifest": {
                  "summary": "Create a mixed object + aerial shortlist",
                  "value": {
                    "scanTypes": [
                      "object",
                      "drone"
                    ],
                    "q": "valve",
                    "hasMesh": true,
                    "minSrs": 0.7,
                    "limit": 40
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Created dataset manifest.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DatasetManifestResponse"
                },
                "examples": {
                  "manifest": {
                    "summary": "Manifest with object and aerial items",
                    "value": {
                      "manifestId": "manifest_abc123",
                      "scanTypes": [
                        "object",
                        "drone"
                      ],
                      "query": "valve",
                      "limit": 40,
                      "count": 2,
                      "createdAt": "2026-03-28T15:10:00.000Z",
                      "expiresAt": "2026-03-29T15:10:00.000Z",
                      "filters": {
                        "minSrs": 0.7,
                        "hasMesh": true,
                        "hasLabeling": false,
                        "hasGpsTrack": false,
                        "claimedOnly": false,
                        "bounds": null
                      },
                      "summary": {
                        "scanTypeCounts": {
                          "scene": 0,
                          "object": 1,
                          "drone": 1
                        },
                        "assetTypeCounts": {
                          "metadata": 2,
                          "viewer": 2,
                          "splat": 2,
                          "mesh": 1,
                          "labeling": 1,
                          "gpsTrack": 1,
                          "renderVideo": 1
                        }
                      },
                      "items": [
                        {
                          "captureId": "capture_object_123",
                          "name": "Industrial Valve Assembly",
                          "scanType": "object",
                          "status": "completed",
                          "srs": 88,
                          "gaussianCount": 184223,
                          "centerPoint": {
                            "latitude": 29.7604,
                            "longitude": -95.3698
                          },
                          "createdAt": "2026-03-20T18:12:10.000Z",
                          "processedAt": "2026-03-20T18:19:33.000Z",
                          "claimStatus": null,
                          "objectLabels": {
                            "title": "Industrial Valve Assembly",
                            "category": "valve"
                          },
                          "objectProcessingStatus": "completed",
                          "gpsTrackPointCount": 0,
                          "availableAssetTypes": [
                            "metadata",
                            "viewer",
                            "splat",
                            "mesh",
                            "labeling",
                            "isolatedPointCloud"
                          ],
                          "viewerUrl": "https://stratis.example/viewer?id=capture_object_123&embed=1"
                        },
                        {
                          "captureId": "capture_drone_456",
                          "name": "Downtown Substation West Pass",
                          "scanType": "drone",
                          "status": "completed",
                          "srs": 84,
                          "gaussianCount": 612004,
                          "centerPoint": {
                            "latitude": 37.7749,
                            "longitude": -122.4194,
                            "altitude": 92.1
                          },
                          "createdAt": "2026-03-19T14:20:00.000Z",
                          "processedAt": "2026-03-19T14:41:12.000Z",
                          "claimStatus": "claimed",
                          "objectLabels": null,
                          "objectProcessingStatus": null,
                          "gpsTrackPointCount": 824,
                          "availableAssetTypes": [
                            "metadata",
                            "viewer",
                            "splat",
                            "cameras",
                            "renderVideo",
                            "thumbnailVideo",
                            "compareVideo",
                            "gpsTrack"
                          ],
                          "viewerUrl": "https://stratis.example/viewer?id=capture_drone_456&embed=1"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/apiGetDatasetManifest": {
      "get": {
        "tags": [
          "Machine API"
        ],
        "operationId": "apiGetDatasetManifest",
        "summary": "Get a dataset manifest",
        "description": "Returns a previously created dataset manifest.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "manifestId",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Manifest identifier. `id` is accepted as an alias."
          },
          {
            "name": "id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Alias for `manifestId`."
          }
        ],
        "responses": {
          "200": {
            "description": "Dataset manifest payload.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DatasetManifestResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/apiQuoteDatasetExport": {
      "post": {
        "tags": [
          "Machine API"
        ],
        "operationId": "apiQuoteDatasetExport",
        "summary": "Quote a dataset export",
        "description": "Calculates the current ECKO cost for exporting a previously created manifest. This is not currently documented as a charged operation.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/QuoteDatasetExportRequest"
              },
              "examples": {
                "quote": {
                  "summary": "Quote object and aerial export",
                  "value": {
                    "manifestId": "manifest_abc123",
                    "includeAssetTypes": [
                      "metadata",
                      "viewer",
                      "splat",
                      "mesh",
                      "labeling"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Dataset export quote.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DatasetExportQuoteResponse"
                },
                "examples": {
                  "quote": {
                    "summary": "Export quote response",
                    "value": {
                      "manifestId": "manifest_abc123",
                      "includeAssetTypes": [
                        "metadata",
                        "viewer",
                        "splat",
                        "mesh",
                        "labeling"
                      ],
                      "itemCount": 2,
                      "baseCost": 5,
                      "perAssetType": {
                        "metadata": 0,
                        "viewer": 0.04,
                        "splat": 0.3,
                        "mesh": 0.2,
                        "labeling": 0.15
                      },
                      "totalEckoCost": 5.69,
                      "assetTypeCounts": {
                        "metadata": 2,
                        "viewer": 2,
                        "splat": 2,
                        "mesh": 1,
                        "labeling": 1
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/apiCreateDatasetExport": {
      "post": {
        "tags": [
          "Machine API"
        ],
        "operationId": "apiCreateDatasetExport",
        "summary": "Create a dataset export",
        "description": "Creates a premium dataset export from a manifest, deducts the quoted ECKO amount, and stores a downloadable JSON package plus manifest file.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateDatasetExportRequest"
              },
              "examples": {
                "export": {
                  "summary": "Create a paid dataset export",
                  "value": {
                    "manifestId": "manifest_abc123",
                    "includeAssetTypes": [
                      "metadata",
                      "viewer",
                      "splat",
                      "mesh",
                      "labeling"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Created dataset export.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DatasetExportResponse"
                },
                "examples": {
                  "export": {
                    "summary": "Completed export response",
                    "value": {
                      "exportId": "export_abc123",
                      "manifestId": "manifest_abc123",
                      "status": "completed",
                      "count": 2,
                      "includeAssetTypes": [
                        "metadata",
                        "viewer",
                        "splat",
                        "mesh",
                        "labeling"
                      ],
                      "chargedEcko": 5.69,
                      "expiresAt": "2026-03-29T15:15:00.000Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/apiGetDatasetExport": {
      "get": {
        "tags": [
          "Machine API"
        ],
        "operationId": "apiGetDatasetExport",
        "summary": "Get a dataset export",
        "description": "Returns status and signed download URLs for a previously created dataset export.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "exportId",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Export identifier. `id` is accepted as an alias."
          },
          {
            "name": "id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Alias for `exportId`."
          }
        ],
        "responses": {
          "200": {
            "description": "Dataset export payload.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DatasetExportResponse"
                },
                "examples": {
                  "export": {
                    "summary": "Retrieve export download URLs",
                    "value": {
                      "exportId": "export_abc123",
                      "manifestId": "manifest_abc123",
                      "status": "completed",
                      "count": 2,
                      "scanTypes": [
                        "object",
                        "drone"
                      ],
                      "includeAssetTypes": [
                        "metadata",
                        "viewer",
                        "splat",
                        "mesh",
                        "labeling"
                      ],
                      "chargedEcko": 5.69,
                      "createdAt": "2026-03-28T15:15:00.000Z",
                      "completedAt": "2026-03-28T15:15:02.000Z",
                      "expiresAt": "2026-03-29T15:15:00.000Z",
                      "expired": false,
                      "bundleUrl": "https://storage.googleapis.com/example/export-bundle.json?X-Goog-Signature=...",
                      "manifestUrl": "https://storage.googleapis.com/example/export-manifest.json?X-Goog-Signature=..."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/apiCreateJob": {
      "post": {
        "tags": [
          "Machine API"
        ],
        "operationId": "apiCreateJob",
        "summary": "Create an upload job",
        "description": "Legacy MP4 compatibility path. Allocates a machine job and returns a signed upload URL for a `video/mp4` source file. For high-quality mobile image-package captures, prefer `/apiInitUpload` and `/apiFinalizeUpload`. This endpoint validates available API service credits before issuing an upload URL, but it does not place the processing hold until `/apiCommitJob`.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ApiCreateJobRequest"
              },
              "examples": {
                "createJob": {
                  "summary": "Create a processing job",
                  "value": {
                    "name": "Warehouse Aisle 3"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Upload job created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiCreateJobResponse"
                },
                "examples": {
                  "created": {
                    "summary": "Upload job created",
                    "value": {
                      "success": true,
                      "jobId": "capture_api_123",
                      "uploadUrl": "https://storage.googleapis.com/upload-signed-url",
                      "uploadExpiresAt": "2026-03-28T16:00:00.000Z",
                      "storagePath": "uploads/api/user_123/capture_api_123.mp4"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/apiCommitJob": {
      "post": {
        "tags": [
          "Machine API"
        ],
        "operationId": "apiCommitJob",
        "summary": "Commit an uploaded job for processing",
        "description": "Commits a previously uploaded legacy MP4 job and queues it for processing. Public captures that allow training hold the base processing rate. Private captures, or captures that do not allow training, hold the private processing rate. If `capturePolicy` is omitted, Stratis uses the conservative private/no-training policy. Maximum supported source duration: 10 minutes.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ApiCommitJobRequest"
              },
              "examples": {
                "commit": {
                  "summary": "Commit an uploaded scene job",
                  "value": {
                    "jobId": "capture_api_123",
                    "durationSeconds": 42.3,
                    "name": "Warehouse Aisle 3",
                    "centerPoint": {
                      "latitude": 37.7749,
                      "longitude": -122.4194,
                      "altitude": 12
                    },
                    "capturePolicy": {
                      "visibility": "public",
                      "trainingConsent": true
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Job committed or already committed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiCommitJobResponse"
                },
                "examples": {
                  "queued": {
                    "summary": "Job accepted for processing",
                    "value": {
                      "success": true,
                      "jobId": "capture_api_123",
                      "status": "queued",
                      "apiCreditHoldAmount": 1,
                      "apiCreditPricingTier": "public_training"
                    }
                  },
                  "alreadyCommitted": {
                    "summary": "Job was already committed earlier",
                    "value": {
                      "success": true,
                      "jobId": "capture_api_123",
                      "status": "pending",
                      "alreadyCommitted": true
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/apiGetJob": {
      "get": {
        "tags": [
          "Machine API"
        ],
        "operationId": "apiGetJob",
        "summary": "Get job status",
        "description": "Returns processing state for a previously created machine job.\n\nWhen the job is complete and result bundles are still valid, `downloadUrl` and `camerasUrl` are returned as signed URLs.\nSigned result bundle URLs expire after 1 hour. Signed source video URLs used internally expire after 24 hours.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "jobId",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Job identifier."
          }
        ],
        "responses": {
          "200": {
            "description": "Job status payload.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobStatus"
                },
                "examples": {
                  "completed": {
                    "summary": "Completed job with signed result URLs",
                    "value": {
                      "jobId": "capture_api_123",
                      "status": "completed",
                      "progress": null,
                      "captureName": "Warehouse Aisle 3",
                      "durationSeconds": 42.3,
                      "resultUrl": "https://storage.googleapis.com/example/result.ksplat",
                      "downloadUrl": "https://storage.googleapis.com/example/result-download-signed",
                      "camerasUrl": "https://storage.googleapis.com/example/cameras-download-signed",
                      "viewerUrl": "https://stratis.example/viewer?id=capture_api_123",
                      "srs": 88,
                      "ssim": 0.93,
                      "lpips": 0.11,
                      "processedAt": "2026-03-28T16:24:00.000Z",
                      "apiResultExpiresAt": "2026-03-28T17:24:00.000Z",
                      "expired": false
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/apiGetBalance": {
      "get": {
        "tags": [
          "Machine API"
        ],
        "operationId": "apiGetBalance",
        "summary": "Get current API billing balance",
        "description": "Returns API service-credit balance, held credits, available credits, and active API price points for the authenticated API key.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Current API billing state.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiBalanceResponse"
                },
                "examples": {
                  "balance": {
                    "summary": "Current available balance",
                    "value": {
                      "apiAccountId": "user_abc123",
                      "creditBalance": 12.5,
                      "creditHeld": 1,
                      "availableCredits": 11.5,
                      "apiSearchCost": 1,
                      "apiProcessCost": 1,
                      "apiPublicTrainingProcessCost": 1,
                      "apiPrivateProcessCost": 3,
                      "apiPrivateProcessMultiplier": 3,
                      "apiDatasetExportBaseCost": 5,
                      "apiKeyId": "gY0Yg4yW9d9mQx7b",
                      "apiKeyName": "Acme Mobile App",
                      "apiKeyLastUsedAt": "2026-03-28T17:05:00.000Z"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/apiGetUsage": {
      "get": {
        "tags": [
          "Machine API"
        ],
        "operationId": "apiGetUsage",
        "summary": "Get recent API billing usage",
        "description": "Returns recent API service-credit ledger activity for the authenticated API account, including credit purchases, search charges, processing holds, final processing spend, dataset export spend, and hold releases.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            },
            "description": "Maximum number of API usage records to return."
          }
        ],
        "responses": {
          "200": {
            "description": "Recent API billing activity.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiUsageResponse"
                },
                "examples": {
                  "usage": {
                    "summary": "Recent API billing activity",
                    "value": {
                      "transactions": [
                        {
                          "id": "txn_1",
                          "type": "spend",
                          "category": "claim_search",
                          "amount": 1,
                          "balanceAfter": 14,
                          "heldAfter": 0,
                          "memo": "API claim search",
                          "createdAt": "2026-03-28T16:00:00.000Z",
                          "jobId": null,
                          "captureId": null,
                          "captureName": null,
                          "jobStatus": null,
                          "amountCredits": 1,
                          "source": "api_runtime"
                        },
                        {
                          "id": "txn_2",
                          "type": "hold",
                          "category": "processing_hold",
                          "amount": 1,
                          "balanceAfter": 14,
                          "heldAfter": 1,
                          "memo": "Hold for API job capture_api_123",
                          "createdAt": "2026-03-28T16:02:00.000Z",
                          "jobId": "capture_api_123",
                          "captureId": "capture_api_123",
                          "captureName": "Warehouse Aisle 3",
                          "jobStatus": null,
                          "amountCredits": 1,
                          "source": "api_runtime"
                        },
                        {
                          "id": "txn_3",
                          "type": "spend",
                          "category": "processing_spend",
                          "amount": 1,
                          "balanceAfter": 13,
                          "heldAfter": 0,
                          "memo": "API processing job capture_api_123",
                          "createdAt": "2026-03-28T16:24:00.000Z",
                          "jobId": "job_789",
                          "captureId": "capture_api_123",
                          "captureName": "Warehouse Aisle 3",
                          "jobStatus": "completed",
                          "amountCredits": 1,
                          "source": "api_runtime"
                        },
                        {
                          "id": "txn_dataset_001",
                          "type": "spend",
                          "category": "dataset_export",
                          "amount": 5.69,
                          "balanceAfter": 5.81,
                          "heldAfter": 1,
                          "memo": "API dataset export export_abc123",
                          "createdAt": "2026-03-28T15:15:02.000Z",
                          "jobId": null,
                          "captureId": null,
                          "captureName": null,
                          "jobStatus": null,
                          "amountCredits": 5.69,
                          "source": "api_runtime"
                        }
                      ],
                      "limit": 25,
                      "count": 4,
                      "summary": {
                        "spends": 3,
                        "holds": 1,
                        "holdReleases": 0,
                        "grossSpend": 7.69,
                        "grossHold": 1,
                        "grossHoldRelease": 0
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/apiPurchaseCredits": {
      "post": {
        "tags": [
          "Machine API"
        ],
        "operationId": "apiPurchaseCredits",
        "summary": "Purchase API service credits",
        "description": "Temporary bridge endpoint that lets an authenticated Stratis user convert legacy ECKO balance into non-custodial API service credits. Runtime API calls spend only service credits.",
        "security": [
          {
            "FirebaseBearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ApiPurchaseCreditsRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Credits purchased.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiPurchaseCreditsResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/apiInitUpload": {
      "post": {
        "tags": [
          "Machine API"
        ],
        "operationId": "apiInitUpload",
        "summary": "Initialize an image-package upload session",
        "description": "Creates a GCS resumable upload session for the public API high-quality image-package capture path. Upload bytes directly to the returned session URI, then call `/apiFinalizeUpload`.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ApiInitUploadRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Upload session created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiInitUploadResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/apiFinalizeUpload": {
      "post": {
        "tags": [
          "Machine API"
        ],
        "operationId": "apiFinalizeUpload",
        "summary": "Finalize an image-package upload and queue processing",
        "description": "Verifies the uploaded image-package zip, reserves API service credits, creates the API capture, and queues existing Stratis image-package processing. Include `metadata.visibility: \"public\"` and `metadata.trainingConsent: true` for base-rate processing. Private captures, or captures that do not allow training, reserve the private processing rate. If policy fields are omitted, Stratis uses the conservative private/no-training policy.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ApiFinalizeUploadRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Capture finalized and queued, or an idempotent finalize retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiFinalizeUploadResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    }
  }
}
