{
  "openapi": "3.0.0",
  "info": {
    "title": "AI 布料替換",
    "description": "# 概述\n以令人驚嘆的真實感改變您的造型！透過照片模式探索獨特的布料風格——無論是絲滑質地的優雅，或大膽圖案的鮮豔，AI 布料 API 讓材質活起來！開發者可以打造沉浸式的體驗，讓使用者前所未有地看見並感受布料。而且，全新的布料更新隨時到來！\n\n---\n\n## 整合指南\n\n* AI 布料 API 使用指南\n\n本指南說明如何使用 AI 布料 API 上傳圖片、取得預先定義的布料風格，以及建立虛擬試戴任務。\n\n***\n\n   * 步驟 1. 使用 File API 上傳檔案\n\n使用 **File API**（`/s2s/v2.0/file`）上傳目標使用者圖片。\n\n**圖片需求：**\n\n*   上傳高解析度的全身照片。\n*   確保照片清楚呈現整個身體。\n*   避免有多人干擾的物件背景。\n\n**請求範例：**\n\n```bash\ncurl --request POST \\\n  --url https://yce-api-01.makeupar.com/s2s/v2.0/file \\\n  --header 'Authorization: Bearer YOUR_API_KEY' \\\n  --header 'content-type: application/json' \\\n  --data '{\n    \"files\": [\n      {\n        \"content_type\": \"image/jpg\",\n        \"file_name\": \"full_body_photo_01_3dbd1b6683.jpg\",\n        \"file_size\": 547541\n      }\n    ]\n  }'\n```\n\n***\n\n   * 步驟 2. 取得 File API 回應\n\n回應包含：\n\n*   用於建立 AI 任務的 `file_id`。\n*   用於上傳實際圖片檔案的 `requests.url`。\n\n**回應範例：**\n\n```json\n{\n  \"status\": 200,\n  \"data\": {\n    \"files\": [\n      {\n        \"content_type\": \"image/jpg\",\n        \"file_name\": \"full_body_photo_01_3dbd1b6683.jpg\",\n        \"file_id\": \"SaGaqpDgKwFrVBgMpQMA3HY0LeqdT9/13W5TOD8/u/FfjK3xgCQ+hRt9MJXBFaud\",\n        \"requests\": [\n          {\n            \"method\": \"PUT\",\n            \"url\": \"https://yce-us.s3-accelerate.amazonaws.com/demo/ttl30/...signature...\",\n            \"headers\": {\n              \"Content-Length\": \"547541\",\n              \"Content-Type\": \"image/jpg\"\n            }\n          }\n        ]\n      }\n    ]\n  }\n}\n```\n\n***\n\n   * 步驟 3. 上傳圖片到提供的網址\n\n使用 File API 回應中的 `requests.url` 上傳圖片：\n\n```bash\ncurl --location --request PUT 'https://yce-us.s3-accelerate.amazonaws.com/demo/ttl30/...signature...' \\\n  --header 'Content-Type: image/jpg' \\\n  --header 'Content-Length: 547541' \\\n  --data-binary @'./full_body_photo_01_3dbd1b6683.jpg'\n```\n\n***\n\n   * 步驟 4. 取得預先定義的布料範本\n\n使用 **範本 API**（`/s2s/v2.0/task/template/fabric`）取得預先定義的布料範本清單：\n\n```bash\ncurl --request GET \\\n    --url 'https://yce-api-01.makeupar.com/s2s/v2.0/task/template/fabric?page_size=20&starting_token=73a3c9e69b89' \\\n    --header 'Authorization: Bearer YOUR_API_KEY'\n```\n\n***\n\n   * 步驟 5. 建立 AI 任務\n\n使用 **AI 任務 API**（`/s2s/v2.0/task/fabric`）建立虛擬試戴任務。\n\n**參數：**\n\n*   使用者圖片：`src_file_id` 或 `src_file_url`。\n*   布料風格：`template_id`。\n\n**請求範例：**\n\n```bash\ncurl --request POST \\\n    --url https://yce-api-01.makeupar.com/s2s/v2.0/task/fabric \\\n    --header 'Authorization: Bearer YOUR_API_KEY' \\\n    --header 'content-type: application/json' \\\n    --data '{\n    \"template_id\":\"good_template_001\",\n    \"src_file_url\":\"https://example.com/selfie.jpg\"\n    }'\n```\n\n**回應範例：**\n\n```json\n{\n  \"status\": 200,\n  \"data\": {\n    \"task_id\": \"SaGaqpDgKwFrVBgMpQMA3HY0LeqdT9_13W5TOD8_u_GPi6NqQ3dhlmN-6ntFwhzT\"\n  }\n}\n```\n\n***\n\n   * 步驟 6. 輪詢任務結果\n\n使用任務 ID 查詢狀態：\n\n```bash\ncurl --request GET \\\n  --url https://yce-api-01.makeupar.com/s2s/v2.0/task/fabric/<YOUR_TASK_ID> \\\n  --header 'Authorization: Bearer YOUR_API_KEY' \\\n  --header 'content-type: application/json'\n```\n\n***\n\n   * 步驟 7. 取得結果\n\n成功的回應會包含結果圖片的下載網址：\n\n```json\n{\n  \"status\": 200,\n  \"data\": {\n    \"error\": null,\n    \"results\": {\n      \"url\": \"https://yce-us.s3-accelerate.amazonaws.com/demo/ttl30/...signature...\"\n    },\n    \"task_status\": \"success\"\n  }\n}\n```\n\nAPI Key 無效的錯誤回應：\n\n```json\n{\n  \"status\": 401,\n  \"error\": \"Unauthorized\",\n  \"error_code\": \"InvalidAccessToken\"\n}\n```\n\n---\n\n\n應用案例：\n![](https://bcw-media.s3.ap-northeast-1.amazonaws.com/strapi/assets/AI%20Fabric.png)\n\n![](https://plugins-media.makeupar.com/smb/blog/post/2024-05-07/b103976d-1b0e-4bed-aab4-9307308b84d7.jpg)\n\n![](https://bcw-media.s3.ap-northeast-1.amazonaws.com/strapi/assets/03%20ai%20clothes%20changer.jpg)\n\n拍攝建議：\n![拍攝建議](https://bcw-media.s3.ap-northeast-1.amazonaws.com/strapi/assets/AI-Cloth-Guideline.png \"拍攝建議\")\n\n---\n\n## 檔案規格與錯誤\n* 支援的格式與尺寸\n\n|AI 功能|支援的尺寸|支援的檔案大小|支援的格式|\n|  ----  | ----  | ----  | ----  |\n|AI 布料|長邊 <= 4096，僅限單人，腹部、臉部與肩膀都必須可見。臉部不可被遮擋。身體應直立並面向前方，不可有坐姿或蹲姿等特殊姿勢。|< 10MB|jpg/jpeg|\n\n* 錯誤代碼\n\n|錯誤代碼|說明|\n|  ----  | ----  |\n|error_apply_region_not_detected|服裝區域過小，或在輸入圖片中未被偵測到\n\n* 環境與相依性\n\n| 範例程式語言 / 工具 | 建議的執行環境版本 |\n|---|---|\n| cURL | - bash >= 3.2</br>   - curl >= 7.58（現代 TLS/HTTP 支援）</br>   - jq >= 1.6（穩健的 JSON 解析） |\n| Node.js（JavaScript） | Node >= 18（支援全域 fetch） |\n| JavaScript | - Chrome / Edge >= 80</br>   - Firefox >= 74</br>   - Safari >= 13.1 |\n| PHP | PHP >= 7.4（現代 TLS/相容性），ext-curl（建議）或 allow_url_fopen=On + ext-openssl、ext-json |\n| Python | Python >= 3.10（支援 f-strings），requests >= 2.20.0 |\n| Java | Java 11+（支援 HttpClient），Jackson Databind >= 2.12.0 |\n\n---\n\n## 點數消耗\n\n| AI 功能 | 消耗的點數 |\n|---|---|\n| AI 布料替換 V1.0 | 2 |\n\n---\n",
    "version": "",
    "termsOfService": "https://www.makeupar.com/perfectbeauty/youcam/terms-of-service-api",
    "contact": {
      "email": "YouCamOnlineEditor_API@perfectcorp.com"
    },
    "license": {
      "name": "Privacy policy",
      "url": "https://www.makeupar.com/perfectbeauty/youcam/privacy-policy-api"
    }
  },
  "servers": [
    {
      "url": "https://yce-api-01.makeupar.com"
    }
  ],
  "tags": [
    {
      "name": "V1.0",
      "description": "AI 布料 API 可讓您使用預先定義的範本與來源照片，將布料風格套用到圖片。"
    }
  ],
  "paths": {
    "/s2s/v2.0/task/template/fabric": {
      "get": {
        "summary": "列出預先定義的範本。",
        "tags": [
          "V1.0"
        ],
        "security": [
          {
            "BearerAuthenticationV2": []
          }
        ],
        "parameters": [
          {
            "name": "page_size",
            "in": "query",
            "schema": {
              "type": "integer",
              "example": 20
            },
            "description": "這一頁要回傳的結果數量。有效值應介於 1 到 20 之間。預設為 20。"
          },
          {
            "name": "starting_token",
            "in": "query",
            "schema": {
              "type": "string",
              "example": "73a3c9e69b89"
            },
            "description": "目前頁面的令牌。第一頁以 `null` 開始，並使用上一個回應中的 `next_token` 開始下一頁"
          }
        ],
        "responses": {
          "200": {
            "description": "成功取得風格",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TemplateResponseSchema"
                }
              }
            }
          },
          "400": {
            "description": "請求參數無效",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvalidParametersSchema"
                }
              }
            }
          },
          "401": {
            "description": "API Key 無效、已停用或已到期",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvalidApiKeySchema"
                }
              }
            }
          }
        }
      }
    },
    "/s2s/v2.0/task/fabric": {
      "post": {
        "summary": "執行布料任務。",
        "description": "查詢任務狀態請參考輪詢指南。",
        "tags": [
          "V1.0"
        ],
        "security": [
          {
            "BearerAuthenticationV2": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RunWithSingleTemplateAndSrcUrl"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "任務執行成功",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BasicRunTaskResponseV2"
                }
              }
            }
          },
          "400": {
            "description": "任務執行失敗",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/RunErrorSchema"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "API Key 無效、已停用或已到期",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvalidApiKeySchema"
                }
              }
            }
          },
          "429": {
            "description": "在指定時間內請求過多",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/s2s/v2.0/task/fabric/{task_id}": {
      "get": {
        "summary": "查詢布料任務的狀態。",
        "tags": [
          "V1.0"
        ],
        "security": [
          {
            "BearerAuthenticationV2": []
          }
        ],
        "parameters": [
          {
            "name": "task_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "grH0CvsgXuAIHLUzD0V1Ol34hoet3R1tvdbtiVHrDb6_UqCLKIejAIajwxrhOAfe"
            },
            "description": "要查詢的任務 ID"
          }
        ],
        "responses": {
          "200": {
            "description": "成功查詢任務狀態",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TaskStatusResponseV2"
                }
              }
            }
          },
          "400": {
            "description": "任務 id 無效",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvalidTaskIdSchema"
                }
              }
            }
          },
          "401": {
            "description": "API Key 無效、已停用或已到期",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvalidApiKeySchema"
                }
              }
            }
          },
          "500": {
            "description": "任務在預期時間內沒有回應",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TaskTimeoutSchema"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Template": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "範本的 ID。執行任務時將其作為 `template_id` 使用。",
            "example": "good_template_001"
          },
          "thumb": {
            "type": "string",
            "description": "風格的縮略圖。"
          },
          "title": {
            "type": "string",
            "description": "範本的標題。"
          },
          "category_name": {
            "type": "string",
            "description": "範本的類別名稱。"
          }
        }
      },
      "TemplateResponseSchema": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer",
            "description": "回應狀態",
            "example": 200
          },
          "data": {
            "type": "object",
            "properties": {
              "templates": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Template"
                }
              },
              "next_token": {
                "type": "string",
                "example": "73a3c9e69b89",
                "description": "查詢下一頁的令牌。"
              }
            }
          }
        }
      },
      "RunWithSingleTemplateAndSrcUrl": {
        "title": "RunWithSingleTemplateAndSrcUrl",
        "allOf": [
          {
            "$ref": "#/components/schemas/RunWithSingleTemplate"
          },
          {
            "$ref": "#/components/schemas/BasicRunTaskV2"
          }
        ]
      },
      "RunWithSingleTemplate": {
        "title": "RunWithSingleTemplate",
        "type": "object",
        "properties": {
          "template_id": {
            "type": "string",
            "description": "範本的 ID。請先列出預先定義的範本，然後使用某個範本的 id。",
            "example": "good_template_001"
          }
        },
        "required": [
          "template_id"
        ]
      },
      "BasicRunTaskV2SrcFileUrl": {
        "title": "以來源檔案網址執行任務",
        "type": "object",
        "required": [
          "src_file_url"
        ],
        "properties": {
          "src_file_url": {
            "type": "string",
            "description": "要執行任務的檔案網址。該網址應可公開存取。",
            "example": "https://example.com/selfie.jpg"
          }
        }
      },
      "BasicRunTaskV2SrcFileId": {
        "title": "以來源檔案 ID 執行任務",
        "type": "object",
        "required": [
          "src_file_id"
        ],
        "properties": {
          "src_file_id": {
            "type": "string",
            "description": "要執行任務的檔案 ID。檔案 ID 來自上傳檔案 API。",
            "example": "pfNK5PuRe0MrwLHcGA3DOmB1ahwfXTbYHjv+KoBIxbE="
          }
        }
      },
      "BasicRunTaskV2": {
        "title": "BasicRunTaskV2",
        "anyOf": [
          {
            "$ref": "#/components/schemas/BasicRunTaskV2SrcFileUrl"
          },
          {
            "$ref": "#/components/schemas/BasicRunTaskV2SrcFileId"
          }
        ]
      },
      "BasicRunTaskResponseV2": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer",
            "description": "回應狀態",
            "example": 200
          },
          "data": {
            "type": "object",
            "properties": {
              "task_id": {
                "type": "string",
                "description": "這個任務的 ID。任務結果可以此 ID 查詢，有效期限 30 天。",
                "example": "grH0CvsgXuAIHLUzD0V1Ol34hoet3R1tvdbtiVHrDb6_UqCLKIejAIajwxrhOAfe"
              }
            }
          }
        }
      },
      "EngineErrorCode": {
        "type": "string",
        "nullable": true,
        "enum": [
          "exceed_max_filesize",
          "invalid_parameter",
          "error_download_image",
          "error_download_mask",
          "error_decode_image",
          "error_decode_mask",
          "error_nsfw_content_detected",
          "error_no_face",
          "error_pose",
          "error_face_parsing",
          "error_inference",
          "exceed_nsfw_retry_limits",
          "error_upload",
          "unknown_internal_error"
        ],
        "description": "錯誤：\n- `exceed_max_filesize` - 輸入檔案大小超過上限\n- `invalid_parameter` - 參數值無效\n- `error_download_image` - 下載來源圖片錯誤\n- `error_download_mask` - 下載遮罩圖片錯誤\n- `error_decode_image` - 解碼來源圖片錯誤\n- `error_decode_mask` - 解碼遮罩圖片錯誤\n- `error_nsfw_content_detected` - 在來源圖片中偵測到 NSFW 內容\n- `error_no_face` - 來源圖片未偵測到臉部\n- `error_pose` - 在來源圖片偵測姿勢失敗\n- `error_face_parsing` - 在來源圖片進行人臉分割失敗\n- `error_inference` - 推論流程錯誤\n- `exceed_nsfw_retry_limits` - 超過重試上限，以避免生成 NSFW 圖片\n- `error_upload` - 上傳結果圖片錯誤\n- `unknown_internal_error` - 其他\n"
      },
      "TaskStatusResponseBodySingleUrlResultsV2": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "description": "下載這個結果的網址。有效期限 2 小時",
            "example": "https://example.com/sample-result-url"
          }
        }
      },
      "TaskStatusResponseV2": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer",
            "description": "回應狀態",
            "example": 200
          },
          "data": {
            "type": "object",
            "properties": {
              "task_status": {
                "type": "string",
                "enum": [
                  "running",
                  "success",
                  "error"
                ],
                "description": "這個任務的狀態"
              },
              "error": {
                "$ref": "#/components/schemas/EngineErrorCode"
              },
              "error_message": {
                "type": "string",
                "description": "錯誤的詳細說明"
              },
              "results": {
                "$ref": "#/components/schemas/TaskStatusResponseBodySingleUrlResultsV2"
              }
            }
          }
        }
      },
      "InvalidParametersSchema": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer",
            "example": 400,
            "description": "回應狀態"
          },
          "error": {
            "type": "string",
            "description": "錯誤訊息",
            "example": "The operation could not be completed"
          },
          "error_code": {
            "type": "string",
            "enum": [
              "InvalidParameters"
            ],
            "description": "錯誤代碼：\n  * InvalidParameters - 請求參數或內容無效\n"
          }
        }
      },
      "InvalidApiKeySchema": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer",
            "example": 401,
            "description": "回應狀態"
          },
          "error_code": {
            "type": "string",
            "enum": [
              "InvalidApiKey",
              "InactiveApiKey",
              "ExpiredApiKey"
            ],
            "description": "錯誤代碼：\n  * InvalidApiKey - 未提供 API Key，或 API Key 無效\n  * InactiveApiKey - API Key 已停用\n  * ExpiredApiKey - API Key 已到期\n"
          }
        }
      },
      "RunErrorSchema": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer",
            "description": "回應狀態",
            "example": 400
          },
          "error": {
            "type": "string",
            "description": "錯誤訊息",
            "example": "The operation could not be completed"
          },
          "error_code": {
            "type": "string",
            "enum": [
              "CreditInsufficiency",
              "InvalidStyleGroup",
              "InvalidStyle",
              "BadRequest",
              "InvalidParameters"
            ],
            "description": "錯誤代碼：\n  * CreditInsufficiency - 點數不足，無法執行\n  * BadRequest - 請求參數不如預期\n  * InvalidStyleGroup - 風格群組 id 無效\n  * InvalidStyle - 風格 id 無效\n  * InvalidParameters - 請求參數無效\n"
          }
        }
      },
      "InvalidTaskIdSchema": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer",
            "description": "回應狀態",
            "example": 400
          },
          "error_code": {
            "type": "string",
            "enum": [
              "InvalidTaskId"
            ],
            "description": "錯誤代碼：\n  * InvalidTaskId - 任務 id 無效\n"
          }
        }
      },
      "TaskTimeoutSchema": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer",
            "description": "回應狀態",
            "example": 500
          },
          "error_code": {
            "type": "string",
            "enum": [
              "TaskTimeout"
            ],
            "description": "錯誤代碼：\n  * TaskTimeout - 任務在預期時間內沒有回應\n"
          }
        }
      }
    },
    "securitySchemes": {
      "BearerAuthenticationV2": {
        "type": "http",
        "scheme": "bearer",
        "description": "使用標準的 'Bearer authentication'。請在標頭中放入您的 'API Key'：`Authorization:Bearer YOUR_API_KEY`。請注意 'Bearer' 與 'YOUR_API_KEY' 之間有一個空格。"
      }
    }
  }
}