Docs · v1

Product-in-Hand

Generate Product-in-Hand videos from a product image and either a script or a voice URL. Choose a model route, then poll a shared status endpoint.

POST/product-in-hand/nova-v2/generate

Audio duration max 90 seconds. Cost: 100 per generation.

Parameters

Name Required Description
image_url Yes Product or subject image URL
script If no voice_url TTS script
voice_url No Direct audio URL; skips TTS
voice_id If no voice_url Voice actor id
project_id No Existing project id
webhook_url No Status callback URL
cURL bash
curl -X POST "https://app.makeugc.ai/api/platform/product-in-hand/nova-v2/generate" \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "image_url": "https://cdn.example.com/product.png",
    "script": "Hold the bottle toward the camera.",
    "voice_id": "voice_123"
  }'
JavaScript javascript
const response = await fetch("https://app.makeugc.ai/api/platform/product-in-hand/nova-v2/generate", {
  method: "POST",
  headers: {
    "X-Api-Key": process.env.MAKEUGC_API_KEY,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    image_url: "https://cdn.example.com/product.png",
    script: "Hold the bottle toward the camera.",
    voice_id: "voice_123",
  }),
});
Python python
import os
import requests

response = requests.post(
    "https://app.makeugc.ai/api/platform/product-in-hand/nova-v2/generate",
    headers={"X-Api-Key": os.environ["MAKEUGC_API_KEY"]},
    json={
        "image_url": "https://cdn.example.com/product.png",
        "script": "Hold the bottle toward the camera.",
        "voice_id": "voice_123",
    },
)

200 response

JSON json
{
  "status": true,
  "message": "Video generation started",
  "data": { "id": "video_123" }
}

POST/product-in-hand/omi-human/generate

Same payload shape as Nova V2. Audio max 30 seconds. Credits: under 15s 100; 15–30s 200.

Parameters

image_url is required, plus either voice_url or script. webhook_url is supported.

Request body

JSON json
{
  "image_url": "https://cdn.example.com/product.png",
  "script": "Hold the bottle toward the camera.",
  "voice_id": "voice_123",
  "webhook_url": "https://example.com/webhooks/makeugc"
}

POST/product-in-hand/veo/generate

Credits: scenes.length × (100 fast or 200 pro).

Parameters

Name Required Description
image_url Yes Thumbnail / first-frame URL
scenes Yes Array of 1–4 objects with script and description
model No pro or fast
voice_id No TTS voice id
end_image_url No Target ending frame
project_id No Project id
webhook_url No Status callback URL

Request body

JSON json
{
  "image_url": "https://cdn.example.com/frame.png",
  "model": "fast",
  "scenes": [
    { "script": "Hook line", "description": "Product hero, handheld" }
  ],
  "webhook_url": "https://example.com/webhooks/makeugc"
}

GET/product-in-hand/status

Parameters

Name In Required
id query Yes

Completed response

JSON json
{
  "status": true,
  "message": "Video is completed",
  "data": {
    "status": "completed",
    "url": "https://cloudfront.net/signed-url.mp4"
  }
}

Failed response

JSON json
{
  "status": true,
  "message": "Video is failed",
  "data": {
    "status": "failed",
    "reason": "Request timeout due to high load"
  }
}

Questions

Which Product-in-Hand model should I call?

Nova V2 supports up to 90 seconds of audio at a flat credit cost. Omi-Human is capped at 30 seconds with duration-based credits. Veo takes 1–4 scenes and prices by scene count and pro/fast.

How do I poll Product-in-Hand jobs?

All three generate routes return an id. Poll GET /product-in-hand/status?id={video_id} until data.status is completed, processing, or failed.