HD Makeup Transfer

Description

Applies makeup from a reference image to a user image. The API supports adjustments to the overall transfer strength, skin brightening, blush, eyeshadow, eyebrows, colored contact lenses, lip color, and highlight/contour effects. It also supports reference image validation and preprocessing, and can return a single result image, a combined comparison image, or results at different makeup intensities.

Version

1.0

Image Requirements

  • Provide image URLs or Base64-encoded image data.
  • For standard makeup transfer, provide two images in order: the user image first, followed by the reference image supplying the makeup style.
  • When ref_judgment=1, provide only the reference image.
  • When input_ref_type=1, the reference image must already be preprocessed to 640 × 640.

Request URL

    Production environment: https://openapi.meitu.com
    Task submission endpoint: https://openapi.meitu.com/api/v1/sdk/sync/push
    Task name (task): /v1/AIMakeup/494490
    Task type (task_type): formula

HTTP Method

POST

Content-Type: application/json

Authentication

Obtain an AccessKey and SecretKey before use, and sign requests according to Open Platform API Signature.

Request Parameters

RequiredParameterTypeDescription
YesparamsstringMakeup processing parameters encoded as a JSON string
Yesinit_imagesobject[]Input images. For standard makeup transfer, provide the user image first and the reference image second. When ref_judgment is 1, provide only the reference image
YestaskstringFixed value: /v1/AIMakeup/494490
Yestask_typestringFixed value: formula
Nosync_timeoutintDefault: 30 seconds; -1 means do not wait. If the synchronous wait times out, status 9 is returned. Retrieve the result through the query API

Structure of each init_images item:

RequiredParameterTypeDescription
YesurlstringImage URL or Base64-encoded image data
YesprofileobjectImage metadata

Structure of profile:

RequiredParameterTypeDescription
Yesmedia_profilesobjectMedia metadata
Nomedia_extraobjectAdditional image information, such as facial landmarks or facial feature attributes
YesversionstringFixed value: v1

Structure of media_profiles:

RequiredParameterTypeDescription
Yesmedia_data_typestringurl indicates an image URL; jpg indicates Base64-encoded JPG data

params is a JSON string with the following structure:

RequiredFieldTypeDescription
Norsp_media_typestringDefault: url; url returns result images as URLs, and jpg returns Base64-encoded result images
YesparameterobjectMakeup algorithm parameters

parameter fields:

RequiredParameterTypeDescription
Noref_judgmentintProcessing mode: 0 standard makeup transfer using a user image and a reference image; 1 validate the reference image for makeup transfer and return a preprocessed 640 × 640 reference image; 2 reference image processing for real-time makeup transfer; 3 processing for real-time makeup transfer scheme 2
Noblend_valueintOverall blending factor. Range: 0–100; default: 100
Nomakeup_res_typeintOutput layout: 0 return only the makeup transfer result; 1 return one combined image containing the processed user image, reference image, and result; 3 return three result images at low, medium, and high makeup intensities; default: 1
Noinput_ref_typeintReference image type: 0 unprocessed image; 1 image already preprocessed to 640 × 640; default: 0
Yesbeauty_flagintUser image beautification preprocessing mode. Must be 0
Noface_color_alphaintSkin brightening level. Range: 0–100; default: 40
Noblusher_alphaintBlush opacity. Range: 0–100; default: 30
Noeyeshadow_alphaintEyeshadow opacity. Range: 0–100; default: 85
Noeyebrow_alphaintEyebrow opacity. Range: 0–100; default: 45
Nopupil_alphaintColored contact lens opacity. Range: 0–100; default: 55
Nolip_alphaintLip color opacity. Range: 0–100; default: 100
Nohl_alphaintHighlight/contour opacity. Range: 0–100; default: 45
Nohightpass_radiusintClarity level. Range: 0–100; default: 0
Noerror_code_modeintError code mode: 0 shared codes for user and reference images; 1 separate codes for user and reference images; default: 0

Request Example

This example submits a user image and a reference image for standard makeup transfer and returns the result image URL. params must be a JSON string.

{
  "task": "/v1/AIMakeup/494490",
  "task_type": "formula",
  "init_images": [
    {
      "url": "https://example.com/user.jpg",
      "profile": {
        "media_profiles": {
          "media_data_type": "url"
        },
        "version": "v1"
      }
    },
    {
      "url": "https://example.com/reference.jpg",
      "profile": {
        "media_profiles": {
          "media_data_type": "url"
        },
        "version": "v1"
      }
    }
  ],
  "params": "{\"rsp_media_type\":\"url\",\"parameter\":{\"ref_judgment\":0,\"makeup_res_type\":0,\"input_ref_type\":0,\"beauty_flag\":0,\"blend_value\":100,\"face_color_alpha\":40,\"blusher_alpha\":70,\"eyeshadow_alpha\":80,\"eyebrow_alpha\":55,\"pupil_alpha\":70,\"lip_alpha\":90,\"hl_alpha\":60,\"hightpass_radius\":0,\"error_code_mode\":0}}",
  "sync_timeout": 30
}

Response Fields

Note: Generated result images are periodically deleted. Download and save them promptly.
FieldTypeDescription
request_idstringRequest identifier
trace_idstringTrace identifier
codeintBusiness status code; 0 indicates that the request was accepted successfully
error_codeintError code; 0 on success
messagestringBusiness status message
tipsanyAdditional information; may be null
dataobjectTask status and algorithm result

data fields:

FieldTypeDescription
statusintTask status: -1 not found; 0 created; 1 processing; 2 failed; 9 timed out and must be retrieved through the query API; 10 succeeded
resultobjectAlgorithm result
progressnumberTask progress, for example 0.1, 0.85, or 1
predict_elapsedintEstimated processing time in milliseconds
create_timeint64Creation timestamp in milliseconds
task_idstringTask ID
custom_task_idstringClient-defined task ID
trace_idstringTrace identifier
client_infostringClient information
init_imagesobject[]/nullInput media echoed by the service

result fields:

FieldTypeDescription
idstringTask ID
urlsstring[]List of result image URLs

A data.status value of 10 indicates completion. Retrieve output images from data.result.urls. When data.status is 9, query the task using the returned task_id.

Response Examples

Success Response Example

{
  "request_id": "req_1234567890",
  "trace_id": "trace_1234567890",
  "code": 0,
  "error_code": 0,
  "message": "success",
  "tips": null,
  "data": {
    "status": 10,
    "result": {
      "id": "task_1234567890",
      "urls": [
        "https://example.com/makeup_result.jpg"
      ]
    },
    "progress": 1,
    "predict_elapsed": 0,
    "create_time": 1789002000000,
    "task_id": "task_1234567890",
    "custom_task_id": "",
    "trace_id": "trace_1234567890",
    "client_info": "",
    "init_images": null
  }
}

Query Required Response Example

When status is 9, pass the returned task_id to the query API to retrieve the result.

{
  "request_id": "req_1234567890",
  "trace_id": "trace_1234567890",
  "code": 0,
  "error_code": 0,
  "message": "success",
  "tips": null,
  "data": {
    "status": 9,
    "result": {
      "id": "task_1234567890"
    },
    "progress": 0,
    "predict_elapsed": 10000,
    "create_time": 1789002000000,
    "task_id": "task_1234567890",
    "custom_task_id": "",
    "trace_id": "trace_1234567890",
    "client_info": "",
    "init_images": null
  }
}

Error Response Example

{
  "request_id": "req_1234567890",
  "trace_id": "trace_1234567890",
  "code": 20001,
  "error_code": 20001,
  "message": "PROCESS_ERROR",
  "tips": null,
  "data": {
    "status": 2,
    "result": {
      "id": "task_1234567890"
    },
    "progress": 0,
    "predict_elapsed": 0,
    "create_time": 1789002000000,
    "task_id": "task_1234567890",
    "custom_task_id": "",
    "trace_id": "trace_1234567890",
    "client_info": "",
    "init_images": null
  }
}

API-Specific Error Codes

error_code_mode = 0

ErrorCodeMessageDescription
20001PROCESS_ERRORProcessing failed
22001MTAIMKTF_ERRO_TYPE_INPUTInvalid input image
22003MTAIMKTF_ERRO_TYPE_FACE_SIDEThe face is too small or turned too far to the side
22004MTAIMKTF_ERRO_TYPE_FACE_BLACKThe face is too dark
22005MTAIMKTF_ERRO_TYPE_FACE_YINGYANGExcessive lighting contrast between the two sides of the face
22006MTAIMKTF_ERRO_TYPE_FACE_BRIGHTThe face is too bright
22007MTAIMKTF_ERRO_TYPE_FACE_COLOR_SHIFTThe face has a color cast
22008MTAIMKTF_ERRO_TYPE_FACE_EYE_CLOSEEye-open/closed states do not match between the user and reference images

error_code_mode = 1

ErrorCodeMessageDescription
20001PROCESS_ERRORProcessing failed
22001MTAIMKTF_ERRO_TYPE_INPUTInvalid input image
23003MTAIMKTF_ERRO_TYPE_FACE_SIDE_SRCThe face in the user image is too small or turned too far to the side
23004MTAIMKTF_ERRO_TYPE_FACE_BLACK_SRCThe face in the user image is too dark
23005MTAIMKTF_ERRO_TYPE_FACE_YINGYANG_SRCExcessive lighting contrast between the two sides of the face in the user image
23006MTAIMKTF_ERRO_TYPE_FACE_BRIGHT_SRCThe face in the user image is too bright
23007MTAIMKTF_ERRO_TYPE_FACE_COLOR_SHIFT_SRCThe face in the user image has a color cast
23008MTAIMKTF_ERRO_TYPE_FACE_EYE_CLOSE_SRCEye-open/closed states do not match between the user and reference images
22003MTAIMKTF_ERRO_TYPE_FACE_SIDE_REFThe face in the reference image is too small or turned too far to the side
22004MTAIMKTF_ERRO_TYPE_FACE_BLACK_REFThe face in the reference image is too dark
22005MTAIMKTF_ERRO_TYPE_FACE_YINGYANG_REFExcessive lighting contrast between the two sides of the face in the reference image
22006MTAIMKTF_ERRO_TYPE_FACE_BRIGHT_REFThe face in the reference image is too bright
22007MTAIMKTF_ERRO_TYPE_FACE_COLOR_SHIFT_REFThe face in the reference image has a color cast
22008MTAIMKTF_ERRO_TYPE_FACE_EYE_CLOSE_SRCEye-open/closed states do not match between the user and reference images

Common Error Codes

See API Error Codes.

SDK Examples

The examples construct the complete request body, sign it with the corresponding SDK, and send the signed request. Replace the sample AK, SK, and image URLs with actual values.

Python

Use the Python signing SDK and install requests.

import json

import requests
from sign_sdk import sign

def api_call_example():
    key = "your_access_key"
    secret = "your_secret_key"
    url = "https://openapi.meitu.com/api/v1/sdk/sync/push"
    method = "POST"
    headers = {
        "Content-Type": "application/json",
        sign.HeaderHost: "openapi.meitu.com",
    }

    inner_params = {
        "rsp_media_type": "url",
        "parameter": {
            "ref_judgment": 0,
            "makeup_res_type": 0,
            "input_ref_type": 0,
            "beauty_flag": 0,
            "blend_value": 100,
            "face_color_alpha": 40,
            "blusher_alpha": 70,
            "eyeshadow_alpha": 80,
            "eyebrow_alpha": 55,
            "pupil_alpha": 70,
            "lip_alpha": 90,
            "hl_alpha": 60,
            "hightpass_radius": 0,
            "error_code_mode": 0
        }
    }
    payload = {
        "task": "/v1/AIMakeup/494490",
        "task_type": "formula",
        "init_images": [
            {
                "url": "https://example.com/user.jpg",
                "profile": {
                    "media_profiles": {
                        "media_data_type": "url"
                    },
                    "version": "v1"
                }
            },
            {
                "url": "https://example.com/reference.jpg",
                "profile": {
                    "media_profiles": {
                        "media_data_type": "url"
                    },
                    "version": "v1"
                }
            }
        ],
        "params": json.dumps(inner_params, ensure_ascii=False),
        "sync_timeout": 30
    }
    body = json.dumps(payload, ensure_ascii=False)

    signer = sign.Signer(key, secret)
    signed_request = signer.sign(url, method, headers, body)
    with requests.Session() as session:
        response = session.send(signed_request, timeout=60)
        print("Status:", response.status_code)
        print("Response:", response.text)

if __name__ == "__main__":
    api_call_example()

Go

Use the Go signing SDK.

package main

import (
	"fmt"
	"io"
	"net/http"
	"time"

	"github.com/mtlab/api/signer"
)

func main() {
	key := "your_access_key"
	secret := "your_secret_key"
	signObj := signer.NewSigner(key, secret)
	url := "https://openapi.meitu.com/api/v1/sdk/sync/push"
	headers := make(http.Header)
	headers.Set(signer.HeaderHost, "openapi.meitu.com")
	headers.Set("Content-Type", "application/json")

	body := `{
  "task": "/v1/AIMakeup/494490",
  "task_type": "formula",
  "init_images": [
    {
      "url": "https://example.com/user.jpg",
      "profile": {
        "media_profiles": {
          "media_data_type": "url"
        },
        "version": "v1"
      }
    },
    {
      "url": "https://example.com/reference.jpg",
      "profile": {
        "media_profiles": {
          "media_data_type": "url"
        },
        "version": "v1"
      }
    }
  ],
  "params": "{\"rsp_media_type\":\"url\",\"parameter\":{\"ref_judgment\":0,\"makeup_res_type\":0,\"input_ref_type\":0,\"beauty_flag\":0,\"blend_value\":100,\"face_color_alpha\":40,\"blusher_alpha\":70,\"eyeshadow_alpha\":80,\"eyebrow_alpha\":55,\"pupil_alpha\":70,\"lip_alpha\":90,\"hl_alpha\":60,\"hightpass_radius\":0,\"error_code_mode\":0}}",
  "sync_timeout": 30
}`

	req, err := signObj.Sign(url, http.MethodPost, headers, body)
	if err != nil {
		fmt.Println("Failed to sign request:", err)
		return
	}
	client := &http.Client{Timeout: 60 * time.Second}
	resp, err := client.Do(req)
	if err != nil {
		fmt.Println("Failed to send request:", err)
		return
	}
	defer resp.Body.Close()

	responseBody, err := io.ReadAll(resp.Body)
	if err != nil {
		fmt.Println("Failed to read response:", err)
		return
	}
	fmt.Println("Status:", resp.StatusCode)
	fmt.Println("Response:", string(responseBody))
}

PHP

Use the PHP signing SDK and place signer.php in the same directory as the example.

<?php
require_once __DIR__ . '/signer.php';

$key = 'your_access_key';
$secret = 'your_secret_key';
$url = 'https://openapi.meitu.com/api/v1/sdk/sync/push';
$headers = [
    'Content-Type' => 'application/json',
    'Host' => 'openapi.meitu.com',
];

$innerParams = json_encode([
    'rsp_media_type' => 'url',
    'parameter' => [
        'ref_judgment' => 0,
        'makeup_res_type' => 0,
        'input_ref_type' => 0,
        'beauty_flag' => 0,
        'blend_value' => 100,
        'face_color_alpha' => 40,
        'blusher_alpha' => 70,
        'eyeshadow_alpha' => 80,
        'eyebrow_alpha' => 55,
        'pupil_alpha' => 70,
        'lip_alpha' => 90,
        'hl_alpha' => 60,
        'hightpass_radius' => 0,
        'error_code_mode' => 0,
    ],
], JSON_UNESCAPED_SLASHES);
$body = json_encode([
    'task' => '/v1/AIMakeup/494490',
    'task_type' => 'formula',
    'init_images' => [
        [
            'url' => 'https://example.com/user.jpg',
            'profile' => [
                'media_profiles' => [
                    'media_data_type' => 'url',
                ],
                'version' => 'v1',
            ],
        ],
        [
            'url' => 'https://example.com/reference.jpg',
            'profile' => [
                'media_profiles' => [
                    'media_data_type' => 'url',
                ],
                'version' => 'v1',
            ],
        ],
    ],
    'params' => $innerParams,
    'sync_timeout' => 30,
], JSON_UNESCAPED_SLASHES);

$signer = new Signer($key, $secret);
$curl = $signer->sign($url, 'POST', $headers, $body);
curl_setopt($curl, CURLOPT_HEADER, false);
curl_setopt($curl, CURLOPT_TIMEOUT, 60);

$response = curl_exec($curl);
if ($response === false) {
    echo 'Error: ' . curl_error($curl);
} else {
    echo 'Status: ' . curl_getinfo($curl, CURLINFO_HTTP_CODE) . PHP_EOL;
    echo 'Response: ' . $response . PHP_EOL;
}
curl_close($curl);

Java

Use the Java signing SDK and save the example as Main.java.

import com.meitu.openai.common.Signer;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

public class Main {
    public static void main(String[] args) throws Exception {
        Signer signer = new Signer("your_access_key", "your_secret_key");
        String url = "https://openapi.meitu.com/api/v1/sdk/sync/push";
        String method = "POST";
        Map<String, String> headers = new HashMap<>();
        headers.put("Content-Type", "application/json");
        headers.put(Signer.HeaderHost, "openapi.meitu.com");

        String body = "{\n" +
                "  \"task\": \"/v1/AIMakeup/494490\",\n" +
                "  \"task_type\": \"formula\",\n" +
                "  \"init_images\": [\n" +
                "    {\n" +
                "      \"url\": \"https://example.com/user.jpg\",\n" +
                "      \"profile\": {\n" +
                "        \"media_profiles\": {\n" +
                "          \"media_data_type\": \"url\"\n" +
                "        },\n" +
                "        \"version\": \"v1\"\n" +
                "      }\n" +
                "    },\n" +
                "    {\n" +
                "      \"url\": \"https://example.com/reference.jpg\",\n" +
                "      \"profile\": {\n" +
                "        \"media_profiles\": {\n" +
                "          \"media_data_type\": \"url\"\n" +
                "        },\n" +
                "        \"version\": \"v1\"\n" +
                "      }\n" +
                "    }\n" +
                "  ],\n" +
                "  \"params\": \"{\\\"rsp_media_type\\\":\\\"url\\\",\\\"parameter\\\":{\\\"ref_judgment\\\":0,\\\"makeup_res_type\\\":0,\\\"input_ref_type\\\":0,\\\"beauty_flag\\\":0,\\\"blend_value\\\":100,\\\"face_color_alpha\\\":40,\\\"blusher_alpha\\\":70,\\\"eyeshadow_alpha\\\":80,\\\"eyebrow_alpha\\\":55,\\\"pupil_alpha\\\":70,\\\"lip_alpha\\\":90,\\\"hl_alpha\\\":60,\\\"hightpass_radius\\\":0,\\\"error_code_mode\\\":0}}\",\n" +
                "  \"sync_timeout\": 30\n" +
                "}";

        Map<String, String> signedHeaders = signer.sign(url, method, headers, body);
        HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
        try {
            connection.setRequestMethod(method);
            connection.setConnectTimeout(10000);
            connection.setReadTimeout(60000);
            connection.setInstanceFollowRedirects(false);
            for (Map.Entry<String, String> header : signedHeaders.entrySet()) {
                connection.setRequestProperty(header.getKey(), header.getValue());
            }
            connection.setDoOutput(true);
            try (OutputStream output = connection.getOutputStream()) {
                output.write(body.getBytes(StandardCharsets.UTF_8));
            }

            int status = connection.getResponseCode();
            InputStream stream = status >= 400
                    ? connection.getErrorStream()
                    : connection.getInputStream();
            System.out.println("Status: " + status);
            if (stream != null) {
                try (InputStream input = stream;
                     ByteArrayOutputStream output = new ByteArrayOutputStream()) {
                    byte[] buffer = new byte[4096];
                    int length;
                    while ((length = input.read(buffer)) != -1) {
                        output.write(buffer, 0, length);
                    }
                    System.out.println("Response: " + output.toString("UTF-8"));
                }
            }
        } finally {
            connection.disconnect();
        }
    }
}