openapi: 3.0.0
info:
  title: AI Smile
  description: >
    # overview

    Introducing Generative AI Smile API, the easy way to turn that frown upside
    down. This convenient AI smile generator transforms sad or neutral facial
    expressions into happy, natural looking smiles in just moments. Powered by
    advanced generative AI, it helps bring warmth and positivity to any photo
    with a simple and effortless process. Upload an image, let the AI work its
    magic, and instantly convert your sad face into a cheerful smiley face that
    spreads happiness everywhere it's shared.


    The AI Smile generator supports two distinct smile styles, giving users more
    control over the final expression.


    1.  **smile_with_teeth_visible**  
        This option creates a bright, joyful smile with naturally visible teeth. It is ideal for upbeat portraits, social media photos, and situations where a warm and expressive look is desired.

    2.  **closed_mouth_smile**  
        This option produces a subtle, gentle smile with lips closed. It works well for professional photos, formal profiles, or when a calm and natural expression is preferred.

    Users can easily choose the smile type that best matches their photo, mood,
    or intended use, ensuring realistic and appealing results every time.


    Whether you're editing photos, creating fun content, or simply want to add a
    touch of positivity, Generative AI Smile makes it easy to spread happiness,
    one smile at a time.


    Upload a face. Click once. Smile instantly.


    ![](https://plugins-media.makeupar.com/smb/blog/post/2024-03-22/5f25b0f7-5d43-421b-ae50-5def0de69f2a.jpg)


    ![](https://plugins-media.makeupar.com/smb/blog/post/2024-12-16/4f4397e0-9e87-429a-8e39-a9d399b6602b.jpg)


    ## Integration Guide

    This guide walks you through:


    Workflow for AI Smile API:


    **Endpoint:** `/s2s/v2.0/task/ai-smile`


    **Authentication Required:** `Authorization: Bearer YOUR_API_KEY`


    **Workflow Steps:**


    1. **Image Upload Preparation:**
        - Prepare a selfie image for upload.
        - Call the File API `/s2s/v2.0/file` to obtain the upload URL and associated `file_id`.
        - Upload the selfie image using the provided upload URL.

    2. **Initiate AI Task and Obtain Task ID:**
        - Send the `file_id` along with the chosen effect configuration via an HTTP POST request to `/s2s/v2.0/task/ai-smile`.
        - Await a unique task ID in the response, which identifies this interaction.

    3. **Poll Task Status (Continuous Check):**
        - Use the obtained `task_id` to periodically poll the task status using an HTTP GET request (e.g., `GET /s2s/v2.0/task/ai-smile/${task_id}`).
        - Continuously monitor for:
            - `Task_status = "success"` (process completed).
            - `Task_status = "error"` (resolve or retry if applicable).
        - Update the workflow accordingly once the status transitions to success.

    This structured workflow ensures efficient integration with user inputs,
    automated monitoring of tasks, and seamless retrieval of results.



    ---


    1. Authentication

    - Include your API key in the request header using **Bearer Token**:
        ```
        Authorization: Bearer YOUR_API_KEY
        ```
    You can find your API Key at
    https://yce.makeupar.com/api-console/en/api-keys/.



    2. Upload an Image

        You may upload a file directly to the server or provide a valid image URL in the AI task payload.

       * Upload Endpoint

            ```
            POST /s2s/v2.0/file
            ```

        Alternatively, skip this step if you already have a public image URL.

    ---


    3. Create an AI Smile Task and Poll for Results

        Once you have an image and a complete effect setup, create a task. The API processes the request asynchronously. You must poll the task status until it reaches `success` or `error`.

        * Create Task Endpoint

            ```
            POST /s2s/v2.0/task/ai-smile
            ```

        * Polling Endpoint

            ```
            GET /s2s/v2.0/task/ai-smile/{task_id}
            ```

    ---


    ## File Specs & Errors


    * AI Smile Specification


    **Supported Selfie View**

    Only single-person images are supported, the image must contain a clearly
    visible face of sufficient size exceeding 32 x 32 pixels when the long edge
    is 640, and the capture angles must have a roll within plus or minus 75
    degrees and a yaw within plus or minus 90 degrees to avoid face detection
    failure.


    ![](https://plugins-media.makeupar.com/strapi/assets/thumbnail_face_reshape_01_85c8ffc055.jpg)



    ---


    * Supported Formats & Dimensions


    | AI Feature | Supported Dimensions | Supported File Size | Supported
    Formats|

    |  ----  | ----  | ----  | ----  |

    | AI Smile | long side <= 4096 | < 10MB | jpg/jpeg/png/heic |



    * Error Codes


    | Error Code | Description |

    | ---------- | ----------- |

    | EXCEED_MAX_FILESIZE  | The input file exceeds the maximum allowed size. |

    | INVALID_PARAMETER     | One or more required parameters are missing,
    empty, or improperly formatted.  |

    | ERROR_DOWNLOAD_IMAGE | The source image could not be downloaded. |

    | ERROR_NO_FACE        | No face was detected in the provided image. |

    | ERROR_INFERENCE       | The inference process failed due to a workflow
    issue, execution error, encoding error, or missing output image. |

    | UNKNOWN_INTERNAL_ERROR | An unexpected internal error occurred. |



    * Environment & Dependency


    | Sample Code Language / Tool | Recommended Runtime Versions |

    |---|---|

    | cURL | - bash >= 3.2</br>   - curl >= 7.58 (modern TLS/HTTP
    support)</br>   - jq >= 1.6 (robust JSON parsing) |

    | Node.js (JavaScript) | Node >= 18 (for global fetch) |

    | JavaScript | - Chrome / Edge >= 80</br>   - Firefox >= 74</br>   - Safari
    >= 13.1 |

    | PHP | PHP >= 7.4 (for modern TLS/compat), ext-curl (recommended) or
    allow_url_fopen=On + ext-openssl, ext-json |

    | Python | Python >= 3.10 (for f-strings), requests >= 2.20.0 |

    | Java | Java 11+ (for HttpClient), Jackson Databind >= 2.12.0 |


    ---


    ## Unit Consumption


    | AI Feature | Unit Consumed |

    |---|---|

    | AI Smile V1.0 | 1 |


    ---
  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: >-
      Turn that frown upside down and convert your sad face into a happy smiley
      face with this convenient AI smile generator.
paths:
  /s2s/v2.0/task/ai-smile:
    post:
      summary: Run an AI Smile 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.


        If 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`.


        Do 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.
      tags:
        - V1.0
      security:
        - BearerAuthenticationV2: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              allOf:
                - $ref: '#/components/schemas/BasicRunTaskV2'
                - type: object
                  required:
                    - expression_type
                  properties:
                    expression_type:
                      type: string
                      enum:
                        - smile_with_teeth_visible
                        - closed_mouth_smile
      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/ai-smile/{task_id}:
    get:
      summary: Check the status of a AI Smile 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:
    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:
              * InvalidParameters - Invalid request parameters
              * CreditInsufficiency - Insufficient unit to run
              * BadRequest - Unexpected request parameter
              * InvalidStyleGroup - Invalid style group id
              * InvalidStyle - Invalid style id
    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:

        - \`error_exceed_max_image_size\`  - Input image size exceeds the
        maximum limit

        - \`exceed_max_filesize\` - Input file size exceeds the maximum limit

        - \`invalid_parameter\` - Invalid parameter value

        - \`error_download_image\` - Download source image error

        - \`error_download_mask\` - Download mask image error

        - \`error_decode_image\` - Decode source image error

        - \`error_decode_mask\` - Decode mask image error

        - \`error_nsfw_content_detected\` - NSFW content detected in source
        image

        - \`error_no_face\` - No face detected on source image

        - \`error_pose\` - Failed to detect pose on source image

        - \`error_face_parsing\` - Failed to do face segmentation on source
        image

        - \`error_inference\` - Inference pipeline error

        - \`exceed_nsfw_retry_limits\` - Exceed the retry limits to avoid
        generated NSFW image

        - \`error_upload\` - Upload result image error

        - \`unknown_internal_error\` - Others
    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
