Retouch4me Cloud AI Retouching API
for Retouch4me AI Image Retouching
This documentation describes an AI-powered retouching platform for teams that need an automated photo retouching API and a cloud-based AI retouching service for portrait retouching, batch processing, and photo post-production workflows. Start with the token instructions below, review the task format, use job status polling as the baseline integration approach, check the webhook integration guide only if you need asynchronous callbacks, and jump to the examples.
General Information
The media server is available at retoucher.hz.labs.retouch4.me.
All API requests are made to /api/v1/<route>, for example:
https://retoucher.hz.labs.retouch4.me/api/v1/retoucher/getFile/s0me-very-l0ng-1d
Retouch Token
Obtain the Retouch token by visiting https://retouch4.me/token_page with an authorized and verified Retouch4me account.
The token is required for all cloud retouching requests that submit or query user work.
Common Error Codes
These error codes can appear across cloud retouching requests when the token is invalid, the task is rejected, or the service cannot complete the requested operation.
- 200 - No errors.
- 400 - Unknown error or invalid request parameters.
- 404 - Requested route or object was not found.
- 460 - Token not found.
- 461 - Processing limit reached.
- 462 - Invalid task for retouch server.
The general retouching pipeline is as follows:
- The image processing task is submitted via
/retoucher/start
- While processing is pending, you can request the current status at
/retoucher/status/{id}
- If the process completes successfully, the result can be fetched from
/retoucher/getFile/{id}
Retrieve Balance https://3dlutcreator.com/api/retouch/v1/balance
Before submitting a processing task, you can check how many cloud retouch credits remain for the current user.
| Protocol | HTTP |
| Method | POST |
| contentType | multipart/form-data |
The request must be sent to:
https://3dlutcreator.com/api/retouch/v1/balance
The following fields are expected in the request body:
retouchtoken- a valid retouch token for the user
modes[]- one or more requested credit types, for exampleprofessional
Example request:
curl --location 'https://3dlutcreator.com/api/retouch/v1/balance' \
--header 'Accept: application/json' \
--form 'retouchtoken="reto_x7K2mQ9Lp4Nz8Vb1cR5Ty0Hs"' \
--form 'modes[]="professional"'
Successful response:
{
"status": 200,
"remaining": {
"professional": 5
}
}
If the token is invalid or expired, the endpoint returns a 401 error with an explanatory message.
Register Task /retoucher/start
Request Description
| Protocol | HTTP |
| Method | POST |
| contentType | multipart/form-data |
The following fields are expected in the request body:
- file - an image file in jpeg, png, or jpg format
- token - user token obtained from token_page
- payload - JSON string describing the task
Processing
- The task is registered on the server and receives a unique ID
- User token is verified
- The task is queued for processing and returns the task ID
Successful Response
If the request is successful, the task is queued, and the server returns
a JSON object with the following fields:
- status - 200
- id - unique task ID used to request the result and processing status
- retouchQuota - remaining retouch attempts for the user for the current day
Possible Errors
If the request is missing a file, the server returns a 400 error with message="No file uploaded"
If there are issues on the server, it returns a 500 error with an error message.
If the CRM returns a 4xx error, a 4xx error code and message="Token issue" are returned.
If the server cannot communicate with the CRM or returns a 200 status, processing continues.
Retouch Status Request /retoucher/status/{id}
| Protocol | HTTP |
| Method | GET |
Request Description
GET request, id is passed in the URL.
Example request:
https://retoucher.hz.labs.retouch4.me/api/v1/retoucher/status/s0me-very-l0ng-1d
Successful Response
In case of a successful request, the server returns JSON with the following fields:
- status - 200
- state - task status
- completed - task completed successfully
- failed - an error occurred during processing
- waiting - task is waiting in queue
- active - task is being processed
- delayed - task is delayed
- progress - number between 0 and 100, indicating the progress of the task
- reason - if the state is failed, the reason field will contain an error message
Possible Errors
If no task with the given id is found, the server returns a 404 error
If there is a server error, a 500 error is returned
Notes
It's better not to request status updates too frequently, such as using a 1-second interval
Get Retouch Result /retoucher/getFile/{id}
Request Description
GET request, id is passed as a param in the URL (similar to the status request).
Successful Response
Depending on the task, this endpoint returns:
- JSON (for mode=facefeatures)
- Image (for mode=retouch4fun)
- ZIP archive with images (for mode=professional and when layers=1 is set in at least one of the plugins, check Task Description how to set layers property) Otherwise, it returns an Image.
This documentation covers tasks with mode=professional, so the response is expected to be a ZIP archive.
Possible Errors
If no task with the given id is found, the server returns a 404 error
If there is a server error, a 500 error is returned
Notes
The /retoucher/getFile request should be made only after receiving a status with state="completed". Even if progress=100, the result may not yet be saved in a file, and the server won’t be able to return it.
It’s also not possible to request old files, as the results are stored for only 24 hours.
Limitations
Before submitting a retouch request, you should check the file (photo or archive) for limitations. The list of limitations can be obtained with a GET request to /info/limits
This endpoint returns JSON in the following format:
{
image: {
formats: ["png", "jpg", "jpeg"],
maxFileSizeInMB: 100,
maxMegapixels: 250
},
archive: {
formats: ["zip"]
}
}
The JSON above indicates that the allowed image formats are png, jpg, jpeg, the maximum file size is 100 MB, and the image resolution should not exceed 250 megapixels.
If these limitations are violated, the task may not be processed.
At the moment, this endpoint is not available in production.
FAQ
How do I get a retouch token?
Use the token acquisition instructions above to obtain a valid token for every cloud retouch request.
How do I submit a retouching task?
Send a multipart request to /retoucher/start with the source image, token, and JSON payload. The payload structure is described on the task format page.
How do I check processing progress?
Poll /retoucher/status/{id} until the task reaches completed or failed.
How do I download the result?
After completion, download the final file or layered archive from /retoucher/getFile/{id}.
Which formats are supported?
The service accepts common image formats such as JPEG and PNG and can return either a flat retouched image or a ZIP archive with layers, depending on the payload.
Complete Examples
These examples use one source photo and two task payloads: one returns a final retouched JPEG, and the other returns a layered ZIP archive.
Example 1 - All-In-One Retouching
This example sends a flat task and receives one final JPEG file.
Important: the final look depends on the JSON payload. The same source image can produce a lighter, balanced, or stronger retouch depending on the plugin parameters you choose.
Payload presets: use the same /retoucher/start request and replace only the JSON in the payload field.
Balanced retouching JSON: a moderate preset for a clean, commercial result.
Note: Dodge Burn uses Scale: 2 in this example for more detailed work.
{
"mode": "professional",
"tasks": [
{"Plugin": "Heal", "Scale": 0, "Alpha1": 1.0},
{"Plugin": "Fabric", "Scale": 0, "Alpha1": 0.39},
{"Plugin": "Eye Vessels", "Scale": 0, "Alpha1": 1.0},
{"Plugin": "Eye Brilliance", "Scale": 0, "Alpha1": 0.5},
{"Plugin": "White Teeth", "Scale": 0, "Alpha1": 0.25, "Alpha2": 0.25},
{"Plugin": "Dodge Burn", "Scale": 2, "Alpha1": 1.0, "Alpha2": 0.2},
{"Plugin": "Skin Tone", "Scale": 0, "Alpha1": 1.0, "Alpha2": 1.0},
{"Plugin": "Portrait Volumes", "Scale": 0, "Alpha1": 0.5}
]
}
Slight retouching JSON: lower values for a softer result that keeps more of the original skin texture and contrast.
{
"mode": "professional",
"tasks": [
{"Plugin": "Heal", "Scale": 0, "Alpha1": 0.8},
{"Plugin": "Eye Vessels", "Scale": 0, "Alpha1": 0.35},
{"Plugin": "White Teeth", "Scale": 0, "Alpha1": 0.1, "Alpha2": 0.08},
{"Plugin": "Dodge Burn", "Scale": 2, "Alpha1": 0.35, "Alpha2": 0.08},
{"Plugin": "Skin Tone", "Scale": 0, "Alpha1": 0.35, "Alpha2": 0.35},
{"Plugin": "Portrait Volumes", "Scale": 0, "Alpha1": 0.18}
]
}
Heavy retouching JSON: higher values for a stronger polished look with more visible cleanup and shaping.
{
"mode": "professional",
"tasks": [
{"Plugin": "Heal", "Scale": 0, "Alpha1": 0.9},
{"Plugin": "Fabric", "Scale": 0, "Alpha1": 0.75},
{"Plugin": "Eye Vessels", "Scale": 0, "Alpha1": 0.9},
{"Plugin": "Eye Brilliance", "Scale": 0, "Alpha1": 0.85},
{"Plugin": "White Teeth", "Scale": 0, "Alpha1": 0.65, "Alpha2": 0.55},
{"Plugin": "Dodge Burn", "Scale": 2, "Alpha1": 1.35, "Alpha2": 0.35},
{"Plugin": "Skin Tone", "Scale": 0, "Alpha1": 1.15, "Alpha2": 1.15},
{"Plugin": "Portrait Volumes", "Scale": 0, "Alpha1": 0.9}
]
}
Start request: submit the source image, token, and inline JSON payload. Replace the payload with whichever preset matches your preferred look.
Baseline approach: submit the task, then poll /retoucher/status/{id} until the job is complete.
Webhook option: if you want asynchronous completion callbacks instead of relying only on polling, add the optional hook form field and follow the webhook integration guide. Before using webhooks, send the list of webhook domains to relu@retouch4.me so they can be approved.
curl --location 'https://retoucher.hz.labs.retouch4.me/api/v1/retoucher/start' \
--form 'file=@"DSC_6229_Sample.jpg"' \
--form 'token="retoexampletokenvaluex83n4j2k9q7m5p1"' \
--form-string 'payload={"mode":"professional","tasks":[{"Plugin":"Heal","Scale":0,"Alpha1":1.0},{"Plugin":"Fabric","Scale":0,"Alpha1":0.39},{"Plugin":"Eye Vessels","Scale":0,"Alpha1":1.0},{"Plugin":"Eye Brilliance","Scale":0,"Alpha1":0.5},{"Plugin":"White Teeth","Scale":0,"Alpha1":0.25,"Alpha2":0.25},{"Plugin":"Dodge Burn","Scale":2,"Alpha1":1.0,"Alpha2":0.2},{"Plugin":"Skin Tone","Scale":0,"Alpha1":1.0,"Alpha2":1.0},{"Plugin":"Portrait Volumes","Scale":0,"Alpha1":0.5}]}'
curl --location "https://retoucher.hz.labs.retouch4.me/api/v1/retoucher/start" --form "file=@DSC_6229_Sample.jpg" --form "token=retoexampletokenvaluex83n4j2k9q7m5p1" --form-string "payload={\"mode\":\"professional\",\"tasks\":[{\"Plugin\":\"Heal\",\"Scale\":0,\"Alpha1\":1.0},{\"Plugin\":\"Fabric\",\"Scale\":0,\"Alpha1\":0.39},{\"Plugin\":\"Eye Vessels\",\"Scale\":0,\"Alpha1\":1.0},{\"Plugin\":\"Eye Brilliance\",\"Scale\":0,\"Alpha1\":0.5},{\"Plugin\":\"White Teeth\",\"Scale\":0,\"Alpha1\":0.25,\"Alpha2\":0.25},{\"Plugin\":\"Dodge Burn\",\"Scale\":2,\"Alpha1\":1.0,\"Alpha2\":0.2},{\"Plugin\":\"Skin Tone\",\"Scale\":0,\"Alpha1\":1.0,\"Alpha2\":1.0},{\"Plugin\":\"Portrait Volumes\",\"Scale\":0,\"Alpha1\":0.5}]}"
Start response: the API returns a task id that is later used for polling and file download.
{
"status": 200,
"id": "jpeg-example-job-id",
"retouchQuota": 999
}
Status request: poll the task id until the state becomes completed.
curl --location 'https://retoucher.hz.labs.retouch4.me/api/v1/retoucher/status/jpeg-example-job-id'
Status response: real in-progress example.
{
"status": 200,
"state": "active",
"progress": 5,
"reason": "",
"attempt": 1,
"currentStep": "downloading",
"maxAttempts": 3,
"pluginName": "",
"expireDate": "2026-03-18T21:58:47.836Z"
}
Status response: real completed example.
{
"status": 200,
"state": "completed",
"progress": 100,
"reason": "",
"attempt": 1,
"currentStep": "uploading",
"maxAttempts": 3,
"pluginName": "",
"expireDate": "2026-03-18T21:29:16.144Z"
}
Note: in the current API, currentStep may keep the last internal stage name even when state is already completed.
Download request: fetch the finished JPEG file by task id.
curl --location 'https://retoucher.hz.labs.retouch4.me/api/v1/retoucher/getFile/jpeg-example-job-id' \
--output DSC_6229_Cloud_Retouch.jpg
curl --location "https://retoucher.hz.labs.retouch4.me/api/v1/retoucher/getFile/jpeg-example-job-id" --output DSC_6229_Cloud_Retouch.jpg
Complete Workflow Scripts
These examples cover the whole photo retouching flow: submit the source image, poll the job status until completion, and download the final JPEG.
Set RETOUCH_TOKEN before running them. Each example uses the balanced all-in-one payload shown above and writes the result file next to the sample image.
Runtime: PHP with cURL enabled.
<?php
declare(strict_types=1);
const API_BASE = 'https://retoucher.hz.labs.retouch4.me/api/v1/retoucher';
$token = getenv('RETOUCH_TOKEN') ?: '<your_token_here>';
$sourceFile = __DIR__ . '/../DSC_6229_Sample.jpg';
$outputFile = __DIR__ . '/../retouch_result_php.jpg';
$payload = [
'mode' => 'professional',
'tasks' => [
['Plugin' => 'Heal', 'Scale' => 0, 'Alpha1' => 1.0],
['Plugin' => 'Fabric', 'Scale' => 0, 'Alpha1' => 0.39],
['Plugin' => 'Eye Vessels', 'Scale' => 0, 'Alpha1' => 1.0],
['Plugin' => 'Eye Brilliance', 'Scale' => 0, 'Alpha1' => 0.5],
['Plugin' => 'White Teeth', 'Scale' => 0, 'Alpha1' => 0.25, 'Alpha2' => 0.25],
['Plugin' => 'Dodge Burn', 'Scale' => 2, 'Alpha1' => 1.0, 'Alpha2' => 0.2],
['Plugin' => 'Skin Tone', 'Scale' => 0, 'Alpha1' => 1.0, 'Alpha2' => 1.0],
['Plugin' => 'Portrait Volumes', 'Scale' => 0, 'Alpha1' => 0.5],
],
];
$jobId = startJob($token, $sourceFile, $payload);
$status = waitForCompletion($jobId);
downloadResult($jobId, $outputFile);
function startJob(string $token, string $sourceFile, array $payload): string
{
$response = requestJson(
API_BASE . '/start',
[
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => [
'file' => new CURLFile($sourceFile),
'token' => $token,
'payload' => json_encode($payload, JSON_UNESCAPED_SLASHES),
],
]
);
return (string) $response['id'];
}
function waitForCompletion(string $jobId): array
{
while (true) {
$response = requestJson(API_BASE . '/status/' . rawurlencode($jobId));
if (($response['state'] ?? '') === 'completed') {
return $response;
}
if (($response['state'] ?? '') === 'failed') {
throw new RuntimeException('Job failed: ' . ($response['reason'] ?? 'unknown'));
}
sleep(5);
}
}
function downloadResult(string $jobId, string $outputFile): void
{
$fp = fopen($outputFile, 'wb');
$ch = curl_init(API_BASE . '/getFile/' . rawurlencode($jobId));
curl_setopt_array($ch, [CURLOPT_FILE => $fp, CURLOPT_FOLLOWLOCATION => true]);
curl_exec($ch);
curl_close($ch);
fclose($fp);
}
function requestJson(string $url, array $extraOptions = []): array
{
$ch = curl_init($url);
curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true] + $extraOptions);
$body = curl_exec($ch);
curl_close($ch);
return json_decode((string) $body, true);
}
Runtime: Python 3 standard library only.
import json
import mimetypes
import os
import time
import urllib.request
import uuid
API_BASE = "https://retoucher.hz.labs.retouch4.me/api/v1/retoucher"
SOURCE_FILE = os.path.join(os.path.dirname(__file__), "..", "DSC_6229_Sample.jpg")
OUTPUT_FILE = os.path.join(os.path.dirname(__file__), "..", "retouch_result_python.jpg")
TOKEN = os.environ.get("RETOUCH_TOKEN", "<your_token_here>")
PAYLOAD = {
"mode": "professional",
"tasks": [
{"Plugin": "Heal", "Scale": 0, "Alpha1": 1.0},
{"Plugin": "Fabric", "Scale": 0, "Alpha1": 0.39},
{"Plugin": "Eye Vessels", "Scale": 0, "Alpha1": 1.0},
{"Plugin": "Eye Brilliance", "Scale": 0, "Alpha1": 0.5},
{"Plugin": "White Teeth", "Scale": 0, "Alpha1": 0.25, "Alpha2": 0.25},
{"Plugin": "Dodge Burn", "Scale": 2, "Alpha1": 1.0, "Alpha2": 0.2},
{"Plugin": "Skin Tone", "Scale": 0, "Alpha1": 1.0, "Alpha2": 1.0},
{"Plugin": "Portrait Volumes", "Scale": 0, "Alpha1": 0.5},
],
}
def start_job():
boundary = f"----RetouchBoundary{uuid.uuid4().hex}"
body = build_multipart_body(
boundary,
[("token", TOKEN), ("payload", json.dumps(PAYLOAD, separators=(",", ":")))],
[("file", SOURCE_FILE)],
)
request = urllib.request.Request(
f"{API_BASE}/start",
data=body,
method="POST",
headers={"Content-Type": f"multipart/form-data; boundary={boundary}"},
)
with urllib.request.urlopen(request) as response:
return json.loads(response.read().decode("utf-8"))["id"]
def wait_for_completion(job_id):
while True:
with urllib.request.urlopen(f"{API_BASE}/status/{job_id}") as response:
data = json.loads(response.read().decode("utf-8"))
if data.get("state") == "completed":
return
if data.get("state") == "failed":
raise RuntimeError(data.get("reason", "unknown"))
time.sleep(5)
def download_result(job_id):
with urllib.request.urlopen(f"{API_BASE}/getFile/{job_id}") as response:
with open(OUTPUT_FILE, "wb") as f:
f.write(response.read())
def build_multipart_body(boundary, fields, files):
chunks = []
for name, value in fields:
chunks += [
f"--{boundary}\r\n".encode(),
f'Content-Disposition: form-data; name="{name}"\r\n\r\n'.encode(),
str(value).encode(),
b"\r\n",
]
for field_name, file_path in files:
filename = os.path.basename(file_path)
content_type = mimetypes.guess_type(filename)[0] or "application/octet-stream"
with open(file_path, "rb") as f:
file_content = f.read()
chunks += [
f"--{boundary}\r\n".encode(),
f'Content-Disposition: form-data; name="{field_name}"; filename="{filename}"\r\n'.encode(),
f"Content-Type: {content_type}\r\n\r\n".encode(),
file_content,
b"\r\n",
]
chunks.append(f"--{boundary}--\r\n".encode())
return b"".join(chunks)
job_id = start_job()
wait_for_completion(job_id)
download_result(job_id)
Runtime: Node.js 18+ with native fetch, FormData, and Blob.
const fs = require('node:fs/promises');
const path = require('node:path');
const API_BASE = 'https://retoucher.hz.labs.retouch4.me/api/v1/retoucher';
const sourceFile = path.join(__dirname, '..', 'DSC_6229_Sample.jpg');
const outputFile = path.join(__dirname, '..', 'retouch_result_js.jpg');
const token = process.env.RETOUCH_TOKEN || '<your_token_here>';
const payload = {
mode: 'professional',
tasks: [
{ Plugin: 'Heal', Scale: 0, Alpha1: 1.0 },
{ Plugin: 'Fabric', Scale: 0, Alpha1: 0.39 },
{ Plugin: 'Eye Vessels', Scale: 0, Alpha1: 1.0 },
{ Plugin: 'Eye Brilliance', Scale: 0, Alpha1: 0.5 },
{ Plugin: 'White Teeth', Scale: 0, Alpha1: 0.25, Alpha2: 0.25 },
{ Plugin: 'Dodge Burn', Scale: 2, Alpha1: 1.0, Alpha2: 0.2 },
{ Plugin: 'Skin Tone', Scale: 0, Alpha1: 1.0, Alpha2: 1.0 },
{ Plugin: 'Portrait Volumes', Scale: 0, Alpha1: 0.5 },
],
};
async function startJob() {
const fileBuffer = await fs.readFile(sourceFile);
const formData = new FormData();
formData.append('file', new Blob([fileBuffer]), path.basename(sourceFile));
formData.append('token', token);
formData.append('payload', JSON.stringify(payload));
const response = await fetch(`${API_BASE}/start`, { method: 'POST', body: formData });
const data = await response.json();
if (!response.ok) throw new Error(JSON.stringify(data));
return data.id;
}
async function waitForCompletion(jobId) {
while (true) {
const response = await fetch(`${API_BASE}/status/${encodeURIComponent(jobId)}`);
const data = await response.json();
if (data.state === 'completed') return;
if (data.state === 'failed') throw new Error(data.reason || 'unknown');
await new Promise((resolve) => setTimeout(resolve, 5000));
}
}
async function downloadResult(jobId) {
const response = await fetch(`${API_BASE}/getFile/${encodeURIComponent(jobId)}`);
const buffer = Buffer.from(await response.arrayBuffer());
await fs.writeFile(outputFile, buffer);
}
(async () => {
const jobId = await startJob();
await waitForCompletion(jobId);
await downloadResult(jobId);
})();
Example 2 - Retouching with Layers
This example sends a layered task and receives a ZIP archive with separate PNG layers that can be composited in an editor.
Note: Mattifier and Clean Backdrop are not included in this layered example.
Payload JSON: layered retouching task definition.
Note: Dodge Burn uses Scale: 2 in this example for more detailed work.
{
"mode": "professional",
"tasks": [
{"Plugin": "Skin Mask", "Scale": 0, "Alpha1": 1.0, "Layer": 1},
{"Plugin": "Heal", "Scale": 0, "Alpha1": 1.0, "Layer": 1},
{"Plugin": "Fabric", "Scale": 0, "Alpha1": 0.39, "Layer": 1},
{"Plugin": "Eye Vessels", "Scale": 0, "Alpha1": 1.0, "Layer": 1},
{"Plugin": "Eye Brilliance", "Scale": 0, "Alpha1": 0.5, "Layer": 1},
{"Plugin": "White Teeth", "Scale": 0, "Alpha1": 0.25, "Alpha2": 0.25, "Layer": 1},
{"Plugin": "Dodge Burn", "Scale": 2, "Alpha1": 1.0, "Alpha2": 0.2, "Layer": 1},
{"Plugin": "Skin Tone", "Scale": 0, "Alpha1": 1.0, "Alpha2": 1.0, "Layer": 1},
{"Plugin": "Portrait Volumes", "Scale": 0, "Alpha1": 0.5, "Layer": 1}
]
}
Start request: submit the source image, token, and layered payload with Layer: 1.
Baseline approach: submit the layered task, then poll /retoucher/status/{id} until the archive is ready.
Webhook option: the same optional hook form field can be used for layered jobs when you want a completion callback instead of polling only. Before using webhooks, send the list of webhook domains to relu@retouch4.me so they can be approved.
curl --location 'https://retoucher.hz.labs.retouch4.me/api/v1/retoucher/start' \
--form 'file=@"DSC_6229_Sample.jpg"' \
--form 'token="retoexampletokenvaluex83n4j2k9q7m5p1"' \
--form-string 'payload={"mode":"professional","tasks":[{"Plugin":"Skin Mask","Scale":0,"Alpha1":1.0,"Layer":1},{"Plugin":"Heal","Scale":0,"Alpha1":1.0,"Layer":1},{"Plugin":"Fabric","Scale":0,"Alpha1":0.39,"Layer":1},{"Plugin":"Eye Vessels","Scale":0,"Alpha1":1.0,"Layer":1},{"Plugin":"Eye Brilliance","Scale":0,"Alpha1":0.5,"Layer":1},{"Plugin":"White Teeth","Scale":0,"Alpha1":0.25,"Alpha2":0.25,"Layer":1},{"Plugin":"Dodge Burn","Scale":2,"Alpha1":1.0,"Alpha2":0.2,"Layer":1},{"Plugin":"Skin Tone","Scale":0,"Alpha1":1.0,"Alpha2":1.0,"Layer":1},{"Plugin":"Portrait Volumes","Scale":0,"Alpha1":0.5,"Layer":1}]}'
curl --location "https://retoucher.hz.labs.retouch4.me/api/v1/retoucher/start" --form "file=@DSC_6229_Sample.jpg" --form "token=retoexampletokenvaluex83n4j2k9q7m5p1" --form-string "payload={\"mode\":\"professional\",\"tasks\":[{\"Plugin\":\"Skin Mask\",\"Scale\":0,\"Alpha1\":1.0,\"Layer\":1},{\"Plugin\":\"Heal\",\"Scale\":0,\"Alpha1\":1.0,\"Layer\":1},{\"Plugin\":\"Fabric\",\"Scale\":0,\"Alpha1\":0.39,\"Layer\":1},{\"Plugin\":\"Eye Vessels\",\"Scale\":0,\"Alpha1\":1.0,\"Layer\":1},{\"Plugin\":\"Eye Brilliance\",\"Scale\":0,\"Alpha1\":0.5,\"Layer\":1},{\"Plugin\":\"White Teeth\",\"Scale\":0,\"Alpha1\":0.25,\"Alpha2\":0.25,\"Layer\":1},{\"Plugin\":\"Dodge Burn\",\"Scale\":2,\"Alpha1\":1.0,\"Alpha2\":0.2,\"Layer\":1},{\"Plugin\":\"Skin Tone\",\"Scale\":0,\"Alpha1\":1.0,\"Alpha2\":1.0,\"Layer\":1},{\"Plugin\":\"Portrait Volumes\",\"Scale\":0,\"Alpha1\":0.5,\"Layer\":1}]}"
Start response: the API returns a task id for the layered archive job.
{
"status": 200,
"id": "layers-example-job-id",
"retouchQuota": 999
}
Check Processing State
Status request: poll the layered task until the archive is ready.
curl --location 'https://retoucher.hz.labs.retouch4.me/api/v1/retoucher/status/layers-example-job-id'
Status response: real completed layered-job example.
{
"status": 200,
"state": "completed",
"progress": 100,
"reason": "",
"attempt": 1,
"currentStep": "uploading",
"maxAttempts": 3,
"pluginName": "",
"expireDate": "2026-03-18T21:29:19.055Z"
}
Download Result File
Download request: fetch the finished ZIP archive by task id.
curl --location 'https://retoucher.hz.labs.retouch4.me/api/v1/retoucher/getFile/layers-example-job-id' \
--output DSC_6229_Cloud_Retouch_Layers.zip
curl --location "https://retoucher.hz.labs.retouch4.me/api/v1/retoucher/getFile/layers-example-job-id" --output DSC_6229_Cloud_Retouch_Layers.zip
Layer Previews
The layered archive contains separate PNG files that can be composited in Photoshop or another editor. Use the blend mode from the file name when applicable.
Skin Mask

Use this mask as a selection helper to confine color and texture work to skin areas.
Heal

Use this normal layer for blemish cleanup and removal of small skin distractions.
Fabric

Use this normal layer to soften wrinkles and clean texture on clothing and fabric details.
Eye Vessels

Use this normal layer to reduce visible veins and redness in the whites of the eyes.
Eye Brilliance

Use this normal layer to enhance iris detail and add subtle brightness to the eyes.
White Teeth

Use this normal layer to whiten and slightly brighten teeth while keeping the effect adjustable.
Dodge Burn

Use this soft-light layer for local light and shadow shaping on skin and facial features.
Skin Tone

Use this soft-light layer to unify skin color and reduce uneven tone transitions.
Portrait Volumes

Use this soft-light layer to emphasize shape and volume in the face and portrait contours.



