The MakeUGC Platform API allows partners to programmatically generate AI-powered videos using our platform. This documentation provides details on authentication, endpoints, and usage examples.
All API requests require authentication using an API key. Include your API key in the request headers:
X-Api-Key: YOUR_API_KEY
https://app.makeugc.ai/api/platform
Using Claude Code / Claude Desktop? See
§9 Connect MakeUGC MCP
(https://mcp.makeugc.ai).
Seedance 2.0 / 2.5 — models, generation, and status
Retrieve a list of available avatars (both template and custom).
GET /video/avatars
gender: Filter avatars by gender (optional) - "Male" or "Female"{
"status": true,
"message": "Avatars fetched",
"data": [
{
"id": "avatar_123",
"name": "Avatar Name",
"thumbnail": "https://...",
"gender": "Male"
}
]
}
Retrieve a list of available voices (template voices and the current user's custom voices).
GET /video/voices
language: Filter by language (optional)gender: Filter voices by gender (optional) - e.g. "Male" or "Female"{
"status": true,
"message": "Voices fetched",
"data": [
{
"id": "voice_123",
"name": "Voice Name",
"language": "English",
"gender": "Female",
"templateUrl": "https://...",
"thumbnail": "https://...",
"voiceId": "internal_tts_voice_id",
"accent": "US",
"country": "United States",
"isCustom": false
}
]
}
Creates a new AI video with specified avatar and voice script.
POST /video/generate
{
"avatar_id": "string", // Required: ID of the avatar to use
"voice_script": "string", // Required: Script for the voice (max 1500 chars)
"video_name": "string", // Optional: Custom name for the video (defaults to "API Generated Video")
"voice_url": "string", // Optional: URL to existing audio (if provided, skip voice generation; max duration 120s)
"voice_id": "string", // Optional: ID Voice actor, if not provide -> using voice default of avatar template
"voice_settings": { // Optional: Voice generation settings
"stability": 0.75, // Range: 0-1
"similarity_boost": 0.4, // Range: 0-1
"style": 0, // Range: 0-1
"use_speaker_boost": true
},
"webhook_url": "string" // Optional: Webhook URL for status callbacks
}
Audio source priority: voice_url → voice_id → avatar default voice. If voice_url is invalid/inaccessible or duration is greater than 120 seconds, the request is rejected.
{
"status": true,
"message": "Video generation started",
"data": {
"id": "video_123" // Use this ID to check video status
}
}
Check the status of a video generation request.
GET /video/status
id: Video ID (required){
"status": true,
"message": "Video is processing",
"data": {
"status": "processing" | "completed" | "failed",
"url": "https://..." // Present when status is "completed"
}
}
Create a custom avatar from an image and optional voice sample. Uses multipart/form-data.
POST /custom-avatar/generate
image (required) — Image file (max 10MB) or URL string
voice (optional) — Voice audio file (max 10MB) or URL string
Input flexibility: Both image and voice accept either a direct file upload or a publicly accessible URL string. Files are uploaded to S3 automatically.
{
"status": true,
"data": {
"status": true,
"message": "Custom avatar created",
"avatar_id": "avatar_456",
"thumbnail_url": "https://...",
"audio_url": "https://...",
"selected_voice_id": "voice_789"
}
}
avatar_id with the Video Generation endpoint to generate videos with your custom avatarGenerate Product-in-Hand videos dynamically using different models.
POST /product-in-hand/nova-v2/generate
Model limits: Audio duration max 90 seconds.
{
"image_url": "string", // Required: Image URL of the product/subject
"script": "string", // Required (if voice_url missing): Script for TTS
"voice_url": "string", // Optional: Direct audio URL (skips TTS generation)
"voice_id": "string", // Required (if voice_url missing): Voice actor ID
"project_id": "string", // Optional: Project ID
"webhook_url": "string" // Optional: Webhook URL for status callbacks
}
{
"status": true,
"message": "Video generation started",
"data": { "id": "video_123" }
}
Credits: 1 credit per generation.
POST /product-in-hand/omi-human/generate
Model limits: Audio duration max 30 seconds.
// Same as Nova V2 payload.
// image_url is required, along with either voice_url OR script.
// webhook_url is also supported.
Credits (Dynamic pricing):
< 15s : 1 credit
15s - 30s : 2 credits
POST /product-in-hand/veo/generate
{
"image_url": "string", // Required: Video thumbnail/first-frame URL
"project_id": "string", // Optional: Project ID
"model": "string", // Optional: "pro" or "fast"
"voice_id": "string", // Optional: TTS Voice ID
"end_image_url": "string", // Optional: Target ending frame URL
"scenes": [ // Required: Array (1-4 scenes)
{
"script": "string",
"description": "string"
}
],
"webhook_url": "string" // Optional: Webhook URL for status callbacks
}
Credits: scenes.length * (model === 'pro' ? 2 : 1)
GET /product-in-hand/status?id={video_id}
Retrieve the status of a generated PIH video.
{
"status": true,
"message": "Video is processing",
"data": { "status": "processing" }
}
{
"status": true,
"message": "Video is completed",
"data": {
"status": "completed",
"url": "https://cloudfront.net/signed-url.mp4"
}
}
{
"status": true,
"message": "Video is failed",
"data": {
"status": "failed",
"reason": "Request timeout due to high load"
}
}
Async product image/video generation optimized for Shopify. Upstream worker docs: /api/platform/shopable/ShoppableAPI.md.
GET /shopable/packs
Categories, allowed formats, and defaults.
POST /shopable/images
{
"category": "general",
"format": "kinetic_start_frame",
"context": "premium clean tone, product hero",
"image_url": "https://cdn.example.com/product.png",
"aspect_ratio": "9:16"
}
Poll: GET /shopable/images/status?id={id}
POST /shopable/videos
{
"category": "general",
"format": "kinetic_packshot",
"context": "premium product motion, clean CTA",
"image_urls": ["https://cdn.example.com/product.png"],
"duration": "7",
"aspect_ratio": "9:16"
}
Poll: GET /shopable/videos/status?id={id}
Normalized status matches Product-in-Hand (processing / completed / failed + url).
Generate videos from pre-built Content Library templates. List templates to discover required fields, then generate and poll by db_id.
GET /content-library/templates
category — Filter by category (default: all). Returns all matching templates.{
"status": true,
"message": "Templates retrieved successfully",
"data": [
{
"id": "template_uuid",
"title": "Template title",
"description": "...",
"credit": "1",
"preview_url": "https://...",
"category": ["hook", "ugc"],
"require_fields": {
"product_name": { "type": "input", "label": "Product name" },
"product_image": { "type": "image", "label": "Product image" },
"script": { "type": "textarea", "label": "Script", "max": 400 }
}
}
]
}
GET /content-library/categories
{
"status": true,
"message": "Categories retrieved successfully",
"data": [
{ "label": "All", "value": "all" },
{ "label": "hook", "value": "hook" }
]
}
POST /content-library/generate
Start a video generation job from a template. Dynamic body fields must match require_fields from the list templates response.
{
"template_id": "string", // Required: Template UUID from list templates
"project_id": "string", // Optional: Auto-creates a project if omitted
"webhook_url": "string", // Optional: HTTPS URL for terminal job callbacks (see Webhook Callback)
"product_name": "string", // Example dynamic field (input)
"product_image": "string", // Example dynamic field (image) — must be public https URL
"script": "string" // Example dynamic field (textarea)
}
Notes:
require_fields for the template are required.image type fields must be valid http:// or https:// URLs (no file upload on this API).credit value.webhook_url is set, you may receive a terminal callback in addition to polling GET /content-library/status.{
"status": true,
"message": "Video generation started",
"data": { "db_id": "uuid" }
}
When webhook_url is provided on generate, your endpoint receives an HTTP POST with Content-Type: application/json when the job reaches a terminal state. Use polling if you need a guaranteed delivery or miss a callback.
video_id in the payload corresponds to the db_id returned from generate.
{
"event": "video2video.job.terminal",
"job_id": "550e8400-e29b-41d4-a716-446655440000",
"video_id": "660e8400-e29b-41d4-a716-446655440001",
"status": "completed",
"user_id": "user_123",
"project_id": "proj_456",
"template_id": "tpl_789",
"template_type": "hook",
"pipeline_id": "hook_default",
"video_url": "https://s3.amazonaws.com/.../final.mp4",
"thumbnail_url": "https://s3.amazonaws.com/.../thumb.jpg",
"error": null,
"completed_at": "2026-05-28T12:34:56.789123+00:00"
}
{
"event": "video2video.job.terminal",
"job_id": "550e8400-e29b-41d4-a716-446655440000",
"video_id": "660e8400-e29b-41d4-a716-446655440001",
"status": "failed",
"user_id": "user_123",
"project_id": "proj_456",
"template_id": "tpl_789",
"template_type": "hook",
"pipeline_id": "hook_default",
"video_url": null,
"error": "Bootstrap validation failed: missing required field prompt",
"completed_at": "2026-05-28T12:34:56.789123+00:00"
}
{
"status": "timed_out",
"video_url": null,
"error": "Job exceeded watchdog deadline"
}
GET /content-library/status?id={db_id}
Poll generation status using the db_id returned from generate.
{
"status": true,
"message": "Video is processing",
"data": { "db_id": "uuid", "status": "processing" }
}
{
"status": true,
"message": "Video is completed",
"data": {
"db_id": "uuid",
"status": "completed",
"url": "https://signed-url.mp4"
}
}
{
"status": true,
"message": "Video is failed",
"data": {
"db_id": "uuid",
"status": "failed",
"reason": "Video generation failed"
}
}
Generate videos from a text prompt, optionally with image and audio references.
Use your existing Platform X-Api-Key; no browser login is required.
Seedance requires a subscription with sufficient credits and is unavailable on Trial Startup.
| Model | Duration | Resolution | Max images | API credits / second |
|---|---|---|---|---|
seedance-2.0 |
4–15s or -1 (Auto) | 480p, 720p, 1080p, 4k | 9 | 480p: 0.05 720p: 0.11 1080p: 0.25 4k: 0.52 |
seedance-2.0-fast |
4–15s or -1 (Auto) | 480p, 720p | 9 | 480p: 0.04 720p: 0.09 |
seedance-2.5 |
4–30s or -1 (Auto) | 480p, 720p, 1080p | 30 | 480p: 0.07 720p: 0.16 1080p: 0.38 |
Credits are estimated as duration × the resolution rate. Auto (-1) is billed using
15s for 2.0 and 30s for 2.5.
The API returns estimated_credits and, when available, credits_charged.
These endpoints use credits; unlimited-plan generation is not supported.
POST /seedance/generate
Send Content-Type: application/json. Only the fields below are accepted.
model (required): one of the model IDs above.prompt (required): non-empty text, at most 15,000 Unicode characters.project_id (optional): an existing project owned by your API-key account.
If omitted, a project is created automatically.duration (optional, default 10): integer seconds within the model's range,
or -1 for Auto. Send a JSON number, not a string.aspect_ratio (optional, default 9:16):
9:16, 16:9, 4:3, 3:4,
1:1, 21:9, or adaptive.resolution (optional, default 720p): a supported resolution for the selected model.generate_audio (optional, default true): whether to generate output audio.image_url (optional): one reference image URL.image_urls (optional): a non-empty array of reference image URLs, up to the model limit.
Use either image_url or image_urls. Images guide the generation;
these are not first/last frame controls.audio_url (optional): one reference audio URL. On 2.0, include at least one image;
on 2.5, audio can be used with just the prompt. Reference audio is trimmed to
15s (2.0) or 30s (2.5).webhook_url (optional): an HTTP(S) notification URL. The status endpoint below
provides the normalized generation result and can also be used alongside notifications.Reference URLs must use HTTP(S) and remain accessible without login during processing.
Upload files first and pass their URLs; base64, asset://, video references, and video editing
are not accepted by this endpoint.
curl -X POST 'https://app.makeugc.ai/api/platform/seedance/generate' \
-H 'X-Api-Key: YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"model": "seedance-2.0",
"prompt": "A cinematic sunrise over a misty mountain lake",
"duration": 10,
"aspect_ratio": "16:9",
"resolution": "720p",
"generate_audio": true
}'
For 2.0 Fast, change model to seedance-2.0-fast.
curl -X POST 'https://app.makeugc.ai/api/platform/seedance/generate' \
-H 'X-Api-Key: YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"model": "seedance-2.5",
"prompt": "Create a product showcase using these references",
"image_urls": ["https://your-cdn.example/product.jpg"],
"audio_url": "https://your-cdn.example/reference.mp3",
"duration": 20,
"resolution": "1080p",
"aspect_ratio": "9:16"
}'
{
"status": true,
"message": "Video generation started",
"data": {
"id": "video-id",
"project_id": "project-id",
"model": "seedance-2.0",
"status": "processing",
"estimated_credits": 1.1,
"credits_charged": 1.1
}
}
Save data.id for polling. A successful POST means the job was accepted,
not that the video is ready. Each POST starts a new job; avoid blindly retrying a submission
after a timeout, which could create a duplicate generation.
GET /seedance/status?id={id}
curl 'https://app.makeugc.ai/api/platform/seedance/status?id=VIDEO_ID' \
-H 'X-Api-Key: YOUR_API_KEY'
Poll every 5–10 seconds until completed or failed.
You can only retrieve Seedance videos owned by your API-key account.
{ "status": true, "message": "Video is processing", "data": { "id": "video-id", "status": "processing" } }
{ "status": true, "message": "Video is completed", "data": { "id": "video-id", "status": "completed", "url": "https://cdn.example/video.mp4" } }
url may be null if the output is not yet available; poll again to retrieve it.
{ "status": true, "message": "Video is failed", "data": { "id": "video-id", "status": "failed", "reason": "Video generation failed" } }
The outer status indicates that the API request succeeded;
data.status indicates the generation outcome.
Errors use { "status": false, "message": "..." }.
Validation errors also contain an errors array with field paths.
400: invalid JSON, unsupported model/parameters, or invalid reference inputs.401: missing, invalid, or inactive API key.402: insufficient credits; the preflight response includes data.required_credits.403: subscription or generation access denied.404: project/video not found, deleted, or owned by another account.422: generation service rejected the input.429: generation limit reached.500: internal error or service configuration missing.502: generation service unreachable or returned an invalid response.503: model under maintenance or temporarily unavailable.Include the response's x-request-id header when contacting support.
Use MakeUGC from Claude via the MCP server at
https://mcp.makeugc.ai. You need a Platform API key from
Settings → API Integration and an active subscription.
claude mcp add --transport http makeugc https://mcp.makeugc.ai \
--header "X-API-Key: YOUR_MAKEUGC_API_KEY"
claude mcp list
# In session: /mcp → makeugc should show connected
Put --transport and --header before the server name.
Or use OAuth (no key in config):
claude mcp add --transport http makeugc https://mcp.makeugc.ai
claude mcp login makeugc
# Paste your Platform API key on the consent page → Approve
Prerequisite: a Platform API key from Settings → API Integration.
In Claude Desktop, open your profile menu and click Settings.
On the settings page, open the Connectors tab, then click Add.
Enter connector name MakeUGC and remote MCP server URL
https://mcp.makeugc.ai, then add the connector.
After the connector appears in your list, click Connect.
Paste your MakeUGC Platform API key, then click Approve.
In a chat, open + → Connectors and enable MakeUGC. Ask Claude to list MakeUGC flows or models.
If you prefer not to use Custom Connector, edit
claude_desktop_config.json (Settings → Developer → Edit Config), then fully quit and reopen Desktop:
{
"mcpServers": {
"makeugc": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"https://mcp.makeugc.ai",
"--header",
"X-API-Key:YOUR_MAKEUGC_API_KEY"
]
}
}
}
Do not put a raw "url" field in Desktop config — use Custom Connector or the
mcp-remote config above.
After connecting, ask Claude to list MakeUGC flows or models. In Claude Code, /mcp
should show makeugc as connected with tools available.
/mcp failed — check API key and that your subscription is active./mcp needs authentication — run claude mcp login makeugc (or Authenticate in /mcp).claude mcp add unknown flag — put --transport / --header before the server name.For API support or questions, please contact: