> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://developer.ideogram.ai/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://developer.ideogram.ai/_mcp/server.

# Ghost Mannequin

POST https://api.ideogram.ai/v2/tool/ghost-mannequin
Content-Type: multipart/form-data

Turns photos of one garment into a ghost-mannequin product image on a
clean white studio background, removing the person, mannequin, hanger,
and other clothing. Upload the photos using `multipart/form-data`, in
the directional fields (such as `front_image`) when the camera
direction is known and in `garment_images` otherwise.
Returns a `generation_id`; poll `GET /v2/generations/{generation_id}` or
supply a `webhook_url`.

Reference: https://developer.ideogram.ai/api-reference/tools/ghost-mannequin

## Authentication

- `Api-Key` header (required) — API key for access control. Use in the header with the name \"Api-Key\"

## Request

### Query parameters

- `dry_run` (boolean, optional, default: false) — When true, the request is validated and priced but not run: nothing is generated, stored, or billed, and no safety review is performed. The response is a `PriceQuote` object instead of the usual response for this endpoint. Send exactly the request you would send to generate, so the quote reflects the same options.

### Body (multipart/form-data)

This endpoint expects a multipart form with multiple files.

- `garment_images` (files, optional) — Additional photos of the same garment, up to 50 MB each. JPEG, PNG, WEBP, HEIF, AVIF, GIF, BMP, TIFF, and MPO are supported. Multipart requests only.
- `front_image` (file, optional) — Optional front-view garment photo, up to 50 MB. Multipart requests only.
- `back_image` (file, optional) — Optional back-view garment photo, up to 50 MB. Multipart requests only.
- `left_image` (file, optional) — Optional left-view garment photo, up to 50 MB. Multipart requests only.
- `right_image` (file, optional) — Optional right-view garment photo, up to 50 MB. Multipart requests only.
- `top_image` (file, optional) — Optional top-view garment photo, up to 50 MB. Multipart requests only.
- `bottom_image` (file, optional) — Optional bottom-view garment photo, up to 50 MB. Multipart requests only.
- `view` (enum, required) — Camera view for the output garment.
- `instruction` (string, optional) — Optional reconstruction guidance or identity-critical garment details to check against the photos. The output always uses a clean white studio background.
- `metadata` (string, optional) — Optional JSON object serialized as a string containing factual product context, such as title, brand, category, color, material, item code, and exact printed text. Metadata helps disambiguate the garment photos but does not add features they do not show.
- `aspect_ratio` (string, optional) — Output aspect ratio. Defaults to `1:1` when omitted. Supported values are `1:1`, `3:4`, `4:3`, `16:9`, and `9:16`.
- `quality` (enum, optional)
- `seed` (integer, optional) — Optional seed for repeatable results.
- `webhook_url` (string, optional) — HTTPS URL that Ideogram delivers the generated result to. Ideogram sends a JSON POST to this URL once all images for the request have finished generating. The body mirrors the synchronous generate response: `request_id`, `created`, and a `data` array containing every generated image (`url`, `prompt`, `resolution`, `seed`, `is_image_safe`). Each delivery is signed with Ed25519 and verifiable against the public keys at `https://api.ideogram.ai/v1/.well-known/jwks.json`. Must be HTTPS; private and loopback hosts and the cloud metadata service are rejected.

## Response

### 200

Ghost-mannequin generation accepted for asynchronous processing.

- `generation_id` (string, required) — URL-safe base64 ID accepted by the generation polling endpoint.

## Errors

### 400 Bad Request Error

Invalid input provided.

- `any`

### 401 Unauthorized Error

Unauthorized.

- `any`

### 402 Payment Required Error

Insufficient credits or quota.

- `error` (string, required) — A message describing why the generation request was rejected.
- `reject_reason` (enum, required) — The account or usage limit that rejected a generation request.
  - Allowed values: `insufficient_funds`, `subscription_required`, `daily_limit`, `priority_credit_required`, `inflight_limit`, `feature_limit`
- `max_inflight_requests` (integer, optional) — How many generations the account may have in progress at once on the queue this request resolved to. Present when `reject_reason` is `inflight_limit`.
- `task_completion_speed` (enum, optional) — The queue this request resolved to. Present when `reject_reason` is `inflight_limit`.
  - Allowed values: `fast`, `slow`

### 403 Forbidden Error

Not authorized to create ghost-mannequin images.

- `any`

### 404 Not Found Error

An input asset was not found or is not readable.

- `any`

### 413 Content Too Large Error

The combined raw image uploads exceed 100 MB.

- `any`

### 422 Unprocessable Entity Error

The instruction did not pass prompt safety validation.

- `any`

### 429 Too Many Requests Error

Too many requests.

- `error` (string, required) — A message describing why the generation request was rejected.
- `reject_reason` (enum, required) — The account or usage limit that rejected a generation request.
  - Allowed values: `insufficient_funds`, `subscription_required`, `daily_limit`, `priority_credit_required`, `inflight_limit`, `feature_limit`
- `max_inflight_requests` (integer, optional) — How many generations the account may have in progress at once on the queue this request resolved to. Present when `reject_reason` is `inflight_limit`.
- `task_completion_speed` (enum, optional) — The queue this request resolved to. Present when `reject_reason` is `inflight_limit`.
  - Allowed values: `fast`, `slow`

## Examples

**Request**

```json
{
  "back_image": "<file: <file1>>",
  "bottom_image": "<file: <file1>>",
  "front_image": "<file: <file1>>",
  "garment_images": [],
  "left_image": "<file: <file1>>",
  "right_image": "<file: <file1>>",
  "top_image": "<file: <file1>>",
  "view": "front"
}
```

**Response**

```json
{
  "generation_id": "generation_id"
}
```

**SDK Code**

```python
import requests

url = "https://api.ideogram.ai/v2/tool/ghost-mannequin"

files = {
    "back_image": "open('<file1>', 'rb')",
    "bottom_image": "open('<file1>', 'rb')",
    "front_image": "open('<file1>', 'rb')",
    "left_image": "open('<file1>', 'rb')",
    "right_image": "open('<file1>', 'rb')",
    "top_image": "open('<file1>', 'rb')"
}
payload = {
    "aspect_ratio": ,
    "instruction": ,
    "metadata": ,
    "quality": ,
    "seed": ,
    "view": "front",
    "webhook_url": 
}
headers = {"Api-Key": "<apiKey>"}

response = requests.post(url, data=payload, files=files, headers=headers)

print(response.json())
```

```javascript
const url = 'https://api.ideogram.ai/v2/tool/ghost-mannequin';
const form = new FormData();
form.append('aspect_ratio', '');
form.append('back_image', '<file1>');
form.append('bottom_image', '<file1>');
form.append('front_image', '<file1>');
form.append('instruction', '');
form.append('left_image', '<file1>');
form.append('metadata', '');
form.append('quality', '');
form.append('right_image', '<file1>');
form.append('seed', '');
form.append('top_image', '<file1>');
form.append('view', 'front');
form.append('webhook_url', '');

const options = {method: 'POST', headers: {'Api-Key': '<apiKey>'}};

options.body = form;

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://api.ideogram.ai/v2/tool/ghost-mannequin"

	payload := strings.NewReader("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"aspect_ratio\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"back_image\"; filename=\"<file1>\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"bottom_image\"; filename=\"<file1>\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"front_image\"; filename=\"<file1>\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"instruction\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"left_image\"; filename=\"<file1>\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"metadata\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"quality\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"right_image\"; filename=\"<file1>\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"seed\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"top_image\"; filename=\"<file1>\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"view\"\r\n\r\nfront\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"webhook_url\"\r\n\r\n\r\n-----011000010111000001101001--\r\n")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("Api-Key", "<apiKey>")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby
require 'uri'
require 'net/http'

url = URI("https://api.ideogram.ai/v2/tool/ghost-mannequin")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Api-Key"] = '<apiKey>'
request.body = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"aspect_ratio\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"back_image\"; filename=\"<file1>\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"bottom_image\"; filename=\"<file1>\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"front_image\"; filename=\"<file1>\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"instruction\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"left_image\"; filename=\"<file1>\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"metadata\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"quality\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"right_image\"; filename=\"<file1>\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"seed\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"top_image\"; filename=\"<file1>\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"view\"\r\n\r\nfront\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"webhook_url\"\r\n\r\n\r\n-----011000010111000001101001--\r\n"

response = http.request(request)
puts response.read_body
```

```java
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://api.ideogram.ai/v2/tool/ghost-mannequin")
  .header("Api-Key", "<apiKey>")
  .body("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"aspect_ratio\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"back_image\"; filename=\"<file1>\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"bottom_image\"; filename=\"<file1>\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"front_image\"; filename=\"<file1>\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"instruction\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"left_image\"; filename=\"<file1>\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"metadata\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"quality\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"right_image\"; filename=\"<file1>\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"seed\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"top_image\"; filename=\"<file1>\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"view\"\r\n\r\nfront\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"webhook_url\"\r\n\r\n\r\n-----011000010111000001101001--\r\n")
  .asString();
```

```php
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://api.ideogram.ai/v2/tool/ghost-mannequin', [
  'multipart' => [
    [
        'name' => 'back_image',
        'filename' => '<file1>',
        'contents' => null
    ],
    [
        'name' => 'bottom_image',
        'filename' => '<file1>',
        'contents' => null
    ],
    [
        'name' => 'front_image',
        'filename' => '<file1>',
        'contents' => null
    ],
    [
        'name' => 'left_image',
        'filename' => '<file1>',
        'contents' => null
    ],
    [
        'name' => 'right_image',
        'filename' => '<file1>',
        'contents' => null
    ],
    [
        'name' => 'top_image',
        'filename' => '<file1>',
        'contents' => null
    ],
    [
        'name' => 'view',
        'contents' => 'front'
    ]
  ]
  'headers' => [
    'Api-Key' => '<apiKey>',
  ],
]);

echo $response->getBody();
```

```csharp
using RestSharp;

var client = new RestClient("https://api.ideogram.ai/v2/tool/ghost-mannequin");
var request = new RestRequest(Method.POST);
request.AddHeader("Api-Key", "<apiKey>");
request.AddParameter("undefined", "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"aspect_ratio\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"back_image\"; filename=\"<file1>\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"bottom_image\"; filename=\"<file1>\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"front_image\"; filename=\"<file1>\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"instruction\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"left_image\"; filename=\"<file1>\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"metadata\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"quality\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"right_image\"; filename=\"<file1>\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"seed\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"top_image\"; filename=\"<file1>\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"view\"\r\n\r\nfront\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"webhook_url\"\r\n\r\n\r\n-----011000010111000001101001--\r\n", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift
import Foundation

let headers = ["Api-Key": "<apiKey>"]
let parameters = [
  [
    "name": "aspect_ratio",
    "value": 
  ],
  [
    "name": "back_image",
    "fileName": "<file1>"
  ],
  [
    "name": "bottom_image",
    "fileName": "<file1>"
  ],
  [
    "name": "front_image",
    "fileName": "<file1>"
  ],
  [
    "name": "instruction",
    "value": 
  ],
  [
    "name": "left_image",
    "fileName": "<file1>"
  ],
  [
    "name": "metadata",
    "value": 
  ],
  [
    "name": "quality",
    "value": 
  ],
  [
    "name": "right_image",
    "fileName": "<file1>"
  ],
  [
    "name": "seed",
    "value": 
  ],
  [
    "name": "top_image",
    "fileName": "<file1>"
  ],
  [
    "name": "view",
    "value": "front"
  ],
  [
    "name": "webhook_url",
    "value": 
  ]
]

let boundary = "---011000010111000001101001"

var body = ""
var error: NSError? = nil
for param in parameters {
  let paramName = param["name"]!
  body += "--\(boundary)\r\n"
  body += "Content-Disposition:form-data; name=\"\(paramName)\""
  if let filename = param["fileName"] {
    let contentType = param["content-type"]!
    let fileContent = String(contentsOfFile: filename, encoding: String.Encoding.utf8)
    if (error != nil) {
      print(error as Any)
    }
    body += "; filename=\"\(filename)\"\r\n"
    body += "Content-Type: \(contentType)\r\n\r\n"
    body += fileContent
  } else if let paramValue = param["value"] {
    body += "\r\n\r\n\(paramValue)"
  }
}

let request = NSMutableURLRequest(url: NSURL(string: "https://api.ideogram.ai/v2/tool/ghost-mannequin")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```