Whiteboard Drawing v3
Description
Generates an image in a specified style from an input sketch. You can specify the sketch background type, generation style, canvas expansion, and output dimensions.
Version
1.0
Image Requirements
Supports JPG and PNG. Supply the image as a URL or Base64-encoded data.
Request URL
- Production host: `https://openapi.meitu.com`
- Task submission endpoint: `https://openapi.meitu.com/api/v1/sdk/sync/push`
- Task name (`task`): `/v1/AI_Drawing_White_V3/426943`
- Task type (`task_type`): `formula`HTTP Method
POST
Content-Type: application/json
Authentication
Sign requests with an Access Key (AK) and Secret Key (SK). See API Request Signing.
Credits cannot be used to pay for API calls. Please visit the MV console to activate this API and purchase or manage resource packages.
Request Parameters
| Required | Parameter | Type | Description |
|---|---|---|---|
| Yes | task | string | Fixed value: /v1/AI_Drawing_White_V3/426943. |
| Yes | task_type | string | Fixed value: formula. |
| Yes | init_images | object[] | Input sketch image list. |
| Yes | params | string | Algorithm parameters serialized as a JSON string. Decoded fields are described below. |
| No | sync_timeout | int | Synchronous wait timeout in seconds. Default: 30. Query the task for results after the wait expires. |
init_images Item
| Required | Parameter | Type | Description |
|---|---|---|---|
| Yes | url | string | Image URL or Base64-encoded data. Do not Base64-encode a URL. |
| Yes | profile | object | Image properties. |
profile
| Required | Parameter | Type | Description |
|---|---|---|---|
| Yes | media_profiles | object | Image transmission information. |
| Yes | version | string | Fixed value: v1. |
| No | media_extra | object | Additional image information. Use {} when no additional information is needed. |
media_profiles
| Required | Parameter | Type | Description |
|---|---|---|---|
| Yes | media_data_type | string | url for an image URL; jpg for Base64-encoded data. Set it explicitly for the input type; the algorithm default is jpg. |
params
The following fields belong directly to the object decoded from params. Serialize this object first, then assign the resulting string to the request's params field.
| Required | Parameter | Type | Description |
|---|---|---|---|
| Yes | scribble_bg_type | int | Sketch background type: 0 for white, 1 for black. The algorithm defaults to black; provide the value explicitly. |
| Yes | scribble_style_type | string | Generation style identifier. Contact your account representative for available values; replace the placeholder YOUR_STYLE_ID. |
| No | padding_type | int | Canvas expansion: 0 to leave unchanged, 1 to expand. Default: 0. |
| No | height | int | Output height in pixels. Range: [100, 2048]; recommended: 1024. Takes precedence over the input image height. |
| No | width | int | Output width in pixels. Range: [100, 2048]; recommended: 1024. Takes precedence over the input image width. |
Request Example
The example uses a sketch with a white background, no canvas expansion, and a 1024 × 1024 output. Replace the image URL and YOUR_STYLE_ID before calling the API.
{
"task": "/v1/AI_Drawing_White_V3/426943",
"task_type": "formula",
"init_images": [
{
"url": "https://example.com/input.png",
"profile": {
"media_profiles": {
"media_data_type": "url"
},
"version": "v1"
}
}
],
"params": "{\"scribble_bg_type\":0,\"scribble_style_type\":\"YOUR_STYLE_ID\",\"padding_type\":0,\"height\":1024,\"width\":1024}",
"sync_timeout": 30
}Response Fields
Generated results are cleaned up periodically. Download and save them promptly.On success, read output image URLs from data.result.urls. A successful HTTP response does not necessarily mean the task has completed; also check data.status.
Successful Response Fields
| Field | Type | Description |
|---|---|---|
| error_code | int | Error code; 0 indicates normal request processing. |
| message | string | Response message. |
| data | object | Task status, progress, and result. |
data
| Field | Type | Description |
|---|---|---|
| status | int | Task status: -1 not found; 0 created; 1 running; 2 failed; 9 synchronous wait expired, query required; 10 succeeded. |
| result | object | Task identifier and result. |
| progress | number | Task progress, for example 0.1, 0.85, or 1. |
result
| Field | Type | Description |
|---|---|---|
| id | string | Gateway task ID. Pass it as task_id when querying the task. |
| urls | string[] | Output image URLs available when the task succeeds. |
Failed Response Fields
| Field | Type | Description |
|---|---|---|
| ErrorCode | int | Error code. |
| ErrorMsg | string | Error message. |
| Data | string/null | Error details; null in the example below. |
Failure field names are case-sensitive. Preserve ErrorCode, ErrorMsg, and Data exactly as shown.
Response Examples
Successful Response
Response Status: 200
Content-Type: application/json; charset=utf-8
{
"error_code": 0,
"message": "success",
"data": {
"status": 10,
"result": {
"id": "example-task-id",
"urls": [
"https://example.com/result.jpeg"
]
},
"progress": 1
}
}When a Query Is Required
When data.status = 9, the synchronous wait has expired; this does not mean the task failed. Use the task ID with the Task Query API to retrieve the result.
The documented task ID field for this API is data.result.id. Query status 0 or 1 means the task is not yet complete; 10 means success and 2 means failure.
Failed Response
Response Status: 400
Content-Type: application/json; charset=utf-8
{
"ErrorCode": 20001,
"ErrorMsg": "PROCESS_ERROR",
"Data": null
}API-Specific Error Codes
| Code | Message | Description |
|---|---|---|
| 20001 | PROCESS_ERROR | Processing error. |
| 20014 | NOT_FOUND | Image not found. |
| 20008 | UNSUITABLE_IMAGE | Image does not meet the requirements. |
| 20026 | NO_SUCH_MODE | Specified mode does not exist. |
| 20034 | NO_SUCH_STYLE | Specified style does not exist. |
| 21008 | BACKGROUND_IMAGE_LOSS | Background image is missing. |
| 20025 | INIT_FAIL | Initialization failed. |
| 21021 | MASK_LOSS | Mask is missing. |
| 21022 | SKETCH_LOSS | Sketch is missing. |
Common Error Codes and Messages
See API Error Codes.
SDK Examples
All examples use the request parameters above. Replace AK, SK, the image URL, and YOUR_STYLE_ID, and install or include the signing SDK following the guide for your language.
The examples print the response. If the task is not complete, retrieve results with the Task Query API.
Python
import json
import requests
from sign_sdk import sign
def main():
key = "YOUR_ACCESS_KEY"
secret = "YOUR_SECRET_KEY"
url = "https://openapi.meitu.com/api/v1/sdk/sync/push"
params = {
"scribble_bg_type": 0,
"scribble_style_type": "YOUR_STYLE_ID",
"padding_type": 0,
"height": 1024,
"width": 1024
}
payload = {
"task": "/v1/AI_Drawing_White_V3/426943",
"task_type": "formula",
"init_images": [{
"url": "https://example.com/input.png",
"profile": {
"media_profiles": {"media_data_type": "url"},
"version": "v1",
},
}],
"params": json.dumps(params, ensure_ascii=True),
"sync_timeout": 30,
}
body = json.dumps(payload, ensure_ascii=True)
headers = {
"Content-Type": "application/json",
sign.HeaderHost: "openapi.meitu.com",
}
signer = sign.Signer(key, secret)
signed_request = signer.sign(url, "POST", headers, body)
with requests.Session() as session:
response = session.send(
signed_request, timeout=(10, 60), verify=True, allow_redirects=False
)
print("Status:", response.status_code)
print("Response:", response.text)
if __name__ == "__main__":
main()Go
package main
import (
"fmt"
"io"
"net/http"
"time"
"github.com/mtlab/api/signer"
)
func main() {
url := "https://openapi.meitu.com/api/v1/sdk/sync/push"
body := `{
"task": "/v1/AI_Drawing_White_V3/426943",
"task_type": "formula",
"init_images": [
{
"url": "https://example.com/input.png",
"profile": {
"media_profiles": {
"media_data_type": "url"
},
"version": "v1"
}
}
],
"params": "{\"scribble_bg_type\":0,\"scribble_style_type\":\"YOUR_STYLE_ID\",\"padding_type\":0,\"height\":1024,\"width\":1024}",
"sync_timeout": 30
}`
headers := make(http.Header)
headers.Set("Content-Type", "application/json")
headers.Set(signer.HeaderHost, "openapi.meitu.com")
signObj := signer.NewSigner("YOUR_ACCESS_KEY", "YOUR_SECRET_KEY")
req, err := signObj.Sign(url, http.MethodPost, headers, body)
if err != nil {
fmt.Println("Sign request failed:", err)
return
}
client := &http.Client{
Timeout: 60 * time.Second,
CheckRedirect: func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
},
}
resp, err := client.Do(req)
if err != nil {
fmt.Println("Send request failed:", err)
return
}
defer resp.Body.Close()
responseBody, err := io.ReadAll(resp.Body)
if err != nil {
fmt.Println("Read response failed:", err)
return
}
fmt.Println("Status:", resp.StatusCode)
fmt.Println("Response:", string(responseBody))
}PHP
<?php
require_once __DIR__ . '/signer.php';
$params = json_encode([
'scribble_bg_type' => 0,
'scribble_style_type' => 'YOUR_STYLE_ID',
'padding_type' => 0,
'height' => 1024,
'width' => 1024,
]);
$body = json_encode([
'task' => '/v1/AI_Drawing_White_V3/426943',
'task_type' => 'formula',
'init_images' => [[
'url' => 'https://example.com/input.png',
'profile' => [
'media_profiles' => ['media_data_type' => 'url'],
'version' => 'v1',
],
]],
'params' => $params,
'sync_timeout' => 30,
], JSON_UNESCAPED_SLASHES);
$url = 'https://openapi.meitu.com/api/v1/sdk/sync/push';
$headers = [
'Content-Type' => 'application/json',
'Host' => 'openapi.meitu.com',
];
$signer = new Signer('YOUR_ACCESS_KEY', 'YOUR_SECRET_KEY');
$curl = $signer->sign($url, 'POST', $headers, $body);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_HEADER, false);
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 10);
curl_setopt($curl, CURLOPT_TIMEOUT, 60);
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2);
$response = curl_exec($curl);
if ($response === false) {
echo 'Error: ' . curl_error($curl) . PHP_EOL;
} else {
echo 'Status: ' . curl_getinfo($curl, CURLINFO_HTTP_CODE) . PHP_EOL;
echo 'Response: ' . $response . PHP_EOL;
}
curl_close($curl);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 {
String body =
"{\n" +
" \"task\": \"/v1/AI_Drawing_White_V3/426943\",\n" +
" \"task_type\": \"formula\",\n" +
" \"init_images\": [\n" +
" {\n" +
" \"url\": \"https://example.com/input.png\",\n" +
" \"profile\": {\n" +
" \"media_profiles\": {\n" +
" \"media_data_type\": \"url\"\n" +
" },\n" +
" \"version\": \"v1\"\n" +
" }\n" +
" }\n" +
" ],\n" +
" \"params\": \"{\\\"scribble_bg_type\\\":0,\\\"scribble_style_type\\\":\\\"YOUR_STYLE_ID\\\",\\\"padding_type\\\":0,\\\"height\\\":1024,\\\"width\\\":1024}\",\n" +
" \"sync_timeout\": 30\n" +
"}";
String url = "https://openapi.meitu.com/api/v1/sdk/sync/push";
Map<String, String> headers = new HashMap<>();
headers.put("Content-Type", "application/json");
headers.put(Signer.HeaderHost, "openapi.meitu.com");
Signer signer = new Signer("YOUR_ACCESS_KEY", "YOUR_SECRET_KEY");
Map<String, String> signedHeaders = signer.sign(url, "POST", headers, body);
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
try {
connection.setRequestMethod("POST");
connection.setConnectTimeout(10000);
connection.setReadTimeout(60000);
connection.setInstanceFollowRedirects(false);
connection.setDoOutput(true);
for (Map.Entry<String, String> entry : signedHeaders.entrySet()) {
connection.setRequestProperty(entry.getKey(), entry.getValue());
}
byte[] bodyBytes = body.getBytes(StandardCharsets.UTF_8);
connection.setFixedLengthStreamingMode(bodyBytes.length);
try (OutputStream output = connection.getOutputStream()) {
output.write(bodyBytes);
}
int status = connection.getResponseCode();
System.out.println("Status: " + status);
InputStream stream = status >= 400
? connection.getErrorStream() : connection.getInputStream();
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();
}
}
}