Generating renders
Two task families on one workflow. The Product beautifier renders the product alone on a background; a photo shoot puts it on a model. Both return a task you poll or subscribe to.
Every task shares the same shape: the same authentication, the same lifecycle queued → processing → completed | failed, the same delivery contract. Pick the endpoint by what you want back.
Product beautifier
POST/v1/tasks/beautifier
A clean render of the product alone on a chosen background. subtype selects the flow.
| Subtype | Inputs |
|---|---|
clothing |
style is required: ghost_mannequin (“Ghost mannequin” in the dashboard) or flatlay. angle_shot names which uploaded view to render from (front or back). |
shoes |
style is forbidden. angle_shot is the desired output view from the shoes catalog. The product needs at least one user-uploaded photo. |
headwear |
Same shape as shoes, with the headwear angle catalog. |
glasses |
Same shape as shoes, with the glasses angle catalog. |
bags |
Same shape as shoes, with the bags angle catalog. top_open needs a photo of the bag open: without one the task fails and is not billed. |
curl https://api.veeton.com/v1/tasks/beautifier \ -H "Authorization: Bearer $VEETON_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: $(uuidgen)" \ -d '{ "subtype": "clothing", "inputs": { "product_id": "01HX5K2MZ7A3Q4FBNDC0EVDXY1", "background": "#ffffff", "angle_shot": "front", "style": "ghost_mannequin" } }'background is a slug from the backgrounds catalog, shared by every beautifier subtype. Hex-coded slugs include the leading # and are case-insensitive. The full galleries of backgrounds, angle shots and styles are in the API reference.
Photo shoot
POST/v1/tasks/tryon
The product worn by a model, on a scene of your choice. A photo shoot (tryon) has a single flow: the product’s own type drives the worker, so there is no subtype.
curl https://api.veeton.com/v1/tasks/tryon \ -H "Authorization: Bearer $VEETON_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: $(uuidgen)" \ -d '{ "inputs": [ { "product_id": "01HX5K2MZ7A3Q4FBNDC0EVDXY1", "model_id": "01HX5K2MZ7A3Q4FBNDC0EVDXMD1", "outfit_product_ids": ["01HX5K2MZ7A3Q4FBNDC0EVDXPN"], "background": "park", "angle_shot": "full_body_relaxed_symmetric", "gaze": "camera" } ] }'| Input | Meaning |
|---|---|
product_id |
The main product. Must be yours and have at least one user-uploaded photo. |
model_id |
A model from GET /v1/models: Veeton-curated public models and models generated by your organization share one id space. Treat ids as opaque. |
outfit_product_ids |
The styling items: up to 10 more products worn alongside the main one (main is a top, styling is pants and shoes). Cannot include the main product. |
background |
A slug from the photo shoot catalog: every Product beautifier category plus indoor and outdoor scenes. |
angle_shot |
A slug from the angle shots catalog. Your organization’s custom angle shots are accepted too. |
gaze |
The dashboard’s “Gaze”: auto (default) keeps the gaze of the angle shot, camera makes the model look into the lens (a back view keeps its pose), away makes the model look away. |
aspect_ratio |
The shape of the output, width/height: auto (default) or one of 1/1, 2/3, 3/4, 4/5, 9/16, 3/2, 4/3, 16/9. auto follows the angle shot: a square angle shot gives a square image, as a photo shoot launched from the dashboard with Format on Auto does. An explicit ratio overrides it and the framing adapts to it. |
The body is always an array of 1 to 20 inputs and the response is always { "data": Task[] }, one task per input in submission order.
Consistency groups
Inputs that share the same model_id, product_id and outfit_product_ids are dispatched together as a consistency group: identity and styling are computed once and reused, so the outputs look like one set. Vary angle_shot, background or gaze across the entries of one request to get coherent variants. Separate requests do not share a group.
Validation
If any input fails validation the whole request is refused with 400 and every bad input listed, so you never retry-and-bisect.
{ "errors": [ { "input_index": 1, "type": "not_found", "code": "model_not_found", "param": "model_id", "message": "Model 01HX… was not found." } ]}Edit with AI
POST/v1/tasks/edit
Change a finished result with a prompt. Name the image to edit and say what you want changed.
{ "inputs": { "image_id": "01HX5K2MZ7A3Q4FBNDC0EVDXIM", "prompt": "Remove the wrinkle on the left sleeve." }}You can edit the output of a completed beautifier or tryon task, or of a completed edit. Your own uploaded photos, and results still running or that failed, are refused with 422 image_not_editable.
An edit makes a new image with its own id. The image you named never changes, and neither does its task’s output_image. Both images are listed in GET /v1/images and in exports, and the new one names its source in edited_from_image_id. To follow a chain of edits, an image nothing was edited from is the end of it. Which version to publish is your choice.
Reading a task
GET/v1/tasks/{task_id}
{ "id": "01HX5K2MZ7A3Q4FBNDC0EVDXY2", "type": "tryon", "subtype": null, "status": "completed", "product_id": "01HX5K2MZ7A3Q4FBNDC0EVDXY1", "inputs": { "product_id": "01HX5K2MZ7A3Q4FBNDC0EVDXY1", "background": "wood", "angle_shot": "front", "style": "ghost_mannequin" }, "output_image": { "id": "01HX…", "mime_type": "image/webp", "width": 1536, "height": 2048, "url": "https://…signed…", "url_expires_at": "2026-09-03T15:32:00Z", "created_at": "2026-09-03T14:31:40Z" }, "failure_reason": null, "started_at": "2026-09-03T14:30:12Z", "finished_at": "2026-09-03T14:31:40Z", "created_at": "2026-09-03T14:30:09Z"}inputs echoes what the task was created with, so a task can be understood on its own. output_image is set once the task has completed and is the same Image object every endpoint returns. Its id is an image id: use it with GET /v1/images/{id} for a fresh URL, and it is what the export lists under the product with role: beautifier or tryon.
GET/v1/tasks lists your tasks newest first with status, type, subtype and product_id filters. Use it for reconciliation after webhook downtime; the canonical “tell me when it finishes” channel is a webhook.
Billing
Each task consumes credits from your subscription when it is created. A request without an active subscription or with insufficient credits is refused with 402 payment_required and nothing is queued. A task that fails to dispatch is marked failed and refunded.