Polling

Poll for tool executions, workflow runs, and project exports.

The VideoGen API exposes poll endpoints for each async surface. Both SDKs ship helpers that loop until a terminal status is reached.

Workflow runs

After POST /v1/workflows/*, poll GET /v1/workflows/runs/{workflowRunId} until status is succeeded, failed, or cancelled, or use pollWorkflowRun / poll_workflow_run. The poll response includes projectId (use for export/remix) and projectUrl (optional app editor link; see Workflows).

import { VideoGen, pollWorkflowRun } from "@videogen/sdk";
const client = new VideoGen({ apiKey: "sk_videogen_live_..." });
const { workflowRunId } = await client.workflows.scriptToVideo({
script:
"Staying hydrated keeps your body and mind running at their best. Drinking enough water boosts your energy, focus, and mood. Keep a water bottle nearby and sip throughout the day.",
visualStyle: {
type: "AI_IMAGE",
aiStyle: "loose watercolor illustration with visible brushstrokes and soft color bleeds",
},
quality: "HIGH",
remixActions: [
{ type: "ENABLE_CAPTIONS" },
{ type: "SET_BACKGROUND_MUSIC", fileId: "vg_file_...", volume: 0.25 },
],
});
const run = await pollWorkflowRun({ client, workflowRunId });
console.log(run.status, run.projectId);

Tool executions

Poll GET /v1/tools/executions/{toolExecutionId} until the status is succeeded, failed, or cancelled, or use pollExecutedTool / poll_executed_tool:

import { pollExecutedTool } from "@videogen/sdk";
const { toolExecutionId } = await client.tools.generateImage({
prompt: "A mountain at sunrise",
});
const response = await pollExecutedTool({ client, toolExecutionId });
if (response.status === "succeeded") {
console.log("File id:", response.results[0].fileId);
}

The helper polls every 1.5 seconds (configurable via pollIntervalMs / poll_interval_ms) and returns once a terminal status is reached. Under the hood it’s a simple loop:

async function pollExecutedTool(
client: Pick<VideoGen, "tools">,
toolExecutionId: string,
options?: { pollIntervalMs?: number; signal?: AbortSignal },
): Promise<ExecutedTool> {
const pollIntervalMs = options?.pollIntervalMs ?? 1500;
while (true) {
options?.signal?.throwIfAborted();
const executed = await client.tools.getToolExecutionInfo({ toolExecutionId });
if (["succeeded", "failed", "cancelled"].includes(executed.status)) {
return executed;
}
await new Promise((r) => setTimeout(r, pollIntervalMs));
}
}

When to use polling: good for scripts, CLI tools, or any situation where you can block and wait. For production systems, consider using webhooks instead.

Public preview

After POST /v1/files/{fileId}/enable-public-preview, poll GET /v1/files/{fileId} until staticPublicPreviewSource.url is ready (and publicPlaybackId for video/audio embeds), or use pollPublicPreview / poll_public_preview:

pollPublicPreview throws if isPublicPreviewEnabled is false — call enablePublicPreview first. Use waitForEmbedPlaybackId: false (or wait_for_embed_playback_id=False) when you only need the permanent direct URL (e.g. images).

Project exports

After POST /v1/projects/{projectId}/export, poll GET /v1/projects/{projectId}/exports/{exportId} until status is succeeded, failed, or cancelled, or use pollProjectExport / poll_project_export. Subscribe to project_export.succeeded, project_export.failed, and project_export.cancelled for push notifications.

Each response includes progressPercentage (0-100) for the current attempt, so you can render a live progress bar while the export runs. It is always 100 once status is succeeded.