Developer Docs/Product Avatar API

Product Avatar API

Generate product images with HeadSwap from a product photo and a person photo. Specify product_rect placement and query the task for result_image_url.

Overview

Generate a product image using a product photo, a person photo, and product_rect placement coordinates. The completed task returns result_image_url.

Primary Endpoint

POST/api/v1/productAvatar/start

Generate a product image by combining product and person images with customizable positioning and styling. This endpoint returns an image, not a video. **⚠️ IMPORTANT: This is an ASYNCHRONOUS operation** ### Async Workflow 1. **Submit Task** - Call this endpoint to create a new generation task - Returns immediately with task `_id` and status `initialized` - Task is queued for processing 2. **Processing States** - The task goes through these states: - `initialized` → Task created, waiting in queue - `sent` → Task submitted to AI service - `pending` → Task received by AI service - `processing` → AI is generating the image - `completed` → Generation finished successfully - `failed` → Generation failed (check `failed_message`) 3. **Get Results** - Poll for task status and results: - Use `GET /api/v1/productAvatar/{_id}` to check status - Use `GET /api/v1/productAvatar/allRecords` to list all tasks - When `current_status` is `completed`, `result_image_url` contains the generated image 4. **Timeout Handling**: - Tasks timeout after 2 hours and automatically fail - Credits are automatically refunded on timeout or failure ### Best Practices - Poll every 3-5 seconds to check task status - Handle both `completed` and `failed` states - Store the returned `_id` to query results later. ### Request - Send a valid bearer token. The server evaluates the operation in the authenticated caller's access context. - Send an `application/json` body. Required fields: `image_urls`, `product_rect`. - API-token callers may include `webhook_url` and `webhook_token` for best-effort terminal-state notifications; ordinary JWT/cookie calls ignore these fields. ### Behavior - This is an asynchronous operation: a successful submission creates a task and returns before processing finishes. - Persist the returned task identifier and use the corresponding detail or list operation to observe progress. - Treat the detail endpoint as the source of truth even when webhook delivery is enabled. ### Response - A `200` response confirms task acceptance; it does not by itself mean media generation has completed. - Retain the returned identifier and wait for a documented terminal status before using output URLs. - JSON object responses, including error responses, normally carry a top-level `trace_id` string for this request; include it when contacting support. It is not a task identifier. - Do not infer undocumented fields or statuses; clients should tolerate additional response properties. ### Errors - `400` — Bad Request - Invalid parameters or missing required fields. - `401` — Unauthorized - Invalid or missing JWT token. ### Related Operations - `GET /api/v1/productAvatar/allRecords` — List all product avatar tasks. - `GET /api/v1/productAvatar/{_id}` — Query task status and get result. - `DELETE /api/v1/productAvatar/{_id}` — Delete a product avatar task. Authentication: set header Authorization: Bearer <token> (supports user JWT or sk_ API token).

Request Parameters

NameTypeRequiredDescription
namestringNoName for the product avatar generation task (optional)
image_urlsarray<string>YesArray of image URLs - [0] product image, [1] person image; minItems: 2; maxItems: 2
product_rectobjectYesProduct placement on image_urls[1]. Coordinates use that person's original image pixel dimensions, with (0, 0) at the top-left. x and y identify the unrotated product box's top-left; the workflow uses x, y, rotation, and scale. Width and height remain required but currently do not change the generated output.
product_rect.xnumberYesLeft edge of the unrotated product box, in pixels from the left of the original image_urls[1] image.
product_rect.ynumberYesTop edge of the unrotated product box, in pixels from the top of the original image_urls[1] image.
product_rect.widthnumberYesProduct box width in person-image pixels, normally original product-image width multiplied by scale; required but currently ignored by the generation workflow.
product_rect.heightnumberYesProduct box height in person-image pixels, normally original product-image height multiplied by scale; required but currently ignored by the generation workflow.
product_rect.rotationnumberYesRotation angle in degrees
product_rect.scalenumberYesMultiplier applied to the original product image dimensions before placement.
promptstringNoAdditional prompt for AI generation (optional)
timeoutnumberNoProcessing timeout in seconds; default: 120
minor_suspected_skipbooleanNoSet to true when retrying after error code 1004 to confirm and bypass the suspected-minor soft block.; default: false
webhook_urlstringNoHTTPS URL to receive task.completed / task.failed notifications. Best-effort delivery, single attempt, no retries; clients should treat the detail API as the source of truth.; maxLength: 2048
webhook_tokenstringNoOptional plaintext token returned in the X-A2e-Webhook-Token header so receivers can verify the request originated from a2e.; maxLength: 256
Request schema and conditional rules
{
  "allOf": [
    {
      "type": "object",
      "properties": {
        "name": {
          "type": "string",
          "description": "Name for the product avatar generation task (optional)",
          "example": "My Product Avatar"
        },
        "image_urls": {
          "type": "array",
          "description": "Array of image URLs - [0] product image, [1] person image",
          "minItems": 2,
          "maxItems": 2,
          "items": {
            "type": "string",
            "format": "uri",
            "pattern": "^https?://.+",
            "description": "Image URL (must be HTTP/HTTPS)"
          },
          "example": [
            "https://example.com/product.jpg",
            "https://example.com/person.jpg"
          ]
        },
        "product_rect": {
          "type": "object",
          "description": "Product placement on image_urls[1]. Coordinates use that person's original image pixel dimensions, with (0, 0) at the top-left. x and y identify the unrotated product box's top-left; the workflow uses x, y, rotation, and scale. Width and height remain required but currently do not change the generated output.",
          "required": [
            "x",
            "y",
            "width",
            "height",
            "rotation",
            "scale"
          ],
          "properties": {
            "x": {
              "type": "number",
              "description": "Left edge of the unrotated product box, in pixels from the left of the original image_urls[1] image.",
              "example": 100
            },
            "y": {
              "type": "number",
              "description": "Top edge of the unrotated product box, in pixels from the top of the original image_urls[1] image.",
              "example": 150
            },
            "width": {
              "type": "number",
              "description": "Product box width in person-image pixels, normally original product-image width multiplied by scale; required but currently ignored by the generation workflow.",
              "example": 200
            },
            "height": {
              "type": "number",
              "description": "Product box height in person-image pixels, normally original product-image height multiplied by scale; required but currently ignored by the generation workflow.",
              "example": 300
            },
            "rotation": {
              "type": "number",
              "description": "Rotation angle in degrees",
              "example": 0
            },
            "scale": {
              "type": "number",
              "description": "Multiplier applied to the original product image dimensions before placement.",
              "example": 1
            }
          }
        },
        "prompt": {
          "type": "string",
          "description": "Additional prompt for AI generation (optional)",
          "example": "Professional product showcase"
        },
        "timeout": {
          "type": "number",
          "description": "Processing timeout in seconds",
          "default": 120,
          "example": 120
        },
        "minor_suspected_skip": {
          "type": "boolean",
          "default": false,
          "description": "Set to true when retrying after error code 1004 to confirm and bypass the suspected-minor soft block."
        }
      },
      "required": [
        "image_urls",
        "product_rect"
      ]
    },
    {
      "$ref": "#/components/schemas/WebhookInput"
    }
  ]
}

Response Fields

code: integer
data: object
Product avatar generation result
data._id: string
Task ID
data.name: string
Task name
data.current_status: enum: initialized | sent | pending | processing | completed | failed
Current processing status. Possible values - initialized, sent, pending, processing, completed, failed
data.coins: number
Cost in credits
trace_id: string
Trace ID of this HTTP request. Include it when contacting support about this request. It is generated per request and is not a task identifier; use the returned task `_id` to query results.

Request Example

curl -X POST "https://headswap.app/api/v1/productAvatar/start" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "My Product Avatar",
  "image_urls": [
    "https://example.com/product.jpg",
    "https://example.com/person.jpg"
  ],
  "product_rect": {
    "x": 100,
    "y": 150,
    "width": 200,
    "height": 300,
    "rotation": 0,
    "scale": 1
  },
  "prompt": "Professional product showcase",
  "timeout": 120
}'

Related Endpoints

Responses

200

Product avatar generation started successfully

400

Bad Request - Invalid parameters or missing required fields

401

Unauthorized - Invalid or missing bearer token

Product Avatar API Documentation