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 to640 × 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): formulaHTTP 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
| Required | Parameter | Type | Description |
|---|---|---|---|
| Yes | params | string | Makeup processing parameters encoded as a JSON string |
| Yes | init_images | object[] | 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 |
| Yes | task | string | Fixed value: /v1/AIMakeup/494490 |
| Yes | task_type | string | Fixed value: formula |
| No | sync_timeout | int | Default: 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:
| Required | Parameter | Type | Description |
|---|---|---|---|
| Yes | url | string | Image URL or Base64-encoded image data |
| Yes | profile | object | Image metadata |
Structure of profile:
| Required | Parameter | Type | Description |
|---|---|---|---|
| Yes | media_profiles | object | Media metadata |
| No | media_extra | object | Additional image information, such as facial landmarks or facial feature attributes |
| Yes | version | string | Fixed value: v1 |
Structure of media_profiles:
| Required | Parameter | Type | Description |
|---|---|---|---|
| Yes | media_data_type | string | url indicates an image URL; jpg indicates Base64-encoded JPG data |
params is a JSON string with the following structure:
| Required | Field | Type | Description |
|---|---|---|---|
| No | rsp_media_type | string | Default: url; url returns result images as URLs, and jpg returns Base64-encoded result images |
| Yes | parameter | object | Makeup algorithm parameters |
parameter fields:
| Required | Parameter | Type | Description |
|---|---|---|---|
| No | ref_judgment | int | Processing 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 |
| No | blend_value | int | Overall blending factor. Range: 0–100; default: 100 |
| No | makeup_res_type | int | Output 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 |
| No | input_ref_type | int | Reference image type: 0 unprocessed image; 1 image already preprocessed to 640 × 640; default: 0 |
| Yes | beauty_flag | int | User image beautification preprocessing mode. Must be 0 |
| No | face_color_alpha | int | Skin brightening level. Range: 0–100; default: 40 |
| No | blusher_alpha | int | Blush opacity. Range: 0–100; default: 30 |
| No | eyeshadow_alpha | int | Eyeshadow opacity. Range: 0–100; default: 85 |
| No | eyebrow_alpha | int | Eyebrow opacity. Range: 0–100; default: 45 |
| No | pupil_alpha | int | Colored contact lens opacity. Range: 0–100; default: 55 |
| No | lip_alpha | int | Lip color opacity. Range: 0–100; default: 100 |
| No | hl_alpha | int | Highlight/contour opacity. Range: 0–100; default: 45 |
| No | hightpass_radius | int | Clarity level. Range: 0–100; default: 0 |
| No | error_code_mode | int | Error 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.| Field | Type | Description |
|---|---|---|
| request_id | string | Request identifier |
| trace_id | string | Trace identifier |
| code | int | Business status code; 0 indicates that the request was accepted successfully |
| error_code | int | Error code; 0 on success |
| message | string | Business status message |
| tips | any | Additional information; may be null |
| data | object | Task status and algorithm result |
data fields:
| Field | Type | Description |
|---|---|---|
| status | int | Task status: -1 not found; 0 created; 1 processing; 2 failed; 9 timed out and must be retrieved through the query API; 10 succeeded |
| result | object | Algorithm result |
| progress | number | Task progress, for example 0.1, 0.85, or 1 |
| predict_elapsed | int | Estimated processing time in milliseconds |
| create_time | int64 | Creation timestamp in milliseconds |
| task_id | string | Task ID |
| custom_task_id | string | Client-defined task ID |
| trace_id | string | Trace identifier |
| client_info | string | Client information |
| init_images | object[]/null | Input media echoed by the service |
result fields:
| Field | Type | Description |
|---|---|---|
| id | string | Task ID |
| urls | string[] | 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
| ErrorCode | Message | Description |
|---|---|---|
20001 | PROCESS_ERROR | Processing failed |
22001 | MTAIMKTF_ERRO_TYPE_INPUT | Invalid input image |
22003 | MTAIMKTF_ERRO_TYPE_FACE_SIDE | The face is too small or turned too far to the side |
22004 | MTAIMKTF_ERRO_TYPE_FACE_BLACK | The face is too dark |
22005 | MTAIMKTF_ERRO_TYPE_FACE_YINGYANG | Excessive lighting contrast between the two sides of the face |
22006 | MTAIMKTF_ERRO_TYPE_FACE_BRIGHT | The face is too bright |
22007 | MTAIMKTF_ERRO_TYPE_FACE_COLOR_SHIFT | The face has a color cast |
22008 | MTAIMKTF_ERRO_TYPE_FACE_EYE_CLOSE | Eye-open/closed states do not match between the user and reference images |
error_code_mode = 1
| ErrorCode | Message | Description |
|---|---|---|
20001 | PROCESS_ERROR | Processing failed |
22001 | MTAIMKTF_ERRO_TYPE_INPUT | Invalid input image |
23003 | MTAIMKTF_ERRO_TYPE_FACE_SIDE_SRC | The face in the user image is too small or turned too far to the side |
23004 | MTAIMKTF_ERRO_TYPE_FACE_BLACK_SRC | The face in the user image is too dark |
23005 | MTAIMKTF_ERRO_TYPE_FACE_YINGYANG_SRC | Excessive lighting contrast between the two sides of the face in the user image |
23006 | MTAIMKTF_ERRO_TYPE_FACE_BRIGHT_SRC | The face in the user image is too bright |
23007 | MTAIMKTF_ERRO_TYPE_FACE_COLOR_SHIFT_SRC | The face in the user image has a color cast |
23008 | MTAIMKTF_ERRO_TYPE_FACE_EYE_CLOSE_SRC | Eye-open/closed states do not match between the user and reference images |
22003 | MTAIMKTF_ERRO_TYPE_FACE_SIDE_REF | The face in the reference image is too small or turned too far to the side |
22004 | MTAIMKTF_ERRO_TYPE_FACE_BLACK_REF | The face in the reference image is too dark |
22005 | MTAIMKTF_ERRO_TYPE_FACE_YINGYANG_REF | Excessive lighting contrast between the two sides of the face in the reference image |
22006 | MTAIMKTF_ERRO_TYPE_FACE_BRIGHT_REF | The face in the reference image is too bright |
22007 | MTAIMKTF_ERRO_TYPE_FACE_COLOR_SHIFT_REF | The face in the reference image has a color cast |
22008 | MTAIMKTF_ERRO_TYPE_FACE_EYE_CLOSE_SRC | Eye-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();
}
}
}