{
  "openapi": "3.0.0",
  "info": {
    "title": "AI Face Reshape",
    "description": "# Overview\nThe AI Face Reshape API lets you programmatically reshape facial features — eyes, nose, lips, jawline, or the whole face — with pixel‑perfect control. Use it to generate before/after visualisations for rhinoplasty, chin fillers, lip augmentations, brow lifts and any other aesthetic‑treatment workflow.\n\n* Rhinoplasty (Nose Job)\nOur online rhinoplasty simulator offers medical-grade precision adjustments. Unlike generic photo editing apps, it allows for comprehensive simulation of specific details, including the Bridge, Lift, and Wing. With our hyper-realistic previews, clients can clearly visualize and explore their ideal proportions before consulting.\n\n* Chin Filler\nThrough our online simulator, you can preview the ideal proportions achieved with chin fillers. Fine-tune Chin Length and Chin Shape to visualize improvements for a receding or short chin. Discover the optimal solution to balance your facial profile before undergoing any dermal filler treatments.\n\n* Lip Filler\nUsers can experiment with different volumes and shapes of lip fillers to simulate the appearance of fuller lips, helping them decide on the desired outcome before undergoing the procedure.\n\n* Brow Lift Surgery\nThis functionality enables users to preview the results of a brow lift, which involves lifting and reshaping the eyebrows to create a more youthful and rejuvenated appearance.\n\n\n\n## Integration Guide\nThis guide walks you through:\n\nWorkflow for AI Face Reshape API:\n\n**Endpoint:** `/s2s/v2.0/file`\n\n**Authentication Required:** `Authorization: Bearer YOUR_API_KEY`\n\n**Workflow Steps:**\n\n1. **Image Upload Preparation:**\n    - Prepare a selfie image for upload.\n    - Call the File API `/s2s/v2.0/file` to obtain the upload URL and associated `file_id`.\n    - Upload the selfie image using the provided upload URL.\n\n2. **Optional Preprocessing For Multiple Faces:**\n    - Preprocess the selfie image if there are more than one face in the image.\n\n3. **Face Reshape Effect Setup:**\n   - Begin by selecting suitable face reshape parameters of Eye, Face, Lip or Nose.\n\n4. **Initiate AI Task and Obtain Task ID:**\n   - Send the `file_id` along with the chosen effect configuration via an HTTP POST request to `/s2s/v2.0/task/face-reshape`.\n   - Await a unique task ID in the response, which identifies this interaction.\n\n5. **Poll Task Status (Continuous Check):**\n   - Use the obtained `task_id` to periodically poll the task status using an HTTP GET request (e.g., `GET /s2s/v2.0/task/face-reshape/${task_id}`).\n   - Continuously monitor for:\n     - `Task_status = \"success\"` (process completed).\n     - `Task_status = \"error\"` (resolve or retry if applicable).\n   - Update the workflow accordingly once the status transitions to success.\n\nThis structured workflow ensures efficient integration with user inputs, automated monitoring of tasks, and seamless retrieval of results.\n\n---\n\n* API Playground\n\nInteractively explore and test the API using our official playground:\n\n**API Playground:**\n[http://yce.makeupar.com/api-console/en/api-playground/ai-face-reshape/](http://yce.makeupar.com/api-console/en/api-playground/ai-face-reshape/)\n\n---\n\n* Authentication\n- Include your API key in the request header using **Bearer Token**:\n    ```\n    Authorization: Bearer YOUR_API_KEY\n    ```\nYou can find your API Key at https://yce.makeupar.com/api-console/en/api-keys/.\n\n\n1. Upload an Image\n\n    You may upload a file directly to the server or provide a valid image URL in the AI task payload.\n\n    * Upload Endpoint\n\n        ```\n        POST /s2s/v2.0/file\n        ```\n\n    Alternatively, skip this step if you already have a public image URL.\n\n---\n\n2. Prepare an effect template\n\n   * Preprocessing\n        Output detected bounding boxes in pixel coordinate. Use the index of result to create a Face Reshape AI task later.\n        ```\n        {\n            \"timed\": number,\n            \"result\": [\n                {\n                    \"left\": number,\n                    \"top\": number,\n                    \"width\": number,\n                    \"height\": number\n                }\n            ]\n        }\n        ```\n\n        * Effect Template JSON Schemas\n        ```\n        {\n            \"version\": \"1.0\",\n            \"index\": 0,\n            \"features\": {},\n            \"global\": {\n            \"skin_smooth_strength\": 50,\n            \"skin_smooth_color_intensity\": 50,\n            },\n        }\n        ```\n        index: index of detected face from preprocessing. optional, default 0.\n        features: required at least 1, non-zero face reshape parameter, cannot be all zero.\n        skin_smooth_strength: 0~100\n        skin_smooth_color_intensity: 0~100\n\n        * Effect Format\n        - Face\n        default range: -100~100\n        range of cheekbones and jaws: 0~100\n        all feature values must not be zero at the same time, at least one feature value must be non-zero\n        ```\n        {\n            \"cheekbones\": 0,\n            \"jaw\": 0,\n            \"face_reshape_left\": 0,\n            \"face_reshape_right\": 0,\n            \"face_width\": 0,\n            \"chin_reshape_left\": 0,\n            \"chin_reshape_right\": 0,\n            \"chin_length\": 0,\n        }\n        ```\n\n        - Eye\n        default range: -100~100\n        all feature values must not be zero at the same time, at least one feature value must be non-zero\n        ```\n        {\n            \"eye_size_left\": 0,\n            \"eye_size_right\": 0,\n            \"eye_distance\": 0,\n            \"eye_angle\": 0,\n            \"eye_height\": 0,\n            \"eye_width\": 0,\n        }\n        ```\n\n        - Nose\n        default range: -100~100\n        all feature values must not be zero at the same time, at least one feature value must be non-zero\n        ```\n        {\n            \"nose_bridge_width\": 0,\n            \"nose_lift\": 0,\n            \"nose_size\": 0,\n            \"nose_tip\": 0,\n            \"nose_tip_width\": 0,\n            \"nose_wing\": 0\n        }\n        ```\n\n        - Lip\n        default range: -100~100\n        all feature values must not be zero at the same time, at least one feature value must be non-zero\n        ```\n        {\n            \"lip_size\": 0,\n            \"lip_width\": 0,\n            \"lip_peak\": 0,\n            \"lip_height_top\": 0,\n            \"lip_height_bottom\": 0,\n        }\n        ```\n\n        * Example Payload (ready to send)\n        ```\n        {\n        \"src_file_url\": \"https://plugins-media.makeupar.com/strapi/assets/face_reshape_01_85c8ffc055.jpg\",\n        \"version\": \"1.0\",\n        \"source\": \"yco\",\n        \"features\": {\n            \"eye_size_left\": 80,\n            \"eye_size_right\": 80,\n            \"eye_width\": 0,\n            \"eye_height\": 0,\n            \"eye_distance\": 0,\n            \"eye_angle\": 0,\n            \"face_reshape_left\": 0,\n            \"face_reshape_right\": 0,\n            \"chin_reshape_left\": 20,\n            \"chin_reshape_right\": 20,\n            \"chin_length\": 0,\n            \"face_width\": -30,\n            \"cheekbones\": 0,\n            \"jaw\": 0,\n            \"lip_size\": 10,\n            \"lip_width\": 40,\n            \"lip_height_top\": 10,\n            \"lip_height_bottom\": 10,\n            \"lip_peak\": -10,\n            \"nose_size\": 30,\n            \"nose_lift\": -20,\n            \"nose_bridge_width\": 10,\n            \"nose_tip\": -10,\n            \"nose_wing\": 30,\n            \"nose_tip_width\": 30\n        },\n        \"global\": {\n            \"skin_smooth_strength\": 50,\n            \"skin_smooth_color_intensity\": 50\n        }\n        }\n        ```\n\n\n3. Create a Face Reshape AI Task and Poll for Results\n\n    Once you have an image and a complete effect payload, create a task. The API processes the request asynchronously. You must poll the task status until it reaches `success` or `error`.\n\n   * Create Task Endpoint\n\n        ```\n        POST /s2s/v2.0/task/face-reshape\n        ```\n\n   * Polling Endpoint\n\n        ```\n        GET /s2s/v2.0/task/face-reshape/{task_id}\n        ```\n\n---\n\n## File Specs & Errors\n\n* AI Face Reshape Specification\n\n**Supported Selfie View**\nA selfie with width and height of a face larger than 1/20 of image width and heigh.\nFace angle less than 30 degree for pitch, yaw and rolling.\n\n![](https://plugins-media.makeupar.com/strapi/assets/thumbnail_face_reshape_01_85c8ffc055.jpg)\n\n\n\n**Facial Customization Parameters Guide**\n\n| Category | Parameter        | Function                             | Min (-100 / 0) | Max (100)    |\n| -------- | ---------------- | ------------------------------------ | -------------- | ------------ |\n| Eyes     | Size (L/R)       | Scales overall size of each eye      | Small          | Large        |\n| Eyes     | Width            | Adjusts horizontal span              | Narrow         | Wide         |\n| Eyes     | Height           | Adjusts vertical span                | Narrow / Flat  | Round / Tall |\n| Eyes     | Distance         | Adjusts spacing between eyes         | Close-set      | Wide-set     |\n| Eyes     | Angle            | Adjusts rotational tilt              | Inward tilt    | Outward tilt |\n| Face     | Size (L/R)       | Scales size of each side of the face | Small          | Large        |\n| Face     | Chin Shape (L/R) | Adjusts chin contour width           | Narrow         | Wide         |\n| Face     | Chin Length      | Adjusts vertical chin length         | Short          | Long         |\n| Face     | Width            | Adjusts overall facial width         | Narrow         | Wide         |\n| Face     | Cheekbone        | Adjusts cheekbone prominence         | Original (0)   | Tucked in    |\n| Face     | Jaw              | Adjusts jawline prominence           | Original (0)   | Tucked in    |\n| Lips     | Size             | Scales overall lip volume            | Small          | Large        |\n| Lips     | Width            | Adjusts horizontal span              | Narrow         | Wide         |\n| Lips     | Upper Height     | Adjusts top lip thickness            | Thin           | Full         |\n| Lips     | Lower Height     | Adjusts bottom lip thickness         | Thin           | Full         |\n| Lips     | Peak             | Adjusts Cupid's bow sharpness        | Smooth         | Defined      |\n| Nose     | Size             | Scales overall nose size             | Small          | Large        |\n| Nose     | Lift             | Adjusts vertical position            | Low            | High         |\n| Nose     | Bridge           | Adjusts bridge width                 | Narrow         | Wide         |\n| Nose     | Tip              | Adjusts vertical angle of the tip    | Up             | Down         |\n| Nose     | Wing             | Adjusts nostril width                | Narrow         | Wide         |\n| Nose     | Width            | Adjusts width of the nose tip        | Narrow         | Wide         |\n\n**Note:** *“Left” and “Right” refer to the character's perspective, not the viewer's side of the screen.*\n\n\n---\n\n* Supported Formats & Dimensions\n\n|AI Feature|Supported Dimensions|Supported File Size|Supported Formats|\n|  ----  | ----  | ----  | ----  |\n|AI Face Reshape|long side <= 4096|< 10MB|jpg/jpeg/png|\n\n* Error Codes\n\n| Error Code | Description |\n|  ----  | ----  |\n| RUNTIME_ERROR | An unexpected error occurred duface reshape runtime |\n| PHOTO_DETECTION_FAIL | The user photo could not be processed correctly, for example no hand detected |\n| OBJECT_DETECTION_FAIL | The object photo could not be processed correctly, for example no product detected |\n| PHOTO_CHECK_INVALID | The pose or size of the user photo is invalid |\n| INPUT_ERROR | The input file format is incorrect |\n| INPUT_MAIN_IMAGE_EMPTY | A user image is required |\n\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## JS Camera Kit\n{% partial file=\"/_partials/js-camera-kit.md\" /%}\n\n---\n\n## Unit Consumption\n\n| AI Feature | Unit Consumed |\n|---|---|\n| AI Face Reshape V1.0 | 1 |\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"
    }
  ],
  "paths": {
    "/s2s/v2.0/task/face-reshape/pre-process": {
      "post": {
        "summary": "Run an AI Face Reshape detection task.",
        "description": "Use the pre-process task when the source image may contain more than one valid target, or when your integration needs to explicitly choose which detected target receives the effect. For single-target images, pre-process can be skipped when the feature supports a default `index` value and your application does not need manual target selection.\n\nThe pre-process task detects candidate targets in the source image and returns their coordinates in `data.results.result`. Each item in the result array represents one detected target. Review the returned coordinates, map them to the intended face or region in the source image, and use that item's zero-based array index as the `index` value when creating the effect task.\n\nFor images with multiple detected faces or regions, do not rely on the default `index` value without checking the pre-process result. The effect is applied only to the target selected by `index`, so the integration must confirm the result item that corresponds to the intended target before running the effect task.\n\nThis task is asynchronous. After creating the task, handle completion with webhook if the feature supports it, or poll the corresponding pre-process status endpoint until `data.task_status` is `success` or `error`.\n",
        "tags": [
          "V1.0"
        ],
        "security": [
          {
            "BearerAuthenticationV2": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/BasicRunTaskV2"
                  }
                ]
              }
            }
          }
        },
        "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/RunError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/InvalidApiKey"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/s2s/v2.0/task/face-reshape/pre-process/{task_id}": {
      "get": {
        "summary": "Check the status of an AI Face Reshape detection task.",
        "description": "Use the pre-process task when the source image may contain more than one valid target, or when your integration needs to explicitly choose which detected target receives the effect. For single-target images, pre-process can be skipped when the feature supports a default `index` value and your application does not need manual target selection.\n\nThe pre-process task detects candidate targets in the source image and returns their coordinates in `data.results.result`. Each item in the result array represents one detected target. Review the returned coordinates, map them to the intended face or region in the source image, and use that item's zero-based array index as the `index` value when creating the effect task.\n\nFor images with multiple detected faces or regions, do not rely on the default `index` value without checking the pre-process result. The effect is applied only to the target selected by `index`, so the integration must confirm the result item that corresponds to the intended target before running the effect task.\n\nThis task is asynchronous. After creating the task, handle completion with webhook if the feature supports it, or poll the corresponding pre-process status endpoint until `data.task_status` is `success` or `error`.\n",
        "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": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/TaskStatusResponsePreProcessNoUrlBase"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "results": {
                              "type": "object",
                              "properties": {
                                "timed": {
                                  "type": "number"
                                },
                                "result": {
                                  "type": "array",
                                  "items": {
                                    "type": "object",
                                    "properties": {
                                      "left": {
                                        "type": "number"
                                      },
                                      "top": {
                                        "type": "number"
                                      },
                                      "width": {
                                        "type": "number"
                                      },
                                      "height": {
                                        "type": "number"
                                      }
                                    }
                                  }
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidTaskId"
          },
          "401": {
            "$ref": "#/components/responses/InvalidApiKey"
          },
          "500": {
            "$ref": "#/components/responses/TaskTimeout"
          }
        }
      }
    },
    "/s2s/v2.0/task/face-reshape": {
      "post": {
        "summary": "Run an AI Face Reshape task.",
        "description": "AI tasks are asynchronous. Prefer webhook-based completion handling when the feature supports webhooks. Configure your webhook endpoint, verify webhook signatures, and use the received `task_id` to query the task result after a `success` or `error` notification. See the [webhook integration guide](/develop/webhook.md) for setup and verification details.\n\nIf webhooks are not supported or cannot be used in your integration, implement polling. After submitting an AI task, poll the status endpoint at regular intervals (e.g., every 10 seconds) until the task status is `success` or `error`.\n",
        "tags": [
          "V1.0"
        ],
        "security": [
          {
            "BearerAuthenticationV2": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/BasicRunTaskV2"
                  },
                  {
                    "type": "object",
                    "required": [
                      "version",
                      "features",
                      "global"
                    ],
                    "properties": {
                      "version": {
                        "type": "string",
                        "description": "Version of the features specification. Defaults to `\"1.0\"` unless otherwise specified.\n",
                        "default": "1.0",
                        "example": "1.0"
                      },
                      "index": {
                        "type": "integer",
                        "example": 0,
                        "default": 0,
                        "description": "Zero-based index of the target object to apply the effect to. For multi-objects images, run the pre-process task first, inspect the object coordinates in `data.results.result`, and pass the index of the selected object here.\n\nThe pre-processing step analyzes the input image to identify all detectable objects before any effect is applied. It runs a detection task that returns structured data for each object, including a list of bounding box coordinates. The position of each entry in this list serves as its zero-based index, which is then used to specify the target object for the effect.\n\nThis information is returned in a structured format, commonly under `data.results.result`.\nBy running this step first, you can:\n    * Understand how many objects are present in the image\n    * Inspect their positions and sizes\n    * Select the correct target object by its index\n\nAlways run the pre-processing step for images with multiple objects.\nReview `data.results.result` to identify objects and their indices.\nUse the corresponding zero-based index to select the correct target."
                      },
                      "features": {
                        "type": "object",
                        "description": "Cannot be all zero",
                        "minProperties": 1,
                        "allOf": [
                          {
                            "$ref": "#/components/schemas/FaceReshapeFaceFeature"
                          },
                          {
                            "$ref": "#/components/schemas/FaceReshapeEyeFeature"
                          },
                          {
                            "$ref": "#/components/schemas/FaceReshapeNoseFeature"
                          },
                          {
                            "$ref": "#/components/schemas/FaceReshapeLipFeature"
                          }
                        ]
                      },
                      "global": {
                        "type": "object",
                        "description": "Skin smooth setup",
                        "properties": {
                          "skin_smooth_strength": {
                            "type": "integer",
                            "minimum": 0,
                            "maximum": 100,
                            "example": 50
                          },
                          "skin_smooth_color_intensity": {
                            "type": "integer",
                            "minimum": 0,
                            "maximum": 100,
                            "example": 50
                          }
                        }
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "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/RunError"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/InvalidApiKey"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/s2s/v2.0/task/face-reshape/{task_id}": {
      "get": {
        "summary": "Check the status of a AI Face Reshape 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": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/TaskStatusResponseV2"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "results": {
                              "type": "object",
                              "properties": {
                                "timed": {
                                  "type": "number"
                                },
                                "timed_apply": {
                                  "type": "number"
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidTaskId"
          },
          "401": {
            "$ref": "#/components/responses/InvalidApiKey"
          },
          "500": {
            "$ref": "#/components/responses/TaskTimeout"
          }
        }
      }
    }
  },
  "components": {
    "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'."
      }
    },
    "schemas": {
      "FaceReshapeFaceFeature": {
        "type": "object",
        "properties": {
          "cheekbones": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100
          },
          "jaw": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100
          },
          "face_reshape": {
            "type": "integer",
            "minimum": -100,
            "maximum": 100,
            "description": "Applies to both sides of the face. A per-side key (`face_reshape_left` / `face_reshape_right`) overrides this value for that side; a per-side `0` means that side is left unchanged."
          },
          "face_reshape_left": {
            "type": "integer",
            "minimum": -100,
            "maximum": 100
          },
          "face_reshape_right": {
            "type": "integer",
            "minimum": -100,
            "maximum": 100
          },
          "face_width": {
            "type": "integer",
            "minimum": -100,
            "maximum": 100
          },
          "chin_reshape": {
            "type": "integer",
            "minimum": -100,
            "maximum": 100,
            "description": "Applies to both sides of the chin. A per-side key (`chin_reshape_left` / `chin_reshape_right`) overrides this value for that side; a per-side `0` means that side is left unchanged."
          },
          "chin_reshape_left": {
            "type": "integer",
            "minimum": -100,
            "maximum": 100
          },
          "chin_reshape_right": {
            "type": "integer",
            "minimum": -100,
            "maximum": 100
          },
          "chin_length": {
            "type": "integer",
            "minimum": -100,
            "maximum": 100
          }
        },
        "example": {
          "cheekbones": 0,
          "jaw": 0,
          "face_reshape": 0,
          "face_reshape_left": 0,
          "face_reshape_right": 0,
          "face_width": 0,
          "chin_reshape": 0,
          "chin_reshape_left": 0,
          "chin_reshape_right": 0,
          "chin_length": 0
        }
      },
      "FaceReshapeEyeFeature": {
        "type": "object",
        "properties": {
          "eye_size": {
            "type": "integer",
            "minimum": -100,
            "maximum": 100,
            "description": "Applies to both eyes. A per-side key (`eye_size_left` / `eye_size_right`) overrides this value for that side; a per-side `0` means that side is left unchanged."
          },
          "eye_size_left": {
            "type": "integer",
            "minimum": -100,
            "maximum": 100
          },
          "eye_size_right": {
            "type": "integer",
            "minimum": -100,
            "maximum": 100
          },
          "eye_distance": {
            "type": "integer",
            "minimum": -100,
            "maximum": 100
          },
          "eye_angle": {
            "type": "integer",
            "minimum": -100,
            "maximum": 100
          },
          "eye_height": {
            "type": "integer",
            "minimum": -100,
            "maximum": 100
          },
          "eye_width": {
            "type": "integer",
            "minimum": -100,
            "maximum": 100
          }
        },
        "example": {
          "eye_size": 0,
          "eye_size_left": 0,
          "eye_size_right": 0,
          "eye_distance": 0,
          "eye_angle": 0,
          "eye_height": 0,
          "eye_width": 0
        }
      },
      "FaceReshapeNoseFeature": {
        "type": "object",
        "properties": {
          "nose_bridge_width": {
            "type": "integer",
            "minimum": -100,
            "maximum": 100
          },
          "nose_lift": {
            "type": "integer",
            "minimum": -100,
            "maximum": 100
          },
          "nose_size": {
            "type": "integer",
            "minimum": -100,
            "maximum": 100
          },
          "nose_tip": {
            "type": "integer",
            "minimum": -100,
            "maximum": 100
          },
          "nose_tip_width": {
            "type": "integer",
            "minimum": -100,
            "maximum": 100
          },
          "nose_wing": {
            "type": "integer",
            "minimum": -100,
            "maximum": 100
          }
        },
        "example": {
          "nose_bridge_width": 0,
          "nose_lift": 0,
          "nose_size": 0,
          "nose_tip": 0,
          "nose_tip_width": 0,
          "nose_wing": 0
        }
      },
      "FaceReshapeLipFeature": {
        "type": "object",
        "properties": {
          "lip_size": {
            "type": "integer",
            "minimum": -100,
            "maximum": 100
          },
          "lip_width": {
            "type": "integer",
            "minimum": -100,
            "maximum": 100
          },
          "lip_peak": {
            "type": "integer",
            "minimum": -100,
            "maximum": 100
          },
          "lip_height_top": {
            "type": "integer",
            "minimum": -100,
            "maximum": 100
          },
          "lip_height_bottom": {
            "type": "integer",
            "minimum": -100,
            "maximum": 100
          }
        },
        "example": {
          "lip_size": 0,
          "lip_width": 0,
          "lip_peak": 0,
          "lip_height_top": 0,
          "lip_height_bottom": 0
        }
      },
      "BasicRunTaskV2SrcFileUrl": {
        "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": {
        "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": [
          {
            "title": "Run task with src file url",
            "allOf": [
              {
                "$ref": "#/components/schemas/BasicRunTaskV2SrcFileUrl"
              }
            ]
          },
          {
            "title": "Run task with src file ID",
            "allOf": [
              {
                "$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"
              }
            }
          }
        }
      },
      "RunError": {
        "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": [
              "InvalidParameters",
              "CreditInsufficiency",
              "InvalidStyleGroup",
              "InvalidStyle",
              "BadRequest"
            ],
            "description": "Error code:\n  * InvalidParameters - Invalid request parameters\n  * CreditInsufficiency - Insufficient unit to run\n  * BadRequest - Unexpected request parameter\n  * InvalidStyleGroup - Invalid style group id\n  * InvalidStyle - Invalid style id\n"
          }
        }
      },
      "EngineErrorCode": {
        "type": "string",
        "nullable": true,
        "enum": [
          "error_exceed_max_image_size",
          "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- \\`error_exceed_max_image_size\\`  - Input image size exceeds the maximum limit\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"
      },
      "TaskStatusResponsePreProcessNoUrlBase": {
        "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"
              }
            }
          }
        }
      },
      "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": null
            }
          }
        },
        "$ref": "#/components/schemas/TaskStatusResponseBodySingleUrlResultsV2"
      }
    },
    "responses": {
      "InvalidApiKey": {
        "description": "Invalid or missing API key",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "properties": {
                "status": {
                  "type": "integer",
                  "example": 401,
                  "description": "Response status"
                },
                "error": {
                  "type": "string",
                  "example": "Invalid API key"
                }
              }
            }
          }
        }
      },
      "TooManyRequests": {
        "description": "Too many requests",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "properties": {
                "status": {
                  "type": "integer",
                  "example": 429,
                  "description": "Response status"
                },
                "error": {
                  "type": "string",
                  "example": "Too many requests"
                }
              }
            }
          }
        }
      },
      "InvalidTaskId": {
        "description": "Invalid task ID",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "properties": {
                "status": {
                  "type": "integer",
                  "example": 400,
                  "description": "Response status"
                },
                "error": {
                  "type": "string",
                  "example": "Invalid task ID"
                }
              }
            }
          }
        }
      },
      "TaskTimeout": {
        "description": "Task execution timeout",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "properties": {
                "status": {
                  "type": "integer",
                  "example": 500,
                  "description": "Response status"
                },
                "error": {
                  "type": "string",
                  "example": "Task execution timed out"
                }
              }
            }
          }
        }
      }
    }
  }
}