InsightFaceSwap /picsi command

February 12, 2024 (November 18, 2024)

Table of contents

  1. Request Headers
  2. Request Body
  3. Responses
  4. Model
  5. Examples
  6. Try It

Use this endpoint to submit the InsightFaceSwap /picsi command to directly generate a Picsi.Ai face morph by attaching a source image and target image/gif/video. The result will be returned in the response body and can also be sent as a callback to an optional replyUrl.

This is a blocking call, you will not be able to make another call to the same InsightFaceSwap Discord channel until the current call is completed. The average execution time is approximately 3 to 10 seconds. If you expect high load and need to make multiple concurrent calls, please consider setting up multiple InsightFaceSwap accounts.

It is important not to use the InsightFaceSwap account setup for API access for any purposes other than its intended use, such as executing /picsi or any other InsightFaceSwap commands manually or in conjunction with any other automation tools. The useapi.net API internally tracks the usage of the InsightFaceSwap account, including the number of currently active executions. Using it for other activities may cause API to function incorrectly.

https://api.useapi.net/v1/faceswap/picsi

Request Headers
Authorization: Bearer {API token}
Content-Type: multipart/form-data
Request Body
{
    "channel": "Discord channel id",
    "source_image": "Source image",
    "target_image_gif_or_video": "Target Image/GIF/Video",
    "options": "Optional parameters such as -f (Face Texturizer), -m (Retain Mouth) etc",
    "replyUrl": "Place your call back URL here",
    "replyRef": "Place your reference id here"
}
  • channel is optional, if omitted a randomly selected configured channel with available credits will be used.

  • source_image is required, source image. Must be either a File or Blob object when included in this FormData POST request.

  • target_image_gif_or_video is required, target image/GIF/Video. Must be either a File or Blob object when included in this FormData POST request.
    Important Video currently not supported.

  • options is optional, for parameters such as -f (Face Texturizer), -m (Retain Mouth), see official help for details.

    Options supported by Free version (this may not be a complete or current list, please refer to official help):

    • -m Keeps the mouth area of the target picture unchanged in the morphed result.
    • --shut Keeps eyes closed in your morphed results matching the closed eyes of the target face. To be used ONLY when the eyes are already closed in the target picture’s face. This will NOT close eyes that are open.
    • --ch Corrects mismatches in chin and jawline between source and target faces.
    • --hl Addresses issues with bangs or low hairlines in source photos morphing incorrectly on target face.

    Options supported by Paid version (this may not be a complete or current list, please refer to official help):

    • -f Face Texturizer mode attempts to preserve intricate details of the target face like fine wrinkles, blemishes and freckles.
    • -s Sharpen option adds clarity and definition.
    • -e Expression Matching synchronizes the expressions between your source face and the target face in the morph. This includes aspects like smiles, frowns, or any other facial expressions, aiming to retain the target face’s expression in the resulting morph for enhanced realism.
    • -e 1...1000 Expression intensity.
    • -o or --oldify Transforms faces in your images to appear older, offering an intriguing look into the future.
    • -o 1...1000 Oldify intensity
    • -y Youngify is a unique feature that blends adult-like features from a source face onto young or childlike target pictures. It’s designed to enhance the blend between adult features and a young-looking target face, but does not transform adults into children or make faces appear younger.
    • -y 1...1000 Youngify intensity
    • -a ARTIFY enriches the morphing experience by enabling your photorealistic source face to blend seamlessly with a pre-stylized artistic target image.
    • -x Xtreme specially designed for creating ultra-detailed, close-up portraits.
  • replyUrl is optional, if not provided value from account will be used.
    Place here your callback URL. API will call the provided replyUrl once job completed or failed.
    Maximum length 1024 characters.
    We recommend using sites like webhook.site to test callback URL functionality.

  • replyRef is optional, place here your reference id which will be stored and returned along with this job response / result.
    Maximum length 1024 characters.

Responses
  • 200 OK

    If field status returned as started use returned jobid to retrieve InsightFaceSwap job status and results or use callback replyUrl.

    Field content contains message generated by InsightFaceSwap. Attachments array contains generated images.

    {
        "jobid": "<jobid>",
        "verb": "faceswap-picsi",
        "status": "completed",
        "options": "-m",
        "source_image": { "size": 2438986, "type": "image/png" },
        "target_image_gif_or_video": { "size": 1604758, "type": "image/png" },
        "created": "2023-09-09T02:04:49.667Z",
        "updated": "2023-09-09T02:04:53.490Z",
        "discord": "<ABC…secured…xyz>",
        "server": "<Discord server id>",
        "channel": "<Discord channel id>",
        "replyUrl": "https://webhook.site/abc",
        "replyRef": "<your optional reference id>",
        "messageId": "<Discord message id>",
        "content": "<@Discord user id>",
        "attachments": [
          {
            "url": "<generated image_1 url>",
            "proxy_url": "<generated proxy image_1 url>",
            "width": 2048,
            "height": 2048,
            "content_type": "<generated image_1 type>",
            "id": "<Discord image_1 id>",
            "filename": "<generated image_1 name>",
            "size": 7204115
          },
          {
            "url": "<generated image_N url>",
            "proxy_url": "<generated proxy image_N url>",
            "width": 2048,
            "height": 2048,
            "content_type": "<generated image_N type>",
            "id": "<Discord image id>",
            "filename": "<generated image_N name>",
            "size": 7204115
          }
        ],
        "timestamp": "2023-09-09T02:04:51.926000+00:00",
        "code": 200
    }
    
  • 400 Bad Request

    {
        "error": 
          "Required param source_image or target_image_gif_or_video is missing or empty"
          "Param source_image or target_image_gif_or_video is not File or Blob"
          "Optional param replyUrl or replyRef is too long"
          "Configuration not found for channel <channel>, to create POST v1/faceswap/account/<channel>"
        "code": 400
    }
    
  • 401 Unauthorized

    {
        "error": "Unauthorized",
        "code": 401
    }
    
  • 402 Payment Required

    {
        "error": "Account has no subscription or subscription expired",
        "code": 402
    }
    
  • 412 Insufficient credits

    {
        "error": "Not enough credits: requested 3, available 0",
        "code": 412
    }
    
  • 429 Too Many Requests

    Wait in a loop for at least 10..30 seconds and retry again.

    There are two possible cases for API response 429.

    1. API query is full and can not accept new faceswap/picsi requests.
      {
       "error": "Unable to lock Discord after <attempts> attempts",
       "code": 429
      }
      
    2. The API received an HTTP status 429 from the Discord API when it attempted to POST to the /interactions endpoint. Under normal circumstances, this should be a rare occurrence because the API is designed to strictly adhere to Discord rate limits. However, in certain scenarios, Discord may still issue a 429 response.
      {
       "error": "Discord /interactions failed with HTTP status 429",
       "errorDetails": "{\"global\":true,\"message\":\"You are being rate limited.\",\"retry_after\":10}",
       "code": 429
      }
      
Model
{ // TypeScript, all fields are optional
  jobid: string, 
  verb: 'faceswap-picsi',
  status: 'started' | 'completed' | 'failed',
  options: string,
  source_image: { size: number, type: string },
  target_image_gif_or_video: { size: number, type: string },
  created: string, // YYYY-MM-DDTHH:mm:ss.sssZ, IS0 8601, UTC
  updated: string, // YYYY-MM-DDTHH:mm:ss.sssZ, IS0 8601, UTC
  discord: string, // Provided for debugging purposes only, contains the first 3 and the last 3 characters of the original value
  server: string,
  channel: string,
  replyUrl: string,
  replyRef: string,
  messageId: string,
  content: string, // Contains message generated by InsightFaceSwap 
  attachments: [
      {
          id: string,
          content_type: string,
          filename: string,
          url: string,
          proxy_url: string,
          size: number,
          width: number,
          height: number
      }
  ],  
  timestamp: string,
  error: string,
  errorDetails: string,
  code: number
}
Examples
  • curl -H "Accept: application/json" \
         -H "Authorization: Bearer …" \
         -X POST https://api.useapi.net/v1/faceswap/picsi \
         -F "options=<options>" \ 
         -F 'source_image=@"<Path to the source_image>"' \
         -F 'target_image_gif_or_video=@"<Path to the target_image_gif_or_video>"' 
    
  • const main = async () => {
        const apiUrl = "https://api.useapi.net/v1/faceswap/picsi";
        const token = "API token";
        const options = "options";
        const channel = "Discord channel";
        const data = {
            method: 'POST',
            headers: {
                'Authorization': `Bearer ${token}`
            }
        };
        const formData = new FormData();
        formData.append("options", options);
        formData.append("channel", channel);
    
        /*
            // Example 1: Fetch image from URL
            const imageUrl = "https://upload.wikimedia.org/wikipedia/commons/7/7d/Mona_Lisa_color_restoration.jpg";
            const responseImage = await fetch(imageUrl);
            formData.append("source_image", await responseImage.blob());
        */
        /* 
            // Example 2: Load image from local file (Blob)
            const fsp = require('fs').promises;
            const imageFileName = "./target_photo.png";
            const blob = new Blob([await fsp.readFile(imageFileName)]);
            formData.append("target_image_gif_or_video", blob);
        */
        /*
            // Example 3: Load from input file html element
            // <input id="target-photo-image-file" type="file"> 
            const imageFile = document.getElementById(`target-photo-image-file`);
            if (imageFile.files[0])
                formData.append("target_image_gif_or_video", imageFile.files[0]);
        */
    
        data.body = formData;
        const response = await fetch(apiUrl, data);
        const result = await response.json();
        console.log("response", { response, result });
    };
    main()
    
    
  • import requests
    
    api_url = "https://api.useapi.net/v1/faceswap/picsi"
    token = "API token"
    options = "options"
    channel = "Discord channel"
    
    headers = {
        'Authorization': f'Bearer {token}'
    }
    
    files = {
        'options': (None, options),
        'channel': (None, channel)
    }
    
    # # Example 1: Fetch image from URL
    # image_url = "https://upload.wikimedia.org/wikipedia/commons/7/7d/Mona_Lisa_color_restoration.jpg"
    # response_image = requests.get(image_url)
    # image_content = response_image.content
    # files['source_image'] = ('image.jpg', image_content, 'image/jpeg')
    
    # # Example 2: Load image from local file
    # image_file_path = "./target_photo.png"
    # with open(image_file_path, 'rb') as image_file:
    #     files['target_image_gif_or_video'] = ('target_photo.png', image_file.read(), 'image/png')
    
    response = requests.post(api_url, headers=headers, files=files)
    print(response, response.json())
    
Try It