{
  "openapi": "3.0.0",
  "info": {
    "title": "AI Abs Filter",
    "description": "# Overview\n\nThe **AI Abs Filter API** lets you add realistic abdominal definition to a photo and generate an athletic body-shaping result with minimal effort. Upload a full-body or upper-body image, select the desired enhancement mode, set the intensity level, and receive an edited output image.\n\n![](https://plugins-media.makeupar.com/smb/blog/post/2024-09-27/daf70f5e-a350-46a3-8b6c-f63bd60c6cf0.jpg)\n\nSupported modes:\n\n- `Six-pack`: Adds visible six-pack abs for a more muscular torso appearance.\n- `Vest-line`: Enhances central abdominal muscle definition for a fit, athletic look.\n\n---\n\n## Integration Guide\n\n**Input Requirements & Processing Criteria:**\n\n- Upload a full-body or upper-body image.\n- Select an enhancement mode: `Six-pack` or `Vest-line`.\n- Choose the desired abdominal enhancement intensity level.\n- Maximum long-side image resolution must not exceed **4096 px**.\n- Source file size must be less than **10 MB**.\n- At least one detectable person is required, with both shoulders visible.\n- The abdomen must be visible, either clothed or unclothed.\n- Supported pose range: `−45° < yaw < 45°`.\n- Single-person processing is supported. If multiple people appear in the image, the API automatically selects the person with the largest visible shoulder area.\n\n**Workflow:**\n\n1. Upload file metadata using the File API.\n2. Retrieve the signed upload URL from the response.\n3. Upload the actual image to the returned URL.\n4. Create an AI task for abs-shape enhancement.\n5. Setup a Webhook or Poll the task status until completion.\n6. Download the generated result image when processing is successful.\n\n---\n\n**Step 1 — Upload File Metadata Using the File API**\n\nUse `POST /s2s/v2.0/file` to create a file record and receive upload details for the source image.\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**File API 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 2 — Retrieve File API Response Details**\n\nThe response contains:\n\n| Field | Description |\n| --- | --- |\n| `file_id` | Identifier used to create the AI task. |\n| `requests.url` | Signed URL for uploading the actual image file. |\n| `requests.method` | Upload method, usually `PUT`. |\n| `requests.headers` | Required headers for the upload request. |\n\n---\n\n**Step 3 — Upload Image to Provided URL**\n\nUse the `requests.url` from the File API response to upload the source 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 — Create an AI Task**\n\nUse `POST /s2s/v2.0/task/abs-shape` to create the abs-enhancement task.\n\n| Parameter | Description | Example |\n| --- | --- | --- |\n| `src_file_id` | File ID returned from the File API upload flow. Required when using uploaded-file workflow. | `\"SaGaqpDgKwFrVBgMpQMA3HY0LeqdT9/13W5TOD8/u/FfjK3xgCQ+hRt9MJXBFaud\"` |\n| `src_file_url` | Direct URL of the source image. Use this alternative to `src_file_id`. | `\"https://example.com/selfie.jpg\"` |\n| `mode` | Enhancement mode. Supported values are `Six-pack` and `Vest-line`. | `\"Six-pack\"` |\n| `intensity` | Abdominal enhancement intensity level. | `1` |\n\n**Example Request:**\n\n```javascript\nconst resp = await fetch(\n  'https://yce-api-01.makeupar.com/s2s/v2.0/task/abs-shape',\n  {\n    method: 'POST',\n    headers: {\n      'Content-Type': 'application/json',\n      Authorization: 'Bearer <YOUR_TOKEN_HERE>'\n    },\n    body: JSON.stringify({\n      src_file_url: 'https://example.com/selfie.jpg',\n      mode: 'Six-pack',\n      intensity: 1\n    })\n  }\n);\n\nconst data = await resp.json();\nconsole.log(data);\n```\n\n**AI Task API 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 5 — Setup a Webhook or Poll for Task Result**\n\nSee the [webhook integration guide](/develop/webhook.md) for setup and verification details.\n\nFor polling, use the returned `task_id` to check task status.\n\n```bash\ncurl --request GET \\\n  --url https://yce-api-01.makeupar.com/s2s/v2.0/task/abs-shape/<YOUR_TASK_ID> \\\n  --header 'Authorization: Bearer YOUR_API_KEY' \\\n  --header 'content-type: application/json'\n```\n\n---\n\n**Step 6 — Retrieve Result Image**\n\nWhen processing is successful, the response includes a download URL in `data.results.url`.\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\n**Invalid API Key Response:**\n\nIf the access token is invalid, the API returns a `401` response.\n\n```json\n{\n  \"status\": 401,\n  \"error\": \"Unauthorized\",\n  \"error_code\": \"InvalidAccessToken\"\n}\n```\n\nUse cases:\n![](https://plugins-media.makeupar.com/smb/blog/post/2025-08-21/307f87b4-d31c-481c-86f1-478c93265a95.jpg)\n\n![](https://plugins-media.makeupar.com/smb/blog/post/2025-08-21/8ab8eca4-b825-4692-aef0-6ffd6176e272.jpg)\n\n---\n\n## File Specs & Errors\n\n**File Specifications:**\n\n| Specification | Requirement |\n| --- | --- |\n| Image type | Full-body or upper-body image. |\n| Source subject | One detectable person with both shoulders visible and abdomen visible. |\n| Pose requirement | Supported pose range is `−45° < yaw < 45°`. |\n| Multi-person handling | If multiple people are detected, the API automatically selects the person with the largest visible shoulder area. |\n| Maximum long-side resolution | Long side must not exceed **4096 px**. |\n| File size limit | Must be less than **10 MB**. |\n| Supported formats | `jpg`, `png`. |\n\n**Error Codes:**\n\n| Error Code | Description |\n| --- | --- |\n| `exceed_max_filesize` | The source image exceeds the maximum allowed dimensions or file size. The long side must not exceed 4096 px, and the file size must remain below 10 MB. |\n| `error_pose` | Pose detection failed due to missing person detection, shoulder visibility issues, abdomen visibility issues, waist-region detection failure, hip-keypoint detection failure, or unsupported pose range. |\n| `error_nsfw_content_detected` | Potential NSFW content was detected in the source image or generated result image. |\n| `invalid_parameter` | Invalid parameters were provided for source keys, destination keys, actions, mode values, intensity levels, or task configuration. |\n| `error_download_image` | The source image could not be downloaded successfully. |\n| `error_decode_image` | The source image could not be decoded successfully. |\n\n**Environment & Dependencies:**\n\n| Tool / Language | Recommended Runtime Versions |\n| --- | --- |\n| cURL | Bash ≥ 3.2; curl ≥ 7.58 with modern TLS/HTTP support; jq ≥ 1.6 for robust JSON parsing. |\n| Node.js | Node ≥ 18 for global `fetch` support. |\n| JavaScript Browser Support | Chrome / Edge ≥ 80, Firefox ≥ 74, Safari ≥ 13.1. |\n| PHP | PHP ≥ 7.4 with modern TLS compatibility; ext-curl recommended or `allow_url_fopen=On` with OpenSSL and JSON support. |\n| Python | Python ≥ 3.10 for f-strings; requests ≥ 2.20.0. |\n| Java | Java 11+ for HttpClient; Jackson Databind ≥ 2.12.0. |\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/youcamapps/youcam/privacy-policy.html"
    }
  },
  "servers": [
    {
      "url": "https://yce-api-01.makeupar.com"
    }
  ],
  "tags": [
    {
      "name": "V1.0",
      "description": "Transform your upper-body photo with AI-generated six-pack abs using the AI Abs Filter API."
    }
  ],
  "paths": {
    "/s2s/v2.0/task/abs-shape": {
      "post": {
        "summary": "Run an AI Abs Filter 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 for the feature, or if your integration cannot use webhooks, implement polling. After starting an AI task, keep polling the task status endpoint at the given `polling_interval` until the task status is either `success` or `error`.\n\nDo not stop polling a running task for longer than the allowed polling window. If the task is not polled in time, the task may expire; a later status check can return `InvalidTaskId` even if processing finished, and the consumed units may still be charged.\n",
        "tags": [
          "V1.0"
        ],
        "security": [
          {
            "BearerAuthenticationV2": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/BasicRunTaskV2"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "mode": {
                        "type": "string",
                        "description": "The abs effect user to choose.\n",
                        "default": "Six-pack",
                        "example": "Six-pack",
                        "enum": [
                          "Six-pack",
                          "Vest-line"
                        ]
                      },
                      "intensity": {
                        "type": "integer",
                        "description": "The intensity the users wish to adjust their abs, 2 is the stronger intensity.\n",
                        "default": 1,
                        "example": 1,
                        "enum": [
                          1,
                          2
                        ]
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "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/abs-shape/{task_id}": {
      "get": {
        "summary": "Check the status of a AI Abs Filter task.",
        "x-display-name": "AI Abs Filter",
        "x-engine-version": "V1.0",
        "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": {
      "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"
      },
      "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"
                }
              }
            }
          }
        }
      }
    }
  }
}