# Assets API

Source: https://frameleaf.app/docs/api/reference/assets/

Use your own server and its scoped API keys.

## List recent archive operations

GET /api/archive-operations



```json
{
  "operationId": "getArchiveOperations",
  "parameters": [],
  "responses": {
    "200": {
      "content": {
        "application/json": {
          "schema": {
            "items": {
              "$ref": "#/components/schemas/ArchiveOperationResponseDto"
            },
            "type": "array"
          }
        }
      },
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "List recent archive operations",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.update"
}
```

## Archive a selection in the background

POST /api/archive-operations

Freezes the selection and hands it to a durable bulk job. Undo later restores only items nothing has changed since.

```json
{
  "description": "Freezes the selection and hands it to a durable bulk job. Undo later restores only items nothing has changed since.",
  "operationId": "createArchiveOperation",
  "parameters": [],
  "requestBody": {
    "content": {
      "application/json": {
        "schema": {
          "$ref": "#/components/schemas/ArchiveOperationCreateDto"
        }
      }
    },
    "required": true
  },
  "responses": {
    "201": {
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/ArchiveOperationResponseDto"
          }
        }
      },
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Archive a selection in the background",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.update"
}
```

## Count and freeze every matching Timeline asset

POST /api/archive-operations/prepare

Counts and freezes, in one transaction, every asset of your own normal Timeline this session can see. Nothing changes until the count is confirmed.

```json
{
  "description": "Counts and freezes, in one transaction, every asset of your own normal Timeline this session can see. Nothing changes until the count is confirmed.",
  "operationId": "prepareArchiveOperation",
  "parameters": [],
  "requestBody": {
    "content": {
      "application/json": {
        "schema": {
          "$ref": "#/components/schemas/ArchiveOperationPrepareDto"
        }
      }
    },
    "required": true
  },
  "responses": {
    "201": {
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/ArchiveOperationResponseDto"
          }
        }
      },
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Count and freeze every matching Timeline asset",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.update"
}
```

## Retrieve an archive operation

GET /api/archive-operations/{id}



```json
{
  "operationId": "getArchiveOperation",
  "parameters": [
    {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
        "type": "string"
      }
    }
  ],
  "responses": {
    "200": {
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/ArchiveOperationResponseDto"
          }
        }
      },
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Retrieve an archive operation",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.update"
}
```

## Confirm a prepared archive selection

POST /api/archive-operations/{id}/confirm



```json
{
  "operationId": "confirmArchiveOperation",
  "parameters": [
    {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
        "type": "string"
      }
    }
  ],
  "requestBody": {
    "content": {
      "application/json": {
        "schema": {
          "$ref": "#/components/schemas/ArchiveOperationConfirmDto"
        }
      }
    },
    "required": true
  },
  "responses": {
    "200": {
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/ArchiveOperationResponseDto"
          }
        }
      },
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Confirm a prepared archive selection",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.update"
}
```

## Undo an archive operation

POST /api/archive-operations/{id}/undo

Restores, in the background, every item the archive changed that nothing has changed since. A running archive is stopped first.

```json
{
  "description": "Restores, in the background, every item the archive changed that nothing has changed since. A running archive is stopped first.",
  "operationId": "undoArchiveOperation",
  "parameters": [
    {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
        "type": "string"
      }
    }
  ],
  "requestBody": {
    "content": {
      "application/json": {
        "schema": {
          "$ref": "#/components/schemas/ArchiveOperationUndoDto"
        }
      }
    },
    "required": true
  },
  "responses": {
    "200": {
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/ArchiveOperationResponseDto"
          }
        }
      },
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Undo an archive operation",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.update"
}
```

## Delete assets

DELETE /api/assets

Deletes multiple assets at the same time.

```json
{
  "description": "Deletes multiple assets at the same time.",
  "operationId": "deleteAssets",
  "parameters": [],
  "requestBody": {
    "content": {
      "application/json": {
        "schema": {
          "$ref": "#/components/schemas/AssetBulkDeleteDto"
        }
      }
    },
    "required": true
  },
  "responses": {
    "204": {
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Delete assets",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.delete"
}
```

## Upload asset

POST /api/assets

Uploads a new asset to the server.

```json
{
  "description": "Uploads a new asset to the server.",
  "operationId": "uploadAsset",
  "parameters": [
    {
      "name": "key",
      "required": false,
      "in": "query",
      "schema": {
        "type": "string"
      }
    },
    {
      "name": "slug",
      "required": false,
      "in": "query",
      "schema": {
        "type": "string"
      }
    }
  ],
  "requestBody": {
    "content": {
      "multipart/form-data": {
        "schema": {
          "$ref": "#/components/schemas/AssetMediaCreateDto"
        }
      }
    },
    "description": "Asset Upload Information",
    "required": true
  },
  "responses": {
    "200": {
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/AssetMediaResponseDto"
          }
        }
      },
      "description": "Asset is a duplicate"
    },
    "201": {
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/AssetMediaResponseDto"
          }
        }
      },
      "description": "Asset uploaded successfully"
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Upload asset",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.upload"
}
```

## Update assets

PUT /api/assets

Updates multiple assets at the same time.

```json
{
  "deprecated": true,
  "description": "Updates multiple assets at the same time.",
  "operationId": "updateAssets",
  "parameters": [],
  "requestBody": {
    "content": {
      "application/json": {
        "schema": {
          "$ref": "#/components/schemas/AssetBulkUpdateDto"
        }
      }
    },
    "required": true
  },
  "responses": {
    "204": {
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Update assets",
  "tags": [
    "Assets",
    "Deprecated"
  ],
  "x-frameleaf-permission": "asset.update"
}
```

## Check bulk upload

POST /api/assets/bulk-upload-check

Determine which assets have already been uploaded to the server based on their SHA1 checksums.

```json
{
  "description": "Determine which assets have already been uploaded to the server based on their SHA1 checksums.",
  "operationId": "checkBulkUpload",
  "parameters": [],
  "requestBody": {
    "content": {
      "application/json": {
        "schema": {
          "$ref": "#/components/schemas/AssetBulkUploadCheckDto"
        }
      }
    },
    "required": true
  },
  "responses": {
    "200": {
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/AssetBulkUploadCheckResponseDto"
          }
        }
      },
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Check bulk upload",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.upload"
}
```

## Copy asset

PUT /api/assets/copy

Copy asset information like albums, tags, etc. from one asset to another.

```json
{
  "description": "Copy asset information like albums, tags, etc. from one asset to another.",
  "operationId": "copyAsset",
  "parameters": [],
  "requestBody": {
    "content": {
      "application/json": {
        "schema": {
          "$ref": "#/components/schemas/AssetCopyDto"
        }
      }
    },
    "required": true
  },
  "responses": {
    "204": {
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Copy asset",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.copy"
}
```

## Run an asset job

POST /api/assets/jobs

Run a specific job on a set of assets.

```json
{
  "description": "Run a specific job on a set of assets.",
  "operationId": "runAssetJobs",
  "parameters": [],
  "requestBody": {
    "content": {
      "application/json": {
        "schema": {
          "$ref": "#/components/schemas/AssetJobsDto"
        }
      }
    },
    "required": true
  },
  "responses": {
    "204": {
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Run an asset job",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "job.create"
}
```

## Lock assets

POST /api/assets/lock

Locks assets: they keep their albums and organization, are hidden from every view except the Locked view of their owner in a PIN-unlocked session, and stacks and live photos lock as a whole.

```json
{
  "description": "Locks assets: they keep their albums and organization, are hidden from every view except the Locked view of their owner in a PIN-unlocked session, and stacks and live photos lock as a whole.",
  "operationId": "lockAssets",
  "parameters": [],
  "requestBody": {
    "content": {
      "application/json": {
        "schema": {
          "$ref": "#/components/schemas/BulkIdsDto"
        }
      }
    },
    "required": true
  },
  "responses": {
    "204": {
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Lock assets",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.update"
}
```

## Delete asset metadata

DELETE /api/assets/metadata

Delete metadata key-value pairs for multiple assets.

```json
{
  "description": "Delete metadata key-value pairs for multiple assets.",
  "operationId": "deleteBulkAssetMetadata",
  "parameters": [],
  "requestBody": {
    "content": {
      "application/json": {
        "schema": {
          "$ref": "#/components/schemas/AssetMetadataBulkDeleteDto"
        }
      }
    },
    "required": true
  },
  "responses": {
    "204": {
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Delete asset metadata",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.update"
}
```

## Upsert asset metadata

PUT /api/assets/metadata

Upsert metadata key-value pairs for multiple assets.

```json
{
  "description": "Upsert metadata key-value pairs for multiple assets.",
  "operationId": "updateBulkAssetMetadata",
  "parameters": [],
  "requestBody": {
    "content": {
      "application/json": {
        "schema": {
          "$ref": "#/components/schemas/AssetMetadataBulkUpsertDto"
        }
      }
    },
    "required": true
  },
  "responses": {
    "200": {
      "content": {
        "application/json": {
          "schema": {
            "items": {
              "$ref": "#/components/schemas/AssetMetadataBulkResponseDto"
            },
            "type": "array"
          }
        }
      },
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Upsert asset metadata",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.update"
}
```

## Get asset statistics

GET /api/assets/statistics

Retrieve various statistics about the assets owned by the authenticated user.

```json
{
  "description": "Retrieve various statistics about the assets owned by the authenticated user.",
  "operationId": "getAssetStatistics",
  "parameters": [
    {
      "name": "isFavorite",
      "required": false,
      "in": "query",
      "description": "Filter by favorite status",
      "schema": {
        "type": "boolean"
      }
    },
    {
      "name": "isTrashed",
      "required": false,
      "in": "query",
      "description": "Filter by trash status",
      "schema": {
        "type": "boolean"
      }
    },
    {
      "name": "visibility",
      "required": false,
      "in": "query",
      "schema": {
        "$ref": "#/components/schemas/AssetVisibility"
      }
    }
  ],
  "responses": {
    "200": {
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/AssetStatsResponseDto"
          }
        }
      },
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Get asset statistics",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.statistics"
}
```

## Unlock assets

POST /api/assets/unlock

Unlocks assets the caller owns, whatever locked them, returning each exactly where it was. Requires a PIN-unlocked session.

```json
{
  "description": "Unlocks assets the caller owns, whatever locked them, returning each exactly where it was. Requires a PIN-unlocked session.",
  "operationId": "unlockAssets",
  "parameters": [],
  "requestBody": {
    "content": {
      "application/json": {
        "schema": {
          "$ref": "#/components/schemas/BulkIdsDto"
        }
      }
    },
    "required": true
  },
  "responses": {
    "204": {
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Unlock assets",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.update"
}
```

## Get resumable asset upload limits

OPTIONS /api/assets/uploads



```json
{
  "operationId": "getAssetUploadResourceLimits",
  "parameters": [],
  "responses": {
    "204": {
      "description": "Resumable upload limits"
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Get resumable asset upload limits",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.upload"
}
```

## Create resumable asset upload

POST /api/assets/uploads

IETF resumable upload draft 12 / interop 9 prerequisite. Single resources publish by default; explicitly declared Live Photo resources stay private until pair commit.

```json
{
  "description": "IETF resumable upload draft 12 / interop 9 prerequisite. Single resources publish by default; explicitly declared Live Photo resources stay private until pair commit.",
  "operationId": "createAssetUploadResource",
  "parameters": [
    {
      "name": "Asset-Metadata",
      "in": "header",
      "description": "Canonical base64url UTF-8 JSON: filename, fileCreatedAt, fileModifiedAt; optional duration (integer milliseconds), isFavorite (JSON boolean; the strings \"true\" and \"false\" are also accepted), visibility, metadata array and publication: live-photo to defer publication until atomic pair commit. No sidecar or pre-existing asset references.",
      "required": true,
      "schema": {
        "type": "string"
      }
    },
    {
      "name": "Repr-Digest",
      "in": "header",
      "description": "RFC 9530 single sha-256=:base64: digest of the entire file, required before any publication",
      "required": true,
      "schema": {
        "type": "string"
      }
    },
    {
      "name": "Upload-Complete",
      "in": "header",
      "required": true,
      "schema": {
        "type": "string",
        "enum": [
          "?0",
          "?1"
        ]
      }
    },
    {
      "name": "Upload-Draft-Interop-Version",
      "in": "header",
      "required": true,
      "schema": {
        "type": "string",
        "enum": [
          "9"
        ]
      }
    },
    {
      "name": "Upload-Length",
      "in": "header",
      "required": false,
      "schema": {
        "type": "integer",
        "minimum": 1,
        "maximum": 2147483648
      }
    }
  ],
  "requestBody": {
    "content": {
      "audio/*": {
        "schema": {
          "format": "binary",
          "type": "string"
        }
      },
      "image/*": {
        "schema": {
          "format": "binary",
          "type": "string"
        }
      },
      "video/*": {
        "schema": {
          "format": "binary",
          "type": "string"
        }
      }
    },
    "required": true
  },
  "responses": {
    "104": {
      "description": "Committed private upload resource exists; Location identifies resumable state"
    },
    "200": {
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/AssetUploadResultDto"
          }
        }
      },
      "description": ""
    },
    "201": {
      "description": "Private upload resource created, incomplete bytes are never an asset"
    },
    "202": {
      "description": "Complete bytes verified; ingestion remains pending"
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Create resumable asset upload",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.upload"
}
```

## Commit two verified Live Photo upload resources atomically

POST /api/assets/uploads/live-photo/commit



```json
{
  "operationId": "commitLivePhotoUpload",
  "parameters": [],
  "requestBody": {
    "content": {
      "application/json": {
        "schema": {
          "$ref": "#/components/schemas/LivePhotoUploadCommitDto"
        }
      }
    },
    "required": true
  },
  "responses": {
    "200": {
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/LivePhotoUploadResultDto"
          }
        }
      },
      "description": ""
    },
    "202": {
      "description": "Both assets committed atomically; required ingestion remains pending"
    },
    "409": {
      "description": "Incompatible pair, existing unrelated duplicate, or concurrent request"
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Commit two verified Live Photo upload resources atomically",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.upload"
}
```

## Cancel an unpublished upload

DELETE /api/assets/uploads/{id}



```json
{
  "operationId": "cancelAssetUploadResource",
  "parameters": [
    {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
        "type": "string"
      }
    }
  ],
  "responses": {
    "204": {
      "description": "Upload cancelled"
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Cancel an unpublished upload",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.upload"
}
```

## Get durable upload offset

HEAD /api/assets/uploads/{id}



```json
{
  "operationId": "getAssetUploadResourceOffset",
  "parameters": [
    {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
        "type": "string"
      }
    }
  ],
  "responses": {
    "204": {
      "description": "Durable acknowledged offset; completion only after final processing",
      "headers": {
        "Upload-Complete": {
          "schema": {
            "enum": [
              "?0",
              "?1"
            ],
            "type": "string"
          }
        },
        "Upload-Offset": {
          "schema": {
            "minimum": 0,
            "type": "integer"
          }
        }
      }
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Get durable upload offset",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.upload"
}
```

## Append immutable upload bytes

PATCH /api/assets/uploads/{id}



```json
{
  "operationId": "appendAssetUploadResource",
  "parameters": [
    {
      "name": "Upload-Complete",
      "in": "header",
      "required": true,
      "schema": {
        "type": "string",
        "enum": [
          "?0",
          "?1"
        ]
      }
    },
    {
      "name": "Upload-Draft-Interop-Version",
      "in": "header",
      "required": true,
      "schema": {
        "type": "string",
        "enum": [
          "9"
        ]
      }
    },
    {
      "name": "Upload-Offset",
      "in": "header",
      "required": true,
      "schema": {
        "type": "integer",
        "minimum": 0
      }
    },
    {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
        "type": "string"
      }
    }
  ],
  "requestBody": {
    "content": {
      "application/partial-upload": {
        "schema": {
          "format": "binary",
          "type": "string"
        }
      }
    },
    "required": true
  },
  "responses": {
    "200": {
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/AssetUploadResultDto"
          }
        }
      },
      "description": ""
    },
    "202": {
      "description": "Same upload is pending final ingestion; retry empty completion at the durable offset"
    },
    "204": {
      "description": "Immutable append durably acknowledged",
      "headers": {
        "Upload-Complete": {
          "schema": {
            "enum": [
              "?0",
              "?1"
            ],
            "type": "string"
          }
        },
        "Upload-Offset": {
          "schema": {
            "minimum": 0,
            "type": "integer"
          }
        }
      }
    },
    "409": {
      "description": "Offset or state conflict; HEAD returns the durable acknowledged offset"
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Append immutable upload bytes",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.upload"
}
```

## Recover a completed upload result

GET /api/assets/uploads/{id}/result



```json
{
  "operationId": "getAssetUploadResourceResult",
  "parameters": [
    {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
        "type": "string"
      }
    }
  ],
  "responses": {
    "200": {
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/AssetUploadResultDto"
          }
        }
      },
      "description": ""
    },
    "202": {
      "description": "Ingestion pending; retry this same resource"
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Recover a completed upload result",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.upload"
}
```

## Retrieve an asset

GET /api/assets/{id}

Retrieve detailed information about a specific asset.

```json
{
  "description": "Retrieve detailed information about a specific asset.",
  "operationId": "getAssetInfo",
  "parameters": [
    {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
        "type": "string"
      }
    },
    {
      "name": "key",
      "required": false,
      "in": "query",
      "schema": {
        "type": "string"
      }
    },
    {
      "name": "slug",
      "required": false,
      "in": "query",
      "schema": {
        "type": "string"
      }
    }
  ],
  "responses": {
    "200": {
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/AssetResponseDto"
          }
        }
      },
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Retrieve an asset",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.read"
}
```

## Update an asset

PUT /api/assets/{id}

Update information of a specific asset.

```json
{
  "deprecated": true,
  "description": "Update information of a specific asset.",
  "operationId": "updateAsset",
  "parameters": [
    {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
        "type": "string"
      }
    }
  ],
  "requestBody": {
    "content": {
      "application/json": {
        "schema": {
          "$ref": "#/components/schemas/UpdateAssetDto"
        }
      }
    },
    "required": true
  },
  "responses": {
    "200": {
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/AssetResponseDto"
          }
        }
      },
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Update an asset",
  "tags": [
    "Assets",
    "Deprecated"
  ],
  "x-frameleaf-permission": "asset.update"
}
```

## List develop versions of an asset

GET /api/assets/{id}/develop

Every saved still-image edit recipe for the asset, newest first, with its render state and which one is current.

```json
{
  "description": "Every saved still-image edit recipe for the asset, newest first, with its render state and which one is current.",
  "operationId": "getAssetDevelop",
  "parameters": [
    {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
        "type": "string"
      }
    }
  ],
  "responses": {
    "200": {
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/AssetDevelopResponseDto"
          }
        }
      },
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "List develop versions of an asset",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.edit.get"
}
```

## Save a develop recipe as a new version

PUT /api/assets/{id}/develop

Stores the recipe as the next revision of the asset and, by default, queues the edited master render. The original file is never changed.

```json
{
  "description": "Stores the recipe as the next revision of the asset and, by default, queues the edited master render. The original file is never changed.",
  "operationId": "saveAssetDevelop",
  "parameters": [
    {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
        "type": "string"
      }
    }
  ],
  "requestBody": {
    "content": {
      "application/json": {
        "schema": {
          "$ref": "#/components/schemas/AssetDevelopSaveDto"
        }
      }
    },
    "required": true
  },
  "responses": {
    "200": {
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/AssetDevelopRevisionResponseDto"
          }
        }
      },
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Save a develop recipe as a new version",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.edit.create"
}
```

## Upload a develop artifact

POST /api/assets/{id}/develop/artifacts

keeps a subject, sky or background mask bitmap (greyscale, covering the whole original) or a Clean Up fill (RGBA, covering its area) that a client computed for this photo. Recipes reference it by the returned id, the SHA-256 of the stored PNG, so every client and the server render the same result. Uploading the same bitmap again returns the same id. A recipe that references an artifact this photo does not have is refused with `develop_artifact_missing`.

```json
{
  "description": "keeps a subject, sky or background mask bitmap (greyscale, covering the whole original) or a Clean Up fill (RGBA, covering its area) that a client computed for this photo. Recipes reference it by the returned id, the SHA-256 of the stored PNG, so every client and the server render the same result. Uploading the same bitmap again returns the same id. A recipe that references an artifact this photo does not have is refused with `develop_artifact_missing`.",
  "operationId": "uploadAssetDevelopArtifact",
  "parameters": [
    {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
        "type": "string"
      }
    }
  ],
  "requestBody": {
    "content": {
      "multipart/form-data": {
        "schema": {
          "$ref": "#/components/schemas/AssetDevelopArtifactUploadDto"
        }
      }
    },
    "description": "A mask bitmap or a generated fill for this photo",
    "required": true
  },
  "responses": {
    "201": {
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/AssetDevelopArtifactResponseDto"
          }
        }
      },
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Upload a develop artifact",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.edit.create"
}
```

## List exports of an original for editing elsewhere

GET /api/assets/{id}/develop/exports

Every recorded export of the original, newest first, and whether the original still matches it.

```json
{
  "description": "Every recorded export of the original, newest first, and whether the original still matches it.",
  "operationId": "getAssetDevelopExports",
  "parameters": [
    {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
        "type": "string"
      }
    }
  ],
  "responses": {
    "200": {
      "content": {
        "application/json": {
          "schema": {
            "items": {
              "$ref": "#/components/schemas/DevelopExportResponseDto"
            },
            "type": "array"
          }
        }
      },
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "List exports of an original for editing elsewhere",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.edit.get"
}
```

## Export an original for editing elsewhere

POST /api/assets/{id}/develop/exports

Records the SHA-256 of the original now, so a file developed from it in another application can be brought back and checked. Download the original through the ordinary download route.

```json
{
  "description": "Records the SHA-256 of the original now, so a file developed from it in another application can be brought back and checked. Download the original through the ordinary download route.",
  "operationId": "createAssetDevelopExport",
  "parameters": [
    {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
        "type": "string"
      }
    }
  ],
  "responses": {
    "201": {
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/DevelopExportResponseDto"
          }
        }
      },
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Export an original for editing elsewhere",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.edit.create"
}
```

## Bring back a file developed elsewhere

POST /api/assets/{id}/develop/imports

Checks that the file arrived intact and was developed from the original the photo has now, then keeps it as a new version and renders its preview. Nothing is kept when a check fails; the original is never changed.

```json
{
  "description": "Checks that the file arrived intact and was developed from the original the photo has now, then keeps it as a new version and renders its preview. Nothing is kept when a check fails; the original is never changed.",
  "operationId": "importAssetDevelopRendition",
  "parameters": [
    {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
        "type": "string"
      }
    }
  ],
  "requestBody": {
    "content": {
      "multipart/form-data": {
        "schema": {
          "$ref": "#/components/schemas/AssetDevelopImportDto"
        }
      }
    },
    "description": "The developed file and the original it was made from",
    "required": true
  },
  "responses": {
    "201": {
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/AssetDevelopRevisionResponseDto"
          }
        }
      },
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Bring back a file developed elsewhere",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.edit.create"
}
```

## Suggest a subject or sky mask locally

POST /api/assets/{id}/develop/masks/propose



```json
{
  "operationId": "proposeAssetDevelopMask",
  "parameters": [
    {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
        "type": "string"
      }
    }
  ],
  "requestBody": {
    "content": {
      "application/json": {
        "schema": {
          "$ref": "#/components/schemas/AssetDevelopSemanticMaskDto"
        }
      }
    },
    "required": true
  },
  "responses": {
    "201": {
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/AssetDevelopArtifactResponseDto"
          }
        }
      },
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Suggest a subject or sky mask locally",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.edit.create"
}
```

## Render a develop preview

POST /api/assets/{id}/develop/preview

Renders the recipe from the original at preview size and returns the image; nothing is stored.

```json
{
  "description": "Renders the recipe from the original at preview size and returns the image; nothing is stored.",
  "operationId": "previewAssetDevelop",
  "parameters": [
    {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
        "type": "string"
      }
    }
  ],
  "requestBody": {
    "content": {
      "application/json": {
        "schema": {
          "$ref": "#/components/schemas/AssetDevelopPreviewDto"
        }
      }
    },
    "required": true
  },
  "responses": {
    "200": {
      "content": {
        "application/octet-stream": {
          "schema": {
            "format": "binary",
            "type": "string"
          }
        }
      },
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Render a develop preview",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.edit.get"
}
```

## Revert to the original or an earlier develop version

POST /api/assets/{id}/develop/revert

Makes the named rendered version current, or the original when no version is named. History and files are kept.

```json
{
  "description": "Makes the named rendered version current, or the original when no version is named. History and files are kept.",
  "operationId": "revertAssetDevelop",
  "parameters": [
    {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
        "type": "string"
      }
    }
  ],
  "requestBody": {
    "content": {
      "application/json": {
        "schema": {
          "$ref": "#/components/schemas/AssetDevelopRevertDto"
        }
      }
    },
    "required": true
  },
  "responses": {
    "200": {
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/AssetDevelopResponseDto"
          }
        }
      },
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Revert to the original or an earlier develop version",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.edit.create"
}
```

## View a rendered develop file

GET /api/assets/{id}/develop/revisions/{revisionId}/file

Streams the edited master or the preview rendered for the version.

```json
{
  "description": "Streams the edited master or the preview rendered for the version.",
  "operationId": "viewAssetDevelopFile",
  "parameters": [
    {
      "name": "id",
      "required": true,
      "in": "path",
      "description": "Asset ID",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
        "type": "string"
      }
    },
    {
      "name": "kind",
      "required": false,
      "in": "query",
      "schema": {
        "default": "preview",
        "$ref": "#/components/schemas/AssetDevelopFileKind"
      }
    },
    {
      "name": "revisionId",
      "required": true,
      "in": "path",
      "description": "Develop revision ID",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
        "type": "string"
      }
    }
  ],
  "responses": {
    "200": {
      "content": {
        "application/octet-stream": {
          "schema": {
            "format": "binary",
            "type": "string"
          }
        }
      },
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "View a rendered develop file",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.edit.get"
}
```

## Cancel a develop render

DELETE /api/assets/{id}/develop/revisions/{revisionId}/render

Stops a queued or running render of the version. Files already rendered for other versions are untouched.

```json
{
  "description": "Stops a queued or running render of the version. Files already rendered for other versions are untouched.",
  "operationId": "cancelAssetDevelopRender",
  "parameters": [
    {
      "name": "id",
      "required": true,
      "in": "path",
      "description": "Asset ID",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
        "type": "string"
      }
    },
    {
      "name": "revisionId",
      "required": true,
      "in": "path",
      "description": "Develop revision ID",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
        "type": "string"
      }
    }
  ],
  "responses": {
    "200": {
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/AssetDevelopRevisionResponseDto"
          }
        }
      },
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Cancel a develop render",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.edit.create"
}
```

## Render a develop version

POST /api/assets/{id}/develop/revisions/{revisionId}/render

Queues (or re-queues after a failure or cancellation) the edited master render of a saved version.

```json
{
  "description": "Queues (or re-queues after a failure or cancellation) the edited master render of a saved version.",
  "operationId": "renderAssetDevelopRevision",
  "parameters": [
    {
      "name": "id",
      "required": true,
      "in": "path",
      "description": "Asset ID",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
        "type": "string"
      }
    },
    {
      "name": "revisionId",
      "required": true,
      "in": "path",
      "description": "Develop revision ID",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
        "type": "string"
      }
    }
  ],
  "responses": {
    "200": {
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/AssetDevelopRevisionResponseDto"
          }
        }
      },
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Render a develop version",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.edit.create"
}
```

## List saved video versions

GET /api/assets/{id}/edit-versions



```json
{
  "operationId": "getVideoEditVersions",
  "parameters": [
    {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
        "type": "string"
      }
    }
  ],
  "responses": {
    "200": {
      "content": {
        "application/json": {
          "schema": {
            "items": {
              "$ref": "#/components/schemas/VideoEditVersionResponseDto"
            },
            "type": "array"
          }
        }
      },
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "List saved video versions",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.edit.get"
}
```

## Export the current video version

POST /api/assets/{id}/edit-versions/export



```json
{
  "operationId": "exportVideoEditVersion",
  "parameters": [
    {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
        "type": "string"
      }
    }
  ],
  "requestBody": {
    "content": {
      "application/json": {
        "schema": {
          "$ref": "#/components/schemas/VideoEditExportDto"
        }
      }
    },
    "required": true
  },
  "responses": {
    "201": {
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/VideoEditVersionResponseDto"
          }
        }
      },
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Export the current video version",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.edit.create"
}
```

## Prune an unselected video version

DELETE /api/assets/{id}/edit-versions/{versionId}



```json
{
  "operationId": "pruneVideoEditVersion",
  "parameters": [
    {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
        "type": "string"
      }
    },
    {
      "name": "versionId",
      "required": true,
      "in": "path",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
        "type": "string"
      }
    }
  ],
  "responses": {
    "204": {
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Prune an unselected video version",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.edit.delete"
}
```

## Download a video version master

GET /api/assets/{id}/edit-versions/{versionId}/download



```json
{
  "operationId": "downloadVideoEditVersion",
  "parameters": [
    {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
        "type": "string"
      }
    },
    {
      "name": "versionId",
      "required": true,
      "in": "path",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
        "type": "string"
      }
    }
  ],
  "responses": {
    "200": {
      "content": {
        "application/octet-stream": {
          "schema": {
            "format": "binary",
            "type": "string"
          }
        }
      },
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Download a video version master",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.download"
}
```

## Restore a saved video version

POST /api/assets/{id}/edit-versions/{versionId}/restore



```json
{
  "operationId": "restoreVideoEditVersion",
  "parameters": [
    {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
        "type": "string"
      }
    },
    {
      "name": "versionId",
      "required": true,
      "in": "path",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
        "type": "string"
      }
    }
  ],
  "responses": {
    "204": {
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Restore a saved video version",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.edit.create"
}
```

## Remove edits from an existing asset

DELETE /api/assets/{id}/edits

Removes all edit actions (crop, rotate, mirror) associated with the specified asset.

```json
{
  "description": "Removes all edit actions (crop, rotate, mirror) associated with the specified asset.",
  "operationId": "removeAssetEdits",
  "parameters": [
    {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
        "type": "string"
      }
    }
  ],
  "responses": {
    "204": {
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Remove edits from an existing asset",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.edit.delete"
}
```

## Retrieve edits for an existing asset

GET /api/assets/{id}/edits

Retrieve a series of edit actions (crop, rotate, mirror) associated with the specified asset.

```json
{
  "description": "Retrieve a series of edit actions (crop, rotate, mirror) associated with the specified asset.",
  "operationId": "getAssetEdits",
  "parameters": [
    {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
        "type": "string"
      }
    }
  ],
  "responses": {
    "200": {
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/AssetEditsResponseDto"
          }
        }
      },
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Retrieve edits for an existing asset",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.edit.get"
}
```

## Apply edits to an existing asset

PUT /api/assets/{id}/edits

Apply a series of edit actions (crop, rotate, mirror) to the specified asset.

```json
{
  "description": "Apply a series of edit actions (crop, rotate, mirror) to the specified asset.",
  "operationId": "editAsset",
  "parameters": [
    {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
        "type": "string"
      }
    }
  ],
  "requestBody": {
    "content": {
      "application/json": {
        "schema": {
          "$ref": "#/components/schemas/AssetEditsCreateDto"
        }
      }
    },
    "required": true
  },
  "responses": {
    "200": {
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/AssetEditsResponseDto"
          }
        }
      },
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Apply edits to an existing asset",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.edit.create"
}
```

## List the original video's keyframes

GET /api/assets/{id}/edits/keyframes

The keyframe times of the original video, so an editor can show where a fast (keyframe) trim actually cuts. Owner's edit permission only; never the edited version.

```json
{
  "description": "The keyframe times of the original video, so an editor can show where a fast (keyframe) trim actually cuts. Owner's edit permission only; never the edited version.",
  "operationId": "getAssetEditKeyframes",
  "parameters": [
    {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
        "type": "string"
      }
    }
  ],
  "responses": {
    "200": {
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/AssetEditKeyframesResponseDto"
          }
        }
      },
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "List the original video's keyframes",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.edit.get"
}
```

## Get image enrichment metadata

GET /api/assets/{id}/image-enrichment

Retrieve private image description, tag, and NSFW detection metadata for a specific asset.

```json
{
  "description": "Retrieve private image description, tag, and NSFW detection metadata for a specific asset.",
  "operationId": "getAssetImageEnrichment",
  "parameters": [
    {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
        "type": "string"
      }
    }
  ],
  "responses": {
    "200": {
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/AssetImageEnrichmentResponseDto"
          }
        }
      },
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Get image enrichment metadata",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.update"
}
```

## Update image enrichment metadata

PUT /api/assets/{id}/image-enrichment

Run repair actions for generated image descriptions, tags, and NSFW detection metadata.

```json
{
  "description": "Run repair actions for generated image descriptions, tags, and NSFW detection metadata.",
  "operationId": "updateAssetImageEnrichment",
  "parameters": [
    {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
        "type": "string"
      }
    }
  ],
  "requestBody": {
    "content": {
      "application/json": {
        "schema": {
          "$ref": "#/components/schemas/AssetImageEnrichmentActionRequestDto"
        }
      }
    },
    "required": true
  },
  "responses": {
    "200": {
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/AssetImageEnrichmentResponseDto"
          }
        }
      },
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Update image enrichment metadata",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.update"
}
```

## Get asset metadata

GET /api/assets/{id}/metadata

Retrieve all metadata key-value pairs associated with the specified asset.

```json
{
  "description": "Retrieve all metadata key-value pairs associated with the specified asset.",
  "operationId": "getAssetMetadata",
  "parameters": [
    {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
        "type": "string"
      }
    }
  ],
  "responses": {
    "200": {
      "content": {
        "application/json": {
          "schema": {
            "items": {
              "$ref": "#/components/schemas/AssetMetadataResponseDto"
            },
            "type": "array"
          }
        }
      },
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Get asset metadata",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.read"
}
```

## Update asset metadata

PUT /api/assets/{id}/metadata

Update or add metadata key-value pairs for the specified asset.

```json
{
  "description": "Update or add metadata key-value pairs for the specified asset.",
  "operationId": "updateAssetMetadata",
  "parameters": [
    {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
        "type": "string"
      }
    }
  ],
  "requestBody": {
    "content": {
      "application/json": {
        "schema": {
          "$ref": "#/components/schemas/AssetMetadataUpsertDto"
        }
      }
    },
    "required": true
  },
  "responses": {
    "200": {
      "content": {
        "application/json": {
          "schema": {
            "items": {
              "$ref": "#/components/schemas/AssetMetadataResponseDto"
            },
            "type": "array"
          }
        }
      },
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Update asset metadata",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.update"
}
```

## Delete asset metadata by key

DELETE /api/assets/{id}/metadata/{key}

Delete a specific metadata key-value pair associated with the specified asset.

```json
{
  "description": "Delete a specific metadata key-value pair associated with the specified asset.",
  "operationId": "deleteAssetMetadata",
  "parameters": [
    {
      "name": "id",
      "required": true,
      "in": "path",
      "description": "Asset ID",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
        "type": "string"
      }
    },
    {
      "name": "key",
      "required": true,
      "in": "path",
      "description": "Metadata key",
      "schema": {
        "type": "string"
      }
    }
  ],
  "responses": {
    "204": {
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Delete asset metadata by key",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.update"
}
```

## Retrieve asset metadata by key

GET /api/assets/{id}/metadata/{key}

Retrieve the value of a specific metadata key associated with the specified asset.

```json
{
  "description": "Retrieve the value of a specific metadata key associated with the specified asset.",
  "operationId": "getAssetMetadataByKey",
  "parameters": [
    {
      "name": "id",
      "required": true,
      "in": "path",
      "description": "Asset ID",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
        "type": "string"
      }
    },
    {
      "name": "key",
      "required": true,
      "in": "path",
      "description": "Metadata key",
      "schema": {
        "type": "string"
      }
    }
  ],
  "responses": {
    "200": {
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/AssetMetadataResponseDto"
          }
        }
      },
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Retrieve asset metadata by key",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.read"
}
```

## Retrieve asset OCR data

GET /api/assets/{id}/ocr

Retrieve all OCR (Optical Character Recognition) data associated with the specified asset.

```json
{
  "description": "Retrieve all OCR (Optical Character Recognition) data associated with the specified asset.",
  "operationId": "getAssetOcr",
  "parameters": [
    {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
        "type": "string"
      }
    }
  ],
  "responses": {
    "200": {
      "content": {
        "application/json": {
          "schema": {
            "items": {
              "$ref": "#/components/schemas/AssetOcrResponseDto"
            },
            "type": "array"
          }
        }
      },
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Retrieve asset OCR data",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.read"
}
```

## Download original asset

GET /api/assets/{id}/original

Downloads the original file of the specified asset.

```json
{
  "description": "Downloads the original file of the specified asset.",
  "operationId": "downloadAsset",
  "parameters": [
    {
      "name": "edited",
      "required": false,
      "in": "query",
      "description": "Return edited asset if available",
      "schema": {
        "type": "boolean"
      }
    },
    {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
        "type": "string"
      }
    },
    {
      "name": "key",
      "required": false,
      "in": "query",
      "schema": {
        "type": "string"
      }
    },
    {
      "name": "slug",
      "required": false,
      "in": "query",
      "schema": {
        "type": "string"
      }
    }
  ],
  "responses": {
    "200": {
      "content": {
        "application/octet-stream": {
          "schema": {
            "format": "binary",
            "type": "string"
          }
        }
      },
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Download original asset",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.download"
}
```

## Discard a restoration

DELETE /api/assets/{id}/restorations/{restorationId}

Cancels anything still running, stops using the result for playback and removes every file the restoration produced. The record stays as history.

```json
{
  "description": "Cancels anything still running, stops using the result for playback and removes every file the restoration produced. The record stays as history.",
  "operationId": "discardAssetRestoration",
  "parameters": [
    {
      "name": "id",
      "required": true,
      "in": "path",
      "description": "Asset ID",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
        "type": "string"
      }
    },
    {
      "name": "restorationId",
      "required": true,
      "in": "path",
      "description": "Restoration ID",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
        "type": "string"
      }
    }
  ],
  "responses": {
    "204": {
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Discard a restoration",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.edit.create"
}
```

## View a restoration file

GET /api/assets/{id}/restorations/{restorationId}/file

Streams the preview input, the restored preview, the full result or its playback rendition.

```json
{
  "description": "Streams the preview input, the restored preview, the full result or its playback rendition.",
  "operationId": "viewAssetRestorationFile",
  "parameters": [
    {
      "name": "id",
      "required": true,
      "in": "path",
      "description": "Asset ID",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
        "type": "string"
      }
    },
    {
      "name": "kind",
      "required": false,
      "in": "query",
      "schema": {
        "default": "after",
        "$ref": "#/components/schemas/AssetRestorationFileKind"
      }
    },
    {
      "name": "restorationId",
      "required": true,
      "in": "path",
      "description": "Restoration ID",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
        "type": "string"
      }
    }
  ],
  "responses": {
    "200": {
      "content": {
        "application/octet-stream": {
          "schema": {
            "format": "binary",
            "type": "string"
          }
        }
      },
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "View a restoration file",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.edit.get"
}
```

## View asset thumbnail

GET /api/assets/{id}/thumbnail

Retrieve the thumbnail image for the specified asset. Viewing the fullsize thumbnail might redirect to downloadAsset, which requires a different permission.

```json
{
  "description": "Retrieve the thumbnail image for the specified asset. Viewing the fullsize thumbnail might redirect to downloadAsset, which requires a different permission.",
  "operationId": "viewAsset",
  "parameters": [
    {
      "name": "edited",
      "required": false,
      "in": "query",
      "description": "Return edited asset if available",
      "schema": {
        "type": "boolean"
      }
    },
    {
      "name": "faceSource",
      "required": false,
      "in": "query",
      "description": "Return the ordinary edited preview used for face coordinates",
      "schema": {
        "type": "boolean"
      }
    },
    {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
        "type": "string"
      }
    },
    {
      "name": "key",
      "required": false,
      "in": "query",
      "schema": {
        "type": "string"
      }
    },
    {
      "name": "size",
      "required": false,
      "in": "query",
      "schema": {
        "$ref": "#/components/schemas/AssetMediaSize"
      }
    },
    {
      "name": "slug",
      "required": false,
      "in": "query",
      "schema": {
        "type": "string"
      }
    }
  ],
  "responses": {
    "200": {
      "content": {
        "application/octet-stream": {
          "schema": {
            "format": "binary",
            "type": "string"
          }
        }
      },
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "View asset thumbnail",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.view"
}
```

## Play asset video

GET /api/assets/{id}/video/playback

Streams the video file for the specified asset. This endpoint also supports byte range requests.

```json
{
  "description": "Streams the video file for the specified asset. This endpoint also supports byte range requests.",
  "operationId": "playAssetVideo",
  "parameters": [
    {
      "name": "edited",
      "required": false,
      "in": "query",
      "description": "Play the edited version when one exists (default). false plays the unedited source for the asset's owner, as the quick editor needs; everyone else is always given the edited version",
      "schema": {
        "type": "boolean"
      }
    },
    {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
        "type": "string"
      }
    },
    {
      "name": "key",
      "required": false,
      "in": "query",
      "schema": {
        "type": "string"
      }
    },
    {
      "name": "slug",
      "required": false,
      "in": "query",
      "schema": {
        "type": "string"
      }
    }
  ],
  "responses": {
    "200": {
      "content": {
        "application/octet-stream": {
          "schema": {
            "format": "binary",
            "type": "string"
          }
        }
      },
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Play asset video",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.view"
}
```

## Get HLS main playlist

GET /api/assets/{id}/video/stream/main.m3u8

Returns an HLS main playlist with all available variants for the asset.

```json
{
  "description": "Returns an HLS main playlist with all available variants for the asset.",
  "operationId": "getMainPlaylist",
  "parameters": [
    {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
        "type": "string"
      }
    },
    {
      "name": "key",
      "required": false,
      "in": "query",
      "schema": {
        "type": "string"
      }
    },
    {
      "name": "slug",
      "required": false,
      "in": "query",
      "schema": {
        "type": "string"
      }
    }
  ],
  "responses": {
    "200": {
      "content": {
        "application/vnd.apple.mpegurl": {
          "schema": {
            "type": "string"
          }
        }
      },
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Get HLS main playlist",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.view"
}
```

## End HLS streaming session

DELETE /api/assets/{id}/video/stream/{sessionId}

Releases server resources for the streaming session.

```json
{
  "description": "Releases server resources for the streaming session.",
  "operationId": "endSession",
  "parameters": [
    {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
        "type": "string"
      }
    },
    {
      "name": "key",
      "required": false,
      "in": "query",
      "schema": {
        "type": "string"
      }
    },
    {
      "name": "sessionId",
      "required": true,
      "in": "path",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
        "type": "string"
      }
    },
    {
      "name": "slug",
      "required": false,
      "in": "query",
      "schema": {
        "type": "string"
      }
    }
  ],
  "responses": {
    "204": {
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "End HLS streaming session",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.view"
}
```

## Get HLS media playlist

GET /api/assets/{id}/video/stream/{sessionId}/{variantIndex}/playlist.m3u8

Returns an HLS media playlist for one variant of the streaming session.

```json
{
  "description": "Returns an HLS media playlist for one variant of the streaming session.",
  "operationId": "getMediaPlaylist",
  "parameters": [
    {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
        "type": "string"
      }
    },
    {
      "name": "key",
      "required": false,
      "in": "query",
      "schema": {
        "type": "string"
      }
    },
    {
      "name": "sessionId",
      "required": true,
      "in": "path",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
        "type": "string"
      }
    },
    {
      "name": "slug",
      "required": false,
      "in": "query",
      "schema": {
        "type": "string"
      }
    },
    {
      "name": "variantIndex",
      "required": true,
      "in": "path",
      "schema": {
        "minimum": 0,
        "maximum": 9007199254740991,
        "type": "integer"
      }
    },
    {
      "name": "x-immich-hls-pos",
      "required": false,
      "in": "header",
      "schema": {
        "minimum": 0,
        "type": "number"
      }
    }
  ],
  "responses": {
    "200": {
      "content": {
        "application/vnd.apple.mpegurl": {
          "schema": {
            "type": "string"
          }
        }
      },
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Get HLS media playlist",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.view"
}
```

## Get HLS segment or init file

GET /api/assets/{id}/video/stream/{sessionId}/{variantIndex}/{filename}

Streams an HLS init segment (init.mp4) or media segment (seg_N.m4s).

```json
{
  "description": "Streams an HLS init segment (init.mp4) or media segment (seg_N.m4s).",
  "operationId": "getSegment",
  "parameters": [
    {
      "name": "filename",
      "required": true,
      "in": "path",
      "schema": {
        "pattern": "^(init\\.mp4|seg_\\d+\\.m4s)$",
        "type": "string"
      }
    },
    {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
        "type": "string"
      }
    },
    {
      "name": "key",
      "required": false,
      "in": "query",
      "schema": {
        "type": "string"
      }
    },
    {
      "name": "sessionId",
      "required": true,
      "in": "path",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
        "type": "string"
      }
    },
    {
      "name": "slug",
      "required": false,
      "in": "query",
      "schema": {
        "type": "string"
      }
    },
    {
      "name": "variantIndex",
      "required": true,
      "in": "path",
      "schema": {
        "minimum": 0,
        "maximum": 9007199254740991,
        "type": "integer"
      }
    },
    {
      "name": "x-immich-hls-msn",
      "required": false,
      "in": "header",
      "schema": {
        "minimum": 0,
        "maximum": 9007199254740991,
        "type": "integer"
      }
    }
  ],
  "responses": {
    "200": {
      "content": {
        "application/octet-stream": {
          "schema": {
            "format": "binary",
            "type": "string"
          }
        }
      },
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Get HLS segment or init file",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.view"
}
```

## Play the Studio HDR intermediate

GET /api/assets/{id}/video/studio-hdr

streams the 10-bit AV1 intermediate that keeps an HDR video’s BT.2020 PQ or HLG signal, for the Studio editor. Not found until it has been made (placing the video in a Studio project queues it). Supports byte range requests.

```json
{
  "description": "streams the 10-bit AV1 intermediate that keeps an HDR video’s BT.2020 PQ or HLG signal, for the Studio editor. Not found until it has been made (placing the video in a Studio project queues it). Supports byte range requests.",
  "operationId": "playStudioHdrVideo",
  "parameters": [
    {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
        "type": "string"
      }
    }
  ],
  "responses": {
    "200": {
      "content": {
        "application/octet-stream": {
          "schema": {
            "format": "binary",
            "type": "string"
          }
        }
      },
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Play the Studio HDR intermediate",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.view"
}
```

## List develop presets

GET /api/develop-presets

Your saved develop presets, by name.

```json
{
  "description": "Your saved develop presets, by name.",
  "operationId": "getDevelopPresets",
  "parameters": [],
  "responses": {
    "200": {
      "content": {
        "application/json": {
          "schema": {
            "items": {
              "$ref": "#/components/schemas/DevelopPresetResponseDto"
            },
            "type": "array"
          }
        }
      },
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "List develop presets",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "all"
}
```

## Save a develop preset

POST /api/develop-presets

Saves develop settings (sliders, look, strength and masks, never geometry) under a new name.

```json
{
  "description": "Saves develop settings (sliders, look, strength and masks, never geometry) under a new name.",
  "operationId": "createDevelopPreset",
  "parameters": [],
  "requestBody": {
    "content": {
      "application/json": {
        "schema": {
          "$ref": "#/components/schemas/DevelopPresetCreateDto"
        }
      }
    },
    "required": true
  },
  "responses": {
    "201": {
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/DevelopPresetResponseDto"
          }
        }
      },
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Save a develop preset",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "all"
}
```

## Delete a develop preset

DELETE /api/develop-presets/{id}

Deletes the preset. Versions already saved with its settings are unchanged.

```json
{
  "description": "Deletes the preset. Versions already saved with its settings are unchanged.",
  "operationId": "deleteDevelopPreset",
  "parameters": [
    {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
        "type": "string"
      }
    }
  ],
  "responses": {
    "204": {
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Delete a develop preset",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "all"
}
```

## Update a develop preset

PUT /api/develop-presets/{id}

Renames a preset, changes its settings, or both. Settings the request leaves out keep their stored values.

```json
{
  "description": "Renames a preset, changes its settings, or both. Settings the request leaves out keep their stored values.",
  "operationId": "updateDevelopPreset",
  "parameters": [
    {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
        "type": "string"
      }
    }
  ],
  "requestBody": {
    "content": {
      "application/json": {
        "schema": {
          "$ref": "#/components/schemas/DevelopPresetUpdateDto"
        }
      }
    },
    "required": true
  },
  "responses": {
    "200": {
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/DevelopPresetResponseDto"
          }
        }
      },
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Update a develop preset",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "all"
}
```

## List Google Photos imports

GET /api/takeout



```json
{
  "operationId": "listTakeoutImports",
  "parameters": [],
  "responses": {
    "200": {
      "content": {
        "application/json": {
          "schema": {
            "items": {
              "$ref": "#/components/schemas/TakeoutResponseDto"
            },
            "type": "array"
          }
        }
      },
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "List Google Photos imports",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.upload"
}
```

## Start a Google Photos import

POST /api/takeout

Creates an import to stage Takeout archives into. Administrators may instead name a folder inside one of the permitted import locations.

```json
{
  "description": "Creates an import to stage Takeout archives into. Administrators may instead name a folder inside one of the permitted import locations.",
  "operationId": "createTakeoutImport",
  "parameters": [],
  "requestBody": {
    "content": {
      "application/json": {
        "schema": {
          "$ref": "#/components/schemas/TakeoutCreateDto"
        }
      }
    },
    "required": true
  },
  "responses": {
    "201": {
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/TakeoutResponseDto"
          }
        }
      },
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Start a Google Photos import",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.upload"
}
```

## List the permitted import locations

GET /api/takeout/roots



```json
{
  "operationId": "getTakeoutRoots",
  "parameters": [],
  "responses": {
    "200": {
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/TakeoutRootsResponseDto"
          }
        }
      },
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "List the permitted import locations",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-admin-only": true,
  "x-frameleaf-permission": "all"
}
```

## Delete a Google Photos import

DELETE /api/takeout/{id}

Removes the import and its staged copies. Everything it brought into the library stays there.

```json
{
  "description": "Removes the import and its staged copies. Everything it brought into the library stays there.",
  "operationId": "deleteTakeoutImport",
  "parameters": [
    {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
        "type": "string"
      }
    }
  ],
  "responses": {
    "204": {
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Delete a Google Photos import",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.upload"
}
```

## Get a Google Photos import

GET /api/takeout/{id}



```json
{
  "operationId": "getTakeoutImport",
  "parameters": [
    {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
        "type": "string"
      }
    }
  ],
  "responses": {
    "200": {
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/TakeoutResponseDto"
          }
        }
      },
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Get a Google Photos import",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.upload"
}
```

## Stage a Takeout archive

POST /api/takeout/{id}/archives



```json
{
  "operationId": "createTakeoutArchive",
  "parameters": [
    {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
        "type": "string"
      }
    }
  ],
  "requestBody": {
    "content": {
      "application/json": {
        "schema": {
          "$ref": "#/components/schemas/TakeoutArchiveCreateDto"
        }
      }
    },
    "required": true
  },
  "responses": {
    "201": {
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/TakeoutSourceResponseDto"
          }
        }
      },
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Stage a Takeout archive",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.upload"
}
```

## Remove a staged Takeout archive

DELETE /api/takeout/{id}/archives/{archiveId}



```json
{
  "operationId": "deleteTakeoutArchive",
  "parameters": [
    {
      "name": "archiveId",
      "required": true,
      "in": "path",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
        "type": "string"
      }
    },
    {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
        "type": "string"
      }
    }
  ],
  "responses": {
    "204": {
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Remove a staged Takeout archive",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.upload"
}
```

## Upload part of a Takeout archive

PUT /api/takeout/{id}/archives/{archiveId}/chunks

Appends up to 8 MiB at the given byte offset. Repeating a part already staged is harmless.

```json
{
  "description": "Appends up to 8 MiB at the given byte offset. Repeating a part already staged is harmless.",
  "operationId": "uploadTakeoutArchiveChunk",
  "parameters": [
    {
      "name": "archiveId",
      "required": true,
      "in": "path",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
        "type": "string"
      }
    },
    {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
        "type": "string"
      }
    },
    {
      "name": "offset",
      "required": true,
      "in": "query",
      "description": "Byte offset of this chunk",
      "schema": {
        "minimum": 0,
        "maximum": 1099511627776,
        "type": "integer"
      }
    }
  ],
  "requestBody": {
    "content": {
      "application/octet-stream": {
        "schema": {
          "format": "binary",
          "type": "string"
        }
      }
    },
    "required": true
  },
  "responses": {
    "200": {
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/TakeoutSourceResponseDto"
          }
        }
      },
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Upload part of a Takeout archive",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.upload"
}
```

## Check a staged part of a Takeout archive

POST /api/takeout/{id}/archives/{archiveId}/verify

Compares a range already uploaded with the file the browser is about to resume from.

```json
{
  "description": "Compares a range already uploaded with the file the browser is about to resume from.",
  "operationId": "verifyTakeoutArchiveChunk",
  "parameters": [
    {
      "name": "archiveId",
      "required": true,
      "in": "path",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
        "type": "string"
      }
    },
    {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
        "type": "string"
      }
    }
  ],
  "requestBody": {
    "content": {
      "application/json": {
        "schema": {
          "$ref": "#/components/schemas/TakeoutVerifyChunkDto"
        }
      }
    },
    "required": true
  },
  "responses": {
    "204": {
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Check a staged part of a Takeout archive",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.upload"
}
```

## Pause, resume or cancel a Google Photos import

POST /api/takeout/{id}/control



```json
{
  "operationId": "controlTakeoutImport",
  "parameters": [
    {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
        "type": "string"
      }
    }
  ],
  "requestBody": {
    "content": {
      "application/json": {
        "schema": {
          "$ref": "#/components/schemas/TakeoutControlDto"
        }
      }
    },
    "required": true
  },
  "responses": {
    "200": {
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/TakeoutResponseDto"
          }
        }
      },
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Pause, resume or cancel a Google Photos import",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.upload"
}
```

## Import the reviewed items

POST /api/takeout/{id}/import

Queues the import as a background job with these choices. Items already in the library are matched, not copied again, and keep their album memberships.

```json
{
  "description": "Queues the import as a background job with these choices. Items already in the library are matched, not copied again, and keep their album memberships.",
  "operationId": "startTakeoutImport",
  "parameters": [
    {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
        "type": "string"
      }
    }
  ],
  "requestBody": {
    "content": {
      "application/json": {
        "schema": {
          "$ref": "#/components/schemas/TakeoutOptionsDto"
        }
      }
    },
    "required": true
  },
  "responses": {
    "200": {
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/TakeoutResponseDto"
          }
        }
      },
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Import the reviewed items",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.upload"
}
```

## List the items of a Google Photos import

GET /api/takeout/{id}/items



```json
{
  "operationId": "getTakeoutItems",
  "parameters": [
    {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
        "type": "string"
      }
    },
    {
      "name": "limit",
      "required": false,
      "in": "query",
      "description": "Items to return",
      "schema": {
        "minimum": 1,
        "maximum": 200,
        "default": 100,
        "type": "integer"
      }
    },
    {
      "name": "offset",
      "required": false,
      "in": "query",
      "description": "Items to skip",
      "schema": {
        "minimum": 0,
        "maximum": 9007199254740991,
        "default": 0,
        "type": "integer"
      }
    },
    {
      "name": "state",
      "required": false,
      "in": "query",
      "schema": {
        "$ref": "#/components/schemas/TakeoutItemState"
      }
    }
  ],
  "responses": {
    "200": {
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/TakeoutItemsResponseDto"
          }
        }
      },
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "List the items of a Google Photos import",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.upload"
}
```

## Choose metadata for an item, or leave it out

PUT /api/takeout/{id}/items/{itemId}



```json
{
  "operationId": "resolveTakeoutItem",
  "parameters": [
    {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
        "type": "string"
      }
    },
    {
      "name": "itemId",
      "required": true,
      "in": "path",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
        "type": "string"
      }
    }
  ],
  "requestBody": {
    "content": {
      "application/json": {
        "schema": {
          "$ref": "#/components/schemas/TakeoutResolveDto"
        }
      }
    },
    "required": true
  },
  "responses": {
    "200": {
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/TakeoutResponseDto"
          }
        }
      },
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Choose metadata for an item, or leave it out",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.upload"
}
```

## List possible Live Photos in a Google Photos import

GET /api/takeout/{id}/live-photos



```json
{
  "operationId": "getTakeoutPairs",
  "parameters": [
    {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
        "type": "string"
      }
    },
    {
      "name": "limit",
      "required": false,
      "in": "query",
      "description": "Pairs to return",
      "schema": {
        "minimum": 1,
        "maximum": 200,
        "default": 100,
        "type": "integer"
      }
    },
    {
      "name": "offset",
      "required": false,
      "in": "query",
      "description": "Pairs to skip",
      "schema": {
        "minimum": 0,
        "maximum": 9007199254740991,
        "default": 0,
        "type": "integer"
      }
    },
    {
      "name": "state",
      "required": false,
      "in": "query",
      "schema": {
        "$ref": "#/components/schemas/TakeoutPairState"
      }
    }
  ],
  "responses": {
    "200": {
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/TakeoutPairsResponseDto"
          }
        }
      },
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "List possible Live Photos in a Google Photos import",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.upload"
}
```

## Link or separate a possible Live Photo

PUT /api/takeout/{id}/live-photos



```json
{
  "operationId": "decideTakeoutPair",
  "parameters": [
    {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
        "type": "string"
      }
    }
  ],
  "requestBody": {
    "content": {
      "application/json": {
        "schema": {
          "$ref": "#/components/schemas/TakeoutPairDecisionDto"
        }
      }
    },
    "required": true
  },
  "responses": {
    "200": {
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/TakeoutPairsResponseDto"
          }
        }
      },
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Link or separate a possible Live Photo",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.upload"
}
```

## Scan a Google Photos import

POST /api/takeout/{id}/scan

Queues the scan of the staged sources as a background job that continues after the browser closes.

```json
{
  "description": "Queues the scan of the staged sources as a background job that continues after the browser closes.",
  "operationId": "scanTakeoutImport",
  "parameters": [
    {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
        "type": "string"
      }
    }
  ],
  "responses": {
    "200": {
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/TakeoutResponseDto"
          }
        }
      },
      "description": ""
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "summary": "Scan a Google Photos import",
  "tags": [
    "Assets"
  ],
  "x-frameleaf-permission": "asset.upload"
}
```
