UGC — Generation

AI image/video/audio generation via MCP — full flow (media → model → estimate → job → poll), scenes and credit costs.

The ugc_* namespace exposes uPubly's content generation engine: image, video and audio models routed through a provider auction, charged in credits with automatic refund on failure/cancellation.

Full generation flow

  1. Input media (optional) — bring reference images: media_upload_from_url (URL → file_id in one call, public URLs only, max 20MB) or the 2-step presigned path (storage_request_upload → PUT → storage_complete_upload). The returned file_id is the media_id used in refs, avatars and scenes.
  2. Model — ugc_models_list returns model_key + capabilities (aspectRatios, resolutions, durationsSec, acceptsImageRefs, acceptsDrivingVideo, lipsync) + price hint.
  3. Estimate — ugc_estimate with the same input as create: runs the same routing/auction without persisting or charging. The displayed number is the charged number.
  4. Balance — credits_balance checks the user has enough credits.
  5. Job — ugc_job_create DEBITS CREDITS on creation and returns the queued job. Send idempotency_key for safe retries (without one the backend derives it from the payload — retry never double-charges).
  6. Poll — the job is async: ugc_job_get until succeeded or failed. The result lands in resultUrl / resultMediaId — a file_id reusable as a reference in later jobs.
  7. Failure/cancel — failed auto-refunds; ugc_job_cancel cancels and refunds in full.

Catalog & cost

ugc_models_list

{ "output_kind": "image|video|audio (optional filter)" }

→ { "models": [{ "key", "displayName", "outputKind", "brand", "capabilities", "estimatedCreditsPerUnit" }] }

ugc_estimate

{
  "model_key": "seedance-2.0",
  "prompt": "optional when refs are enough",
  "params": { "...": "same schema as ugc_job_create" }
}

→ { "credits", "usdEstimated", "mode", "provider", "fallbackProvider" }

Jobs

ugc_job_create

{
  "model_key": "required (ugc_models_list)",
  "prompt": "optional when refs are enough",
  "idempotency_key": "recommended",
  "params": {
    "duration_sec": 5,
    "aspect_ratio": "9:16|16:9|1:1",
    "resolution": "720p|1080p",
    "image_ref_media_ids": ["media_id — direct visual ref (i2i)"],
    "extra_ref_media_ids": ["media_id — scene/style; with avatar+pose_copy becomes the copied scene"],
    "driving_video_media_id": "media_id of the driving video (motion/lipsync)",
    "avatar_ids": ["avatar_id — identity refs (base+sheets)"],
    "avatar_include_base": true,
    "avatar_sheet_kinds": ["angles", "expressions"],
    "pose_copy": true,
    "voice_id": "voice (audio/lipsync)",
    "timestamps": true,
    "format": "mp4",
    "scene_id": "library scene as background",
    "template_id": "driving template (ugc_templates_list)",
    "project_id": "project to organize (ugc_projects_list)",
    "script_id": "linked script",
    "mentions": [{ "token": "@maria", "kind": "avatar|scene|ref", "id": "..." }],
    "extra": { "provider-specific params": "..." }
  }
}

→ { "job": { "id", "status", "costCredits", "charged", "params", ... }, "replayed": false }

avatar_ids bring the avatar's identity refs (base + current sheets — fine control via avatar_include_base / avatar_sheet_kinds). extra_ref_media_ids with pose_copy: true (default when avatar+extras are present) enable scene recreate mode: the extra image defines pose, framing and setting, with the avatar replacing the person. With pose_copy: false extras are just style context.

ugc_job_get

{ "job_id": "..." }

→ status (queued|running|succeeded|failed|cancelled), costCredits, charged, refunded, errorReason, resultMediaId, resultUrl. Manual polling — repeat until a terminal status.

ugc_jobs_list

{
  "kind": "image|video|audio", "status": "...", "avatar_id": "?",
  "project_id": "?", "page": 0, "size": 20, "ready_for_video": true
}

→ workspace gallery (newest first).

ugc_job_cancel / ugc_job_delete

Cancels a non-terminal job with full refund / removes it from the gallery (an active job is cancelled first — the media_file survives).

{ "job_id": "..." }

Scenes

Scenes are reusable backgrounds — scene_id in job params applies the scene as the background.

ugc_scene_create — three paths

{ "name": "Neon studio", "media_id": "file_id" }

→ Direct upload — the image becomes the scene. Free, no job.

{ "name": "Empty beach", "prompt": "beach at dusk", "model_key": "...", "aspect_ratio": "9:16" }

→ t2i empty environment (the backend instructs "no people" automatically). purpose=scene job — returns job_id to poll.

{ "name": "Copy café", "ref_media_ids": ["file_id"], "prompt": "optional extra direction" }

→ Scene copy (i2i): recreates location, framing, lighting and mood from the refs removing people. Refs alone are enough — prompt is just extra direction.

ugc_scenes_list / ugc_scene_update / ugc_scene_delete

List (a scene with jobId + url: null is still generating), rename and remove (soft delete).

Auxiliaries

media_upload_from_url

{ "url": "https://.../image.png", "file_name": "optional" }

→ { "file_id", "file_url" } in one call. Public http(s) URLs only — private/loopback/link-local IPs are rejected (anti-SSRF), max 20MB.

ugc_templates_list / ugc_projects_list

Templates = ingested driving videos (use id as template_id in video). Projects = job organization (project_id).

Balance

credits_balance

→ { "monthly_balance", "topup_balance", "total_balance", "monthly_allowance", "cycle_ends_at", "plan_name" }

Check before any debiting operation — insufficient credits return isError with the balance message.

See also: Avatars · Video generation · Tools