{
  "openapi": "3.0.0",
  "info": {
    "title": "AI Fabric Virtual Try-On",
    "description": "# Overview\nTransform your look with stunning realism! Explore unique fabric styles with photo mode — whether it's the elegance of silky textures or the vibrance of bold prints, the AI Fabric API brings materials to life! Developers can craft immersive experiences that let users see and feel fabrics like never before. Plus, fresh fabric updates are always on the way!\n\n---\n\n## Integration Guide\n\n* AI Fabric API Usage Guide\n\nThis guide explains how to upload images, fetch predefined fabric styles, and create virtual try-on tasks using the AI Fabric API.\n\n***\n\n   * Step 1. Upload a File Using the File API\n\nUse the **File API** (`/s2s/v2.0/file`) to upload a target user image.\n\n**Image Requirements:**\n\n*   Upload a high-resolution full-body photo.\n*   Ensure the photo clearly shows the entire body.\n*   Avoid backgrounds with multiple people or distracting objects.\n\n**Example Request:**\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   * Step 2. Retrieve File API Response\n\nThe response includes:\n\n*   `file_id` for creating an AI task.\n*   `requests.url` for uploading the actual image file.\n\n**Sample Response:**\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   * Step 3. Upload Image to Provided URL\n\nUse the `requests.url` from the File API response to upload the image:\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   * Step 4. Fetch Predefined Fabric Templates\n\nUse the **Template API** (`/s2s/v2.0/task/template/fabric`) to retrieve a list of predefined fabric templates:\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   * Step 5. Create an AI Task\n\nUse the **AI Task API** (`/s2s/v2.0/task/fabric`) to create a virtual try-on task.\n\n**Parameters:**\n\n*   For the user image: `src_file_id` or `src_file_url`.\n*   For the fabric style: `template_id`.\n\n**Example Request:**\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**Sample Response:**\n\n```json\n{\n  \"status\": 200,\n  \"data\": {\n    \"task_id\": \"SaGaqpDgKwFrVBgMpQMA3HY0LeqdT9_13W5TOD8_u_GPi6NqQ3dhlmN-6ntFwhzT\"\n  }\n}\n```\n\n***\n\n   * Step 6. Poll for Task Result\n\nUse the task ID to check the status:\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   * Step 7. Retrieve Result\n\nA successful response includes a download URL for the result image:\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\nInvalid API Key error response:\n\n```json\n{\n  \"status\": 401,\n  \"error\": \"Unauthorized\",\n  \"error_code\": \"InvalidAccessToken\"\n}\n```\n\n---\n\n\nUse cases:\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\nSuggestions for How to Shoot:\n![Suggestions for How to Shoot](https://bcw-media.s3.ap-northeast-1.amazonaws.com/strapi/assets/AI-Cloth-Guideline.png \"Suggestions for How to Shoot\")\n\n---\n\n## File Specs & Errors\n* Supported Formats & Dimensions\n\n|AI Feature|Supported Dimensions|Supported File Size|Supported Formats|\n|  ----  | ----  | ----  | ----  |\n|AI Fabric|long side <= 4096, single person only, The abdomen, face, and shoulders should all be visible. The face must not be obstructed. The body should be upright and facing forward, without any unusual poses like sitting or squatting.|< 10MB|jpg/jpeg|\n\n* Error Codes\n\n|Error Code|Description|\n|  ----  | ----  |\n|error_apply_region_not_detected|The clothing area is either too small or wasn’t detected in the input image\n\n* Environment & Dependency\n\n| Sample Code Language / Tool | Recommended Runtime Versions |\n|---|---|\n| cURL | - bash >= 3.2</br>   - curl >= 7.58 (modern TLS/HTTP support)</br>   - jq >= 1.6 (robust JSON parsing) |\n| Node.js (JavaScript) | Node >= 18 (for global fetch) |\n| JavaScript | - Chrome / Edge >= 80</br>   - Firefox >= 74</br>   - Safari >= 13.1 |\n| PHP | PHP >= 7.4 (for modern TLS/compat), ext-curl (recommended) or allow_url_fopen=On + ext-openssl, ext-json |\n| Python | Python >= 3.10 (for f-strings), requests >= 2.20.0 |\n| Java | Java 11+ (for HttpClient), Jackson Databind >= 2.12.0 |\n\n---\n\n## Unit Consumption\n\n| AI Feature | Unit Consumed |\n|---|---|\n| AI Fabric Virtual Try-On 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 Fabric API allows you to apply fabric styles to images using predefined templates and source images."
    }
  ],
  "paths": {
    "/s2s/v2.0/task/template/fabric": {
      "get": {
        "summary": "List predefined templates.",
        "tags": [
          "V1.0"
        ],
        "security": [
          {
            "BearerAuthenticationV2": []
          }
        ],
        "parameters": [
          {
            "name": "page_size",
            "in": "query",
            "schema": {
              "type": "integer",
              "example": 20
            },
            "description": "Number of results to return in this page. Valid value should be between 1 and 20. Default 20."
          },
          {
            "name": "starting_token",
            "in": "query",
            "schema": {
              "type": "string",
              "example": "73a3c9e69b89"
            },
            "description": "Token for current page. Start with `null` for the first page, and use `next_token` from the previous response to start next page"
          }
        ],
        "responses": {
          "200": {
            "description": "Successful retrieval of styles",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TemplateResponseSchema"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request parameters",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvalidParametersSchema"
                }
              }
            }
          },
          "401": {
            "description": "Invalid API Key or Inactive API Key or Expired API Key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvalidApiKeySchema"
                }
              }
            }
          }
        }
      }
    },
    "/s2s/v2.0/task/fabric": {
      "post": {
        "summary": "Run an Fabric task.",
        "description": "Please refer to the polling guide for checking task status.",
        "tags": [
          "V1.0"
        ],
        "security": [
          {
            "BearerAuthenticationV2": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RunWithSingleTemplateAndSrcUrl"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful execution of the task",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BasicRunTaskResponseV2"
                }
              }
            }
          },
          "400": {
            "description": "Failed execution of task",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/RunErrorSchema"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Invalid API Key or Inactive API Key or Expired API Key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvalidApiKeySchema"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests within a given amount of time",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/s2s/v2.0/task/fabric/{task_id}": {
      "get": {
        "summary": "Check the status of the Fabric task.",
        "tags": [
          "V1.0"
        ],
        "security": [
          {
            "BearerAuthenticationV2": []
          }
        ],
        "parameters": [
          {
            "name": "task_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "grH0CvsgXuAIHLUzD0V1Ol34hoet3R1tvdbtiVHrDb6_UqCLKIejAIajwxrhOAfe"
            },
            "description": "ID of task to check"
          }
        ],
        "responses": {
          "200": {
            "description": "Successful check of the task status",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TaskStatusResponseV2"
                }
              }
            }
          },
          "400": {
            "description": "Invalid task id",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvalidTaskIdSchema"
                }
              }
            }
          },
          "401": {
            "description": "Invalid API Key or Inactive API Key or Expired API Key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvalidApiKeySchema"
                }
              }
            }
          },
          "500": {
            "description": "The task has no response in the expected time",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TaskTimeoutSchema"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Template": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The ID of the template. Use this as `template_id` when run task.",
            "example": "good_template_001"
          },
          "thumb": {
            "type": "string",
            "description": "The thumbnail of style."
          },
          "title": {
            "type": "string",
            "description": "The title of the template."
          },
          "category_name": {
            "type": "string",
            "description": "The category name of the template."
          }
        }
      },
      "TemplateResponseSchema": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer",
            "description": "Response status",
            "example": 200
          },
          "data": {
            "type": "object",
            "properties": {
              "templates": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Template"
                }
              },
              "next_token": {
                "type": "string",
                "example": "73a3c9e69b89",
                "description": "Token to query next page."
              }
            }
          }
        }
      },
      "RunWithSingleTemplateAndSrcUrl": {
        "title": "RunWithSingleTemplateAndSrcUrl",
        "allOf": [
          {
            "$ref": "#/components/schemas/RunWithSingleTemplate"
          },
          {
            "$ref": "#/components/schemas/BasicRunTaskV2"
          }
        ]
      },
      "RunWithSingleTemplate": {
        "title": "RunWithSingleTemplate",
        "type": "object",
        "properties": {
          "template_id": {
            "type": "string",
            "description": "ID of the template. List predefined templates first, and use the id of a template.",
            "example": "good_template_001"
          }
        },
        "required": [
          "template_id"
        ]
      },
      "BasicRunTaskV2SrcFileUrl": {
        "title": "Run task with src file url",
        "type": "object",
        "required": [
          "src_file_url"
        ],
        "properties": {
          "src_file_url": {
            "type": "string",
            "description": "Url of the file to run task. The url should be publicly accessible.",
            "example": "https://example.com/selfie.jpg"
          }
        }
      },
      "BasicRunTaskV2SrcFileId": {
        "title": "Run task with src file ID",
        "type": "object",
        "required": [
          "src_file_id"
        ],
        "properties": {
          "src_file_id": {
            "type": "string",
            "description": "ID of file to run task. File ID from upload file API.",
            "example": "pfNK5PuRe0MrwLHcGA3DOmB1ahwfXTbYHjv+KoBIxbE="
          }
        }
      },
      "BasicRunTaskV2": {
        "title": "BasicRunTaskV2",
        "anyOf": [
          {
            "$ref": "#/components/schemas/BasicRunTaskV2SrcFileUrl"
          },
          {
            "$ref": "#/components/schemas/BasicRunTaskV2SrcFileId"
          }
        ]
      },
      "BasicRunTaskResponseV2": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer",
            "description": "Response status",
            "example": 200
          },
          "data": {
            "type": "object",
            "properties": {
              "task_id": {
                "type": "string",
                "description": "ID of this task. Task result is valid to query by this ID for 24 hours.",
                "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": "Errors:\n- `exceed_max_filesize` - Input file size exceeds the maximum limit\n- `invalid_parameter` - Invalid parameter value\n- `error_download_image` - Download source image error\n- `error_download_mask` - Download mask image error\n- `error_decode_image` - Decode source image error\n- `error_decode_mask` - Decode mask image error\n- `error_nsfw_content_detected` - NSFW content detected in source image\n- `error_no_face` - No face detected on source image\n- `error_pose` - Failed to detect pose on source image\n- `error_face_parsing` - Failed to do face segmentation on source image\n- `error_inference` - Inference pipeline error\n- `exceed_nsfw_retry_limits` - Exceed the retry limits to avoid generated NSFW image\n- `error_upload` - Upload result image error\n- `unknown_internal_error` - Others\n"
      },
      "TaskStatusResponseBodySingleUrlResultsV2": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "description": "URL to download this result. Valid for 2 hours",
            "example": "https://example.com/sample-result-url"
          }
        }
      },
      "TaskStatusResponseV2": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer",
            "description": "Response status",
            "example": 200
          },
          "data": {
            "type": "object",
            "properties": {
              "task_status": {
                "type": "string",
                "enum": [
                  "running",
                  "success",
                  "error"
                ],
                "description": "Status of this task"
              },
              "error": {
                "$ref": "#/components/schemas/EngineErrorCode"
              },
              "error_message": {
                "type": "string",
                "description": "Detailed description of error"
              },
              "results": {
                "$ref": "#/components/schemas/TaskStatusResponseBodySingleUrlResultsV2"
              }
            }
          }
        }
      },
      "InvalidParametersSchema": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer",
            "example": 400,
            "description": "Response status"
          },
          "error": {
            "type": "string",
            "description": "Error message",
            "example": "The operation could not be completed"
          },
          "error_code": {
            "type": "string",
            "enum": [
              "InvalidParameters"
            ],
            "description": "Error code:\n  * InvalidParameters - Invalid request parameters or body\n"
          }
        }
      },
      "InvalidApiKeySchema": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer",
            "example": 401,
            "description": "Response status"
          },
          "error_code": {
            "type": "string",
            "enum": [
              "InvalidApiKey",
              "InactiveApiKey",
              "ExpiredApiKey"
            ],
            "description": "Error code:\n  * InvalidApiKey - API Key is not given or not valid\n  * InactiveApiKey - API Key is inactivated\n  * ExpiredApiKey - API Key is expired\n"
          }
        }
      },
      "RunErrorSchema": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer",
            "description": "Response status",
            "example": 400
          },
          "error": {
            "type": "string",
            "description": "Error message",
            "example": "The operation could not be completed"
          },
          "error_code": {
            "type": "string",
            "enum": [
              "CreditInsufficiency",
              "InvalidStyleGroup",
              "InvalidStyle",
              "BadRequest",
              "InvalidParameters"
            ],
            "description": "Error code:\n  * CreditInsufficiency - Insufficient unit to run\n  * BadRequest - Unexpected request parameter\n  * InvalidStyleGroup - Invalid style group id\n  * InvalidStyle - Invalid style id\n  * InvalidParameters - Invalid request parameters\n"
          }
        }
      },
      "InvalidTaskIdSchema": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer",
            "description": "Response status",
            "example": 400
          },
          "error_code": {
            "type": "string",
            "enum": [
              "InvalidTaskId"
            ],
            "description": "Error code:\n  * InvalidTaskId - Invalid task id\n"
          }
        }
      },
      "TaskTimeoutSchema": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer",
            "description": "Response status",
            "example": 500
          },
          "error_code": {
            "type": "string",
            "enum": [
              "TaskTimeout"
            ],
            "description": "Error code:\n  * TaskTimeout - The task has no response in the expected time\n"
          }
        }
      }
    },
    "securitySchemes": {
      "BearerAuthenticationV2": {
        "type": "http",
        "scheme": "bearer",
        "description": "Use the standard 'Bearer authentication'. Put your 'API Key' in header: `Authorization:Bearer YOUR_API_KEY`. Notice that there is ' ' a space between 'Bearer' and the 'YOUR_API_KEY'."
      }
    }
  }
}