Skip to main content
The Sales Email Video Flow converts a sales-call summary into a short follow-up video featuring an AI-generated script, voice narration, and avatar render. Flows run asynchronously through a sequence of states. Base URL: https://app.yuzulabs.io/api/v1 All endpoints require Bearer authentication and a workspace with at least one ready avatar, a configured voice, and remaining quota.

Lifecycle

pending → generating_script → [pending_approval] → segmenting → voice_generating → video_generating → completed
StatusDescription
pendingFlow accepted, queued.
generating_scriptDrafting the video script.
pending_approvalAwaiting a human approve / edit / reject (only when autoApproveScript: false).
segmentingBreaking the script into scenes.
voice_generatingProducing the voiceover.
video_generatingRendering the avatar + scenes.
completedvideoUrl available.
failedPermanent error — see error.
cancelledCancelled by user or timeout.

Endpoint summary

MethodPathScope
POST/v1/flows/sales-email-videoflows:create
GET/v1/flows/sales-email-videoflows:read
GET/v1/flows/sales-email-video/{flowId}flows:read
POST/v1/flows/sales-email-video/{flowId}/approveflows:approve
DELETE/v1/flows/sales-email-video/{flowId}flows:cancel

POST Create flow

POST /v1/flows/sales-email-video Creates a flow and starts script generation. The response returns immediately with a flowId you can poll.

Body parameters

emailContent
string
required
Sales-call summary in plain text. Minimum 50 words. Becomes the input for script generation.
autoApproveScript
boolean
default:"true"
When true, the flow proceeds straight from generating_script to segmenting. When false, it stops at pending_approval until you call the /approve endpoint.
avatarId
string
Convex ID of the avatar to render. Defaults to the first ready 16:9 avatar in your workspace.
voiceId
string
ElevenLabs voice ID. Defaults to the workspace’s configured voice.
prospectName
string
Prospect’s first name. Used in the script’s greeting.
prospectCompany
string
Prospect’s company name.
userName
string
Sender’s name. Defaults to the API key’s owner.
userCompany
string
Sender’s company. Defaults to the workspace name.
title
string
Video title shown in the dashboard. Auto-generated from the prospect name when omitted.

Response

success
boolean
required
true on accepted requests.
flowId
string
required
Convex ID. Use this to poll status, approve, or cancel.
status
string
required
Always pending for newly created flows.
message
string
Human-readable confirmation.
curl -X POST https://app.yuzulabs.io/api/v1/flows/sales-email-video \
  -H "Authorization: Bearer yzlk_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "emailContent": "Great call with John from Acme Corp today. We discussed video marketing pain points: production time, brand consistency, scaling content. Next step: send a product demo.",
    "autoApproveScript": true,
    "prospectName": "John",
    "prospectCompany": "Acme Corp"
  }'
{
  "success": true,
  "flowId": "k97x3n2m4p5q6r7s",
  "status": "pending",
  "message": "Flow created successfully"
}

GET List flows

GET /v1/flows/sales-email-video Returns flows visible to the API key, most recent first. Useful for dashboards and reconciliation jobs.

Query parameters

limit
number
default:"20"
Page size. Maximum 100.
cursor
string
Continuation cursor from a previous response.
status
string
Filter by a single status (e.g. completed, pending_approval).

Response

success
boolean
required
flows
object[]
required
Array of flow summaries. Each entry contains flowId, status, createdAt, title, and videoUrl (when completed).
nextCursor
string
Present when more results are available.
curl "https://app.yuzulabs.io/api/v1/flows/sales-email-video?limit=20&status=completed" \
  -H "Authorization: Bearer yzlk_your_api_key_here"
{
  "success": true,
  "flows": [
    {
      "flowId": "k97x3n2m4p5q6r7s",
      "status": "completed",
      "createdAt": "2026-01-22T10:30:00Z",
      "title": "Acme Corp follow-up",
      "videoUrl": "https://assets.yuzulabs.io/videos/k97x3n2m4p5q6r7s.mp4"
    }
  ],
  "nextCursor": null
}

GET Get flow

GET /v1/flows/sales-email-video/{flowId} Returns the current status of a single flow. Poll this every few seconds while the flow is in progress.

Path parameters

flowId
string
required
The flow ID returned from the create endpoint.

Response

flowId
string
required
status
string
required
One of the lifecycle states above.
createdAt
string
required
ISO-8601 timestamp.
completedAt
string
ISO-8601 timestamp. Only present once status is completed.
videoUrl
string
Direct CDN URL to the rendered MP4. Only present once status is completed.
videoDuration
number
Duration in seconds.
generatedScript
string
Final script. Available from pending_approval onwards.
scenes
object[]
Per-scene breakdown: index, text, durationEstimate. Available from segmenting onwards.
error
string
Failure reason. Only present when status is failed.
curl https://app.yuzulabs.io/api/v1/flows/sales-email-video/k97x3n2m4p5q6r7s \
  -H "Authorization: Bearer yzlk_your_api_key_here"
{
  "flowId": "k97x3n2m4p5q6r7s",
  "status": "completed",
  "createdAt": "2026-01-22T10:30:00Z",
  "completedAt": "2026-01-22T10:38:00Z",
  "videoUrl": "https://assets.yuzulabs.io/videos/k97x3n2m4p5q6r7s.mp4",
  "videoDuration": 65.2,
  "generatedScript": "Hey John, great speaking with you today...",
  "scenes": [
    { "index": 0, "text": "Hey John...", "durationEstimate": 12.5 },
    { "index": 1, "text": "I understand you're facing...", "durationEstimate": 15.0 }
  ]
}

POST Approve, edit, or reject script

POST /v1/flows/sales-email-video/{flowId}/approve Only valid while the flow is in pending_approval. Use it to advance, edit, or kill a draft script.

Path parameters

flowId
string
required

Body parameters

action
string
required
Either "approve" or "reject".
editedScript
string
Replacement script. Honored only when action: "approve". If omitted, the draft script proceeds unchanged.

Response

success
boolean
required
flowId
string
required
status
string
required
After approval, transitions to segmenting. After rejection, transitions to cancelled.
curl -X POST https://app.yuzulabs.io/api/v1/flows/sales-email-video/k97x3n2m4p5q6r7s/approve \
  -H "Authorization: Bearer yzlk_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{"action": "approve"}'
{
  "success": true,
  "flowId": "k97x3n2m4p5q6r7s",
  "status": "segmenting"
}

DELETE Cancel flow

DELETE /v1/flows/sales-email-video/{flowId} Cancels a flow in any non-terminal state. Already-rendered videos are kept; in-flight rendering is aborted.

Path parameters

flowId
string
required

Response

success
boolean
required
flowId
string
required
status
string
required
Always cancelled on success.
curl -X DELETE https://app.yuzulabs.io/api/v1/flows/sales-email-video/k97x3n2m4p5q6r7s \
  -H "Authorization: Bearer yzlk_your_api_key_here"
{
  "success": true,
  "flowId": "k97x3n2m4p5q6r7s",
  "status": "cancelled"
}