{
  "openapi": "3.1.2",
  "info": {
    "title": "Media2URL Developer Platform REST API",
    "version": "1.0.0",
    "description": "Official public external REST API for Media2URL. Provides direct Cloudflare R2 presigned file uploads with temporary-to-final object promotion, transactional quota reservations, asset management, version history, duplicate detection, and remote URL imports.",
    "contact": {
      "name": "Media2URL Developer Platform",
      "url": "https://media2url.com/contact",
      "email": "security@media2url.com"
    },
    "license": {
      "name": "Proprietary",
      "url": "https://media2url.com/terms"
    }
  },
  "servers": [
    {
      "url": "https://api.media2url.com/v1",
      "description": "Production API v1"
    }
  ],
  "security": [
    {
      "BearerAuth": []
    }
  ],
  "paths": {
    "/usage": {
      "get": {
        "operationId": "getUsage",
        "summary": "Retrieve Account & API Usage",
        "description": "Returns authoritative usage metrics for storage, bandwidth, and monthly upload counts.",
        "security": [
          {
            "BearerAuth": [
              "usage:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Authoritative usage metrics",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UsageResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/uploads/presign": {
      "post": {
        "operationId": "presignUpload",
        "summary": "Request Direct R2 Upload URL",
        "description": "Validates file metadata against account quotas, atomically reserves storage capacity, and generates a short-lived presigned PUT URL targeting a temporary R2 key.",
        "security": [
          {
            "BearerAuth": [
              "uploads:write"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PresignUploadRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Temporary upload URL generated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PresignUploadResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/uploads/finalize": {
      "post": {
        "operationId": "finalizeUpload",
        "summary": "Finalize Upload & Promote Asset",
        "description": "Atomically consumes the upload session, validates temporary R2 object size, content type, magic bytes, and blocked fingerprints, promotes the validated bytes into a non-presigned final key, commits quota, and returns the canonical asset links.",
        "security": [
          {
            "BearerAuth": [
              "uploads:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 128
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FinalizeUploadRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Asset created and promoted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AssetResource"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "410": {
            "$ref": "#/components/responses/Gone"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/uploads/check-duplicate": {
      "post": {
        "operationId": "checkDuplicate",
        "summary": "Check for Duplicate Asset",
        "description": "Searches within the authenticated account's scope for an existing asset matching the given SHA-256 checksum and optional byte size.",
        "security": [
          {
            "BearerAuth": [
              "assets:read"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CheckDuplicateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Duplicate detection result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CheckDuplicateResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/assets": {
      "get": {
        "operationId": "listAssets",
        "summary": "List Assets",
        "description": "Returns a cursor-paginated list of assets owned by the authenticated account.",
        "security": [
          {
            "BearerAuth": [
              "assets:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 20,
              "maximum": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "type",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "image",
                "video",
                "pdf",
                "document",
                "archive",
                "other"
              ]
            }
          },
          {
            "name": "folder_id",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "search",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated assets list",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaginatedAssetList"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/assets/{assetId}": {
      "get": {
        "operationId": "getAsset",
        "summary": "Get Asset Details",
        "description": "Fetches canonical asset metadata. Strictly enforces object ownership authorization.",
        "security": [
          {
            "BearerAuth": [
              "assets:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "assetId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Asset resource",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AssetResource"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "delete": {
        "operationId": "deleteAsset",
        "summary": "Delete Asset",
        "description": "Deactivates public links, purges all underlying R2 storage objects, and deducts storage usage.",
        "security": [
          {
            "BearerAuth": [
              "assets:delete"
            ]
          }
        ],
        "parameters": [
          {
            "name": "assetId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Asset successfully deleted"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/assets/{assetId}/replace/presign": {
      "post": {
        "operationId": "presignAssetReplacement",
        "summary": "Presign Replacement Upload",
        "description": "Requests a temporary presigned upload URL to replace the active bytes of an existing asset.",
        "security": [
          {
            "BearerAuth": [
              "assets:replace"
            ]
          }
        ],
        "parameters": [
          {
            "name": "assetId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReplacePresignRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Replacement upload presigned",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PresignUploadResponse"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/assets/{assetId}/replace/finalize": {
      "post": {
        "operationId": "finalizeAssetReplacement",
        "summary": "Finalize Asset Replacement",
        "description": "Validates uploaded replacement bytes, records a new version, deactivates older versions, and preserves the public URL.",
        "security": [
          {
            "BearerAuth": [
              "assets:replace"
            ]
          }
        ],
        "parameters": [
          {
            "name": "assetId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FinalizeUploadRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Asset replaced successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AssetResource"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/assets/{assetId}/versions": {
      "get": {
        "operationId": "getAssetVersions",
        "summary": "List Asset Version History",
        "description": "Returns safe metadata for all historical and active versions of an asset.",
        "security": [
          {
            "BearerAuth": [
              "assets:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "assetId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Version history list",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VersionHistoryResponse"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/folders": {
      "get": {
        "operationId": "listFolders",
        "summary": "List Folders",
        "security": [
          {
            "BearerAuth": [
              "folders:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Folder list",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FolderListResponse"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createFolder",
        "summary": "Create Folder",
        "security": [
          {
            "BearerAuth": [
              "folders:write"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateFolderRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Folder created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FolderResource"
                }
              }
            }
          }
        }
      }
    },
    "/imports": {
      "post": {
        "operationId": "importRemoteUrl",
        "summary": "Import Remote URL",
        "description": "Downloads media from a verified remote URL with strict SSRF defenses, DNS rebinding mitigation, streaming byte limits, and policy validation.",
        "security": [
          {
            "BearerAuth": [
              "imports:write"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ImportRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Import completed synchronously",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ImportResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          }
        }
      }
    },
    "/jobs/{jobId}": {
      "get": {
        "operationId": "getJob",
        "summary": "Get Job Status",
        "security": [
          {
            "BearerAuth": [
              "imports:read"
            ]
          },
          {
            "BearerAuth": [
              "imports:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "jobId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Job status and result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobResource"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "BearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "m2u_live_*",
        "description": "Media2URL production high-entropy API key. Format: `m2u_live_<hex>`"
      }
    },
    "schemas": {
      "ProblemDetails": {
        "type": "object",
        "required": [
          "type",
          "title",
          "status",
          "detail",
          "code",
          "request_id"
        ],
        "properties": {
          "type": {
            "type": "string",
            "format": "uri"
          },
          "title": {
            "type": "string"
          },
          "status": {
            "type": "integer"
          },
          "detail": {
            "type": "string"
          },
          "instance": {
            "type": "string"
          },
          "code": {
            "type": "string"
          },
          "request_id": {
            "type": "string"
          }
        }
      },
      "UsageResponse": {
        "type": "object",
        "properties": {
          "api": {
            "type": "object",
            "properties": {
              "version": {
                "type": "string",
                "example": "v1"
              },
              "access": {
                "type": "boolean",
                "example": true
              }
            }
          },
          "requests": {
            "type": "object",
            "properties": {
              "used": {
                "type": "integer",
                "example": 420
              },
              "limit": {
                "type": "integer",
                "example": 100000
              },
              "reset_at": {
                "type": "string",
                "format": "date-time"
              }
            }
          },
          "storage": {
            "type": "object",
            "properties": {
              "used_bytes": {
                "type": "integer",
                "example": 1073741824
              },
              "limit_bytes": {
                "type": "integer",
                "example": 268435456000
              }
            }
          },
          "bandwidth": {
            "type": "object",
            "properties": {
              "used_bytes": {
                "type": "integer",
                "example": 5368709120
              },
              "limit_bytes": {
                "type": "integer",
                "example": 3221225472000
              }
            }
          }
        }
      },
      "PresignUploadRequest": {
        "type": "object",
        "required": [
          "filename",
          "content_type",
          "size"
        ],
        "properties": {
          "filename": {
            "type": "string",
            "example": "hero.png"
          },
          "content_type": {
            "type": "string",
            "example": "image/png"
          },
          "size": {
            "type": "integer",
            "example": 245817
          },
          "checksum_sha256": {
            "type": "string",
            "example": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
          },
          "privacy": {
            "type": "string",
            "enum": [
              "public",
              "unlisted",
              "private"
            ],
            "default": "public"
          }
        }
      },
      "PresignUploadResponse": {
        "type": "object",
        "properties": {
          "upload_id": {
            "type": "string",
            "example": "upl_9f3b1458-45a2-4a0b-8d59-2c7bb2de3f1a"
          },
          "upload_url": {
            "type": "string",
            "format": "uri"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          },
          "required_headers": {
            "type": "object",
            "properties": {
              "Content-Type": {
                "type": "string",
                "example": "image/png"
              },
              "x-amz-checksum-sha256": {
                "type": "string",
                "description": "Present when checksum_sha256 was supplied; send the base64-encoded SHA-256 digest with the PUT request."
              }
            }
          }
        }
      },
      "FinalizeUploadRequest": {
        "type": "object",
        "required": [
          "upload_id"
        ],
        "properties": {
          "upload_id": {
            "type": "string",
            "example": "upl_9f3b1458-45a2-4a0b-8d59-2c7bb2de3f1a"
          }
        }
      },
      "ReplacePresignRequest": {
        "type": "object",
        "required": [
          "size"
        ],
        "properties": {
          "filename": {
            "type": "string",
            "example": "hero-v2.png"
          },
          "content_type": {
            "type": "string",
            "example": "image/png"
          },
          "size": {
            "type": "integer",
            "example": 312000
          },
          "checksum_sha256": {
            "type": "string"
          }
        }
      },
      "AssetResource": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "asset_01HXYZ..."
          },
          "status": {
            "type": "string",
            "example": "active"
          },
          "filename": {
            "type": "string",
            "example": "hero.png"
          },
          "content_type": {
            "type": "string",
            "example": "image/png"
          },
          "size": {
            "type": "integer",
            "example": 245817
          },
          "checksum_sha256": {
            "type": "string",
            "nullable": true
          },
          "privacy": {
            "type": "string",
            "example": "public"
          },
          "direct_url": {
            "type": "string",
            "format": "uri",
            "example": "https://files.media2url.com/media/hero.png"
          },
          "share_url": {
            "type": "string",
            "format": "uri",
            "example": "https://media2url.com/m/hero"
          },
          "embeds": {
            "type": "object",
            "properties": {
              "markdown": {
                "type": "string"
              },
              "html": {
                "type": "string"
              },
              "css": {
                "type": "string"
              }
            }
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "CheckDuplicateRequest": {
        "type": "object",
        "required": [
          "checksum_sha256"
        ],
        "properties": {
          "checksum_sha256": {
            "type": "string"
          },
          "size": {
            "type": "integer"
          }
        }
      },
      "CheckDuplicateResponse": {
        "type": "object",
        "properties": {
          "duplicate": {
            "type": "boolean"
          },
          "asset": {
            "$ref": "#/components/schemas/AssetResource",
            "nullable": true
          }
        }
      },
      "PaginatedAssetList": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AssetResource"
            }
          },
          "pagination": {
            "type": "object",
            "properties": {
              "next_cursor": {
                "type": "string",
                "nullable": true
              },
              "has_more": {
                "type": "boolean"
              }
            }
          }
        }
      },
      "VersionHistoryResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "version_number": {
                  "type": "integer"
                },
                "content_type": {
                  "type": "string"
                },
                "size": {
                  "type": "integer"
                },
                "file_extension": {
                  "type": "string"
                },
                "is_active": {
                  "type": "boolean"
                },
                "checksum_sha256": {
                  "type": "string",
                  "nullable": true
                },
                "created_at": {
                  "type": "string",
                  "format": "date-time"
                }
              }
            }
          }
        }
      },
      "FolderResource": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          },
          "parent_folder_id": {
            "type": "string",
            "nullable": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "FolderListResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FolderResource"
            }
          }
        }
      },
      "CreateFolderRequest": {
        "type": "object",
        "required": [
          "name"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "parent_folder_id": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "ImportRequest": {
        "type": "object",
        "required": [
          "url"
        ],
        "properties": {
          "url": {
            "type": "string",
            "format": "uri"
          },
          "privacy": {
            "type": "string",
            "enum": [
              "public",
              "unlisted",
              "private"
            ]
          },
          "filename": {
            "type": "string"
          }
        }
      },
      "ImportResponse": {
        "type": "object",
        "properties": {
          "job_id": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "asset": {
            "$ref": "#/components/schemas/AssetResource"
          }
        }
      },
      "JobResource": {
        "type": "object",
        "properties": {
          "job_id": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "queued",
              "processing",
              "completed",
              "failed"
            ]
          },
          "source_url": {
            "type": "string"
          },
          "asset": {
            "$ref": "#/components/schemas/AssetResource",
            "nullable": true
          },
          "error": {
            "type": "object",
            "nullable": true,
            "properties": {
              "code": {
                "type": "string"
              },
              "detail": {
                "type": "string"
              }
            }
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Bad Request (RFC 9457)",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/ProblemDetails"
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Missing or Invalid Authentication (RFC 9457)",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/ProblemDetails"
            }
          }
        }
      },
      "Forbidden": {
        "description": "Forbidden / Subscription Required / Insufficient Scope (RFC 9457)",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/ProblemDetails"
            }
          }
        }
      },
      "NotFound": {
        "description": "Resource Not Found (RFC 9457)",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/ProblemDetails"
            }
          }
        }
      },
      "Conflict": {
        "description": "State Conflict / Idempotency Conflict (RFC 9457)",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/ProblemDetails"
            }
          }
        }
      },
      "Gone": {
        "description": "Expired Upload Session (RFC 9457)",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/ProblemDetails"
            }
          }
        }
      },
      "Unprocessable": {
        "description": "Unprocessable Content (RFC 9457)",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/ProblemDetails"
            }
          }
        }
      },
      "RateLimited": {
        "description": "Rate Limit Exceeded (RFC 9457)",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/ProblemDetails"
            }
          }
        }
      }
    }
  }
}
