{
  "openapi": "3.0.0",
  "info": {
    "title": "AI Necklace Virtual Try On",
    "description": "# Overview\nLuxurious Look and Feel with State-of-the-Art Virtual Try-On for Necklace\nPrecise AI neck and clavicle tracking gives users an ultra-realistic AR try-on experience, recreating the luxurious look and feel of physical necklace sampling.\n\nCreate realistic and dynamic necklace vitual try-on from a 2D image, no expensive 3D modelling required. Our advanced algorithms create lifelike virtual try-on necklace SKUs with sophisticated lighting effects and physically accurate motions.\n\n## Integration Guide\nThis guide walks you through:\n\n*   **Endpoint:** `/s2s/v2.0/task/2d-vto/necklace`\n*   **Authentication:** All requests require an `Authorization: Bearer YOUR_API_KEY`\n*   **Workflow:**\n    1.  **Prepare a selfie image:** Uploading an image or provide a valid image URL\n    2.  **Prepare a necklace image:** Uploading an image or provide a valid image URL of a necklace product\n    3.  **Fire an AI task and Retrieve Task ID:** Capture the `task_id` from the response.\n    4.  **Poll Status (`GET`):** Use the `task_id` to check the status of the task. Continue polling until `task_status` is `\"success\"` or `\"error\"`.\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-necklace-virtual-try-on/](http://yce.makeupar.com/api-console/en/api-playground/ai-necklace-virtual-try-on/)\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\n* 1. Upload an Image\n\nYou may upload a file directly to the server or provide a valid image URL in the VTO task payload.\n\n   * Upload Endpoint\n\n```\nPOST /s2s/v2.0/file\n```\n\nAlternatively, skip this step if you already have a public image URL.\n\nYou may upload a file directly to the URL provided in the response from the File API and then use the corresponding `src_file_id` returned by the File API to invoke the AI task later. Or provide a valid image URL in the VTO task payload as `src_file_url`. The `src_file_id` or `src_file_url` will serve as the virtual try-on target.\n\nYou must also provide another necklace product image as a reference using `ref_file_ids` or `ref_file_urls` to be applied to your `src_file_id` or `src_file_url`.\n\nThe AI engine supports automatic background removal for your selfie. However, you may provide an occlusion mask image file for your neck (`srcmsk_file_id` or `srcmsk_file_url`) to fine-tune the segmentation.\n\n---\n\n* 2. Create a Necklace VTO Task and Poll for Results\n\nOnce you have an image and a template ID, 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```\nPOST /s2s/v2.0/task/2d-vto/necklace\n```\n\n   * Polling Endpoint\n\n```\nGET /s2s/v2.0/task/2d-vto/necklace/{task_id}\n```\n\n---\n\n## File Specs & Errors\n\n* AI Necklace Virtual Try-On Specification\n\n**Supported Necklace View**\nA front-facing image of the necklace worn, with the background removed.\n\n![](https://bcw-media.s3.ap-northeast-1.amazonaws.com/strapi/assets/necklace_product_01_124206cfbe_3993a2128d.jpg)\n\n**Supported Selfie View**\nA front-facing selfie with the neck clearly visible and unobstructed. Horizontal head rotation is supported within 20 degrees. The head size should be proportionate, and the neck width should occupy at least 15 per cent of the image width.\n\n![](https://bcw-media.s3.ap-northeast-1.amazonaws.com/strapi/assets/Necklace_restriction_83410fb6c1.png)\n\n**necklace\\_wearing\\_location: array of two points (optional)**\nSpecifies the target locations in the photo where the necklace should be placed.\nDefault: null (engine default)\n\n![](https://bcw-media.s3.ap-northeast-1.amazonaws.com/strapi/assets/wearing_location_874264bb70.jpg)\n\n**necklace\\_shadow\\_intensity: float (0.0 to 1.0)**\nControls the shadow strength:\n0.0 represents no shadow\n1.0 represents maximum shadow\nDefault value: 0.15\n\n**necklace\\_ambient\\_light\\_intensity: float (0.0 to 1.0)**\nDefines how much the lighting references the selfie image:\n0.0 ignores the selfie image lighting\n1.0 fully matches the selfie image lighting and shadow rendering\nDefault value: 1.0\n\n**necklace\\_anchor\\_point: array of two points in pixel coordinate (optional)**\nSpecifies the anchor points for the left and right visible ends of the necklace chain in the product image, used for alignment.\nDefault: null (engine default)\n\n![](https://bcw-media.s3.ap-northeast-1.amazonaws.com/strapi/assets/anchor_point_7f9b254ca4.jpg)\n\n---\n\n* Supported Formats & Dimensions\n\n|AI Feature|Supported Dimensions|Supported File Size|Supported Formats|\n|  ----  | ----  | ----  | ----  |\n|AI Necklace Virtual Try-On|long side <= 4096 |< 10MB|jpg/jpeg/png|\n\n* Error Codes\n\n|Error Code|Description|\n|  ----  | ----  |\n| RUNTIME_ERROR | An unexpected error occurred dunecklace runtime |\n| PHOTO_DETECTION_FAIL | The user photo could not be processed correctly, for example no neck 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 Necklace Virtual Try-On V1.0 | 1 Unit for Single-item wear |\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": "Generate virtual try-on experiences for necklaces from uploaded images using AI processing, supporting alignment and shadow parameters."
    }
  ],
  "paths": {
    "/s2s/v2.0/task/2d-vto/necklace": {
      "post": {
        "summary": "Run an AI 2D Virtual Try On Necklace task.",
        "description": "This endpoint initiates the necklace virtual try-on process. You must provide source file(s) and reference image(s) (via URL or File ID), along with specific parameters for alignment, shadowing, and wearing location. The task will be processed asynchronously, and you can check its status using the task_id returned in this response.\n",
        "tags": [
          "V1.0"
        ],
        "security": [
          {
            "BearerAuthenticationV2": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NecklaceRunTaskV2"
              }
            }
          }
        },
        "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/2d-vto/necklace/{task_id}": {
      "get": {
        "summary": "Check the status of a AI 2D Virtual Try On Necklace 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": {
            "$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": {
      "NecklaceRunTaskV2": {
        "allOf": [
          {
            "anyOf": [
              {
                "allOf": [
                  {
                    "title": "Run task with src file url & srcmsk file url & ref file urls"
                  },
                  {
                    "$ref": "#/components/schemas/BasicRunTaskV2SrcFileUrl"
                  },
                  {
                    "$ref": "#/components/schemas/2dVtoRunTaskV2SrcmskFileUrl"
                  },
                  {
                    "$ref": "#/components/schemas/2dVtoRunTaskV2RefFileUrls"
                  }
                ]
              },
              {
                "allOf": [
                  {
                    "title": "Run task with src file url & srcmsk file url & ref file IDs"
                  },
                  {
                    "$ref": "#/components/schemas/BasicRunTaskV2SrcFileUrl"
                  },
                  {
                    "$ref": "#/components/schemas/2dVtoRunTaskV2SrcmskFileUrl"
                  },
                  {
                    "$ref": "#/components/schemas/2dVtoRunTaskV2RefFileIds"
                  }
                ]
              },
              {
                "allOf": [
                  {
                    "title": "Run task with src file ID & srcmsk file ID & ref file urls"
                  },
                  {
                    "$ref": "#/components/schemas/BasicRunTaskV2SrcFileId"
                  },
                  {
                    "$ref": "#/components/schemas/2dVtoRunTaskV2SrcmskFileId"
                  },
                  {
                    "$ref": "#/components/schemas/2dVtoRunTaskV2RefFileUrls"
                  }
                ]
              },
              {
                "allOf": [
                  {
                    "title": "Run task with src file ID & srcmsk file ID & ref file IDs"
                  },
                  {
                    "$ref": "#/components/schemas/BasicRunTaskV2SrcFileId"
                  },
                  {
                    "$ref": "#/components/schemas/2dVtoRunTaskV2SrcmskFileId"
                  },
                  {
                    "$ref": "#/components/schemas/2dVtoRunTaskV2RefFileIds"
                  }
                ]
              }
            ]
          },
          {
            "$ref": "#/components/schemas/2dVtoRunTaskV2SrcInfo"
          },
          {
            "type": "object",
            "required": [
              "object_infos"
            ],
            "properties": {
              "object_infos": {
                "type": "array",
                "items": {
                  "type": "object",
                  "required": [
                    "name"
                  ],
                  "properties": {
                    "name": {
                      "type": "string",
                      "description": "The reference url or File ID. Indicate which reference product image should be matched.",
                      "example": "https://example.com/vto_sku.jpg"
                    },
                    "parameter": {
                      "type": "object",
                      "description": "Contain several object informations in this list.",
                      "properties": {
                        "necklace_need_remove_background": {
                          "type": "boolean",
                          "description": "Whether the necklace image needs background removal.",
                          "default": true,
                          "example": true
                        },
                        "necklace_anchor_point": {
                          "type": "array",
                          "description": "The anchor points of the necklace image, used for alignment. <br>Type: 2x2 list of integers <br>Range: [[x, y], [x, y]] (pixel coordinates) <br>Default: null (use engine default)",
                          "default": null,
                          "example": null,
                          "minItems": 2,
                          "maxItems": 2,
                          "items": {
                            "type": "array",
                            "minItems": 2,
                            "maxItems": 2,
                            "items": {
                              "type": "integer"
                            }
                          }
                        },
                        "necklace_wearing_location": {
                          "type": "array",
                          "description": "The target locations of photo where the necklace should be placed. <br>Type: 2x2 list of integers <br>Range: [[x, y], [x, y]] (pixel coordinates) <br>Default: null (use engine default)",
                          "default": null,
                          "example": null,
                          "minItems": 2,
                          "maxItems": 2,
                          "items": {
                            "type": "array",
                            "minItems": 2,
                            "maxItems": 2,
                            "items": {
                              "type": "integer"
                            }
                          }
                        },
                        "necklace_shadow_intensity": {
                          "type": "number",
                          "description": "Shadow intensity applied to the necklace (higher = darker shadow).",
                          "minimum": 0,
                          "maximum": 1,
                          "default": 0.5,
                          "example": 0.5
                        },
                        "necklace_ambient_light_intensity": {
                          "type": "number",
                          "description": "Ambient light adjustment intensity for the necklace.",
                          "minimum": 0,
                          "maximum": 1,
                          "default": 0.5,
                          "example": 0.5
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        ]
      },
      "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"
          }
        }
      },
      "2dVtoRunTaskV2SrcmskFileUrl": {
        "type": "object",
        "properties": {
          "srcmsk_file_url": {
            "type": "string",
            "description": "Url of the source mask file to run task. The url should be publicly accessible.",
            "example": "https://example.com/src_mask.jpg"
          }
        }
      },
      "2dVtoRunTaskV2RefFileUrls": {
        "type": "object",
        "required": [
          "ref_file_urls"
        ],
        "properties": {
          "ref_file_urls": {
            "type": "array",
            "description": "Url of the reference file to run task. The url should be publicly accessible.",
            "example": [
              "https://example.com/vto_sku.jpg"
            ],
            "items": {
              "type": "string"
            }
          }
        }
      },
      "2dVtoRunTaskV2RefFileIds": {
        "type": "object",
        "required": [
          "ref_file_ids"
        ],
        "properties": {
          "ref_file_ids": {
            "type": "array",
            "description": "ID of the reference file file to run task. File ID from upload file API.",
            "example": [
              "pfNK5PuRe0MrwLHcGA3DOmB1ahwfXTbYHjv+KoBIxbE="
            ],
            "items": {
              "type": "string"
            }
          }
        }
      },
      "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="
          }
        }
      },
      "2dVtoRunTaskV2SrcmskFileId": {
        "type": "object",
        "properties": {
          "srcmsk_file_id": {
            "type": "string",
            "description": "ID of the source mask file to run task. File ID from upload file API.",
            "example": "pfNK5PuRe0MrwLHcGA3DOmB1ahwfXTbYHjv+KoBIxbE="
          }
        }
      },
      "2dVtoRunTaskV2SrcInfo": {
        "type": "object",
        "required": [
          "source_info"
        ],
        "properties": {
          "source_info": {
            "type": "object",
            "description": "Contain source photo informations.",
            "properties": {
              "name": {
                "type": "string",
                "description": "The source url or File ID.",
                "example": "https://example.com/selfie.jpg"
              },
              "mask_name": {
                "type": "string",
                "description": "The source mask url or File ID.",
                "example": "https://example.com/src_mask.jpg"
              }
            },
            "required": [
              "name"
            ]
          }
        }
      },
      "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"
      },
      "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"
                }
              }
            }
          }
        }
      }
    }
  }
}