Skip to main content

Authentication

All webhooks are sent with a signature in the X-Mosaic-Signature header when you have a webhook secret configured. The signature is your webhook secret sent as a plaintext string for simple validation. Important: This is NOT encryption or hashing - it’s a direct plaintext string comparison for authentication.

Signature Validation Example

# Simple plaintext validation
webhook_signature = request.headers.get('X-Mosaic-Signature')
expected_secret = os.environ.get('MOSAIC_WEBHOOK_SECRET')

if expected_secret and webhook_signature != expected_secret:
    return {"error": "Invalid webhook signature"}, 401

Webhook Types

Mosaic sends three types of webhooks:
  1. RUN_STARTED - Sent when an agent run begins processing
  2. RUN_PROGRESS - Sent when one or more agent nodes change status
  3. RUN_FINISHED - Sent when an agent run completes (successfully or with failures)

RUN_STARTED

Sent immediately when an agent run begins processing. This webhook includes information about all input videos being processed.

Payload Structure

{
  "flag": "RUN_STARTED",
  "agent_id": "123e4567-e89b-12d3-a456-789012345678",
  "run_id": "7f8d9c2b-4a6e-8b3f-1d5c-9e2f3a4b5c6d",
  "status": "running",
  "inputs": [
    {
      "video_url": "https://storage.googleapis.com/.../input.mp4",
      "thumbnail_url": "https://storage.googleapis.com/.../input-thumb.jpg"
    }
  ],
  "node_status_counts": {
    "completed": 1,
    "in_progress": 5,
    "failed": 0
  },
  "triggered_by": {
    "type": "youtube",
    "channel_id": "UCxxxxxxxxxxxxxx",
    "video_id": "dQw4w9WgXcQ",
    "video_title": "Never Gonna Give You Up",
    "video_url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
    "triggered_at": "2024-01-15T10:30:00Z",
    "trigger_id": "8f7d6c5b-4a3e-2b1f-9d8c-1a2b3c4d5e6f"
  }
}

Field Descriptions

FieldTypeDescription
flag"RUN_STARTED"Webhook type identifier
agent_idstringUUID of the agent being executed
run_idstringUUID of the agent run (same as agent_state_id)
status"running"Current status of the run
inputsVideoInput[]Array of input videos being processed
node_status_countsNodeStatusCountsCounts of nodes in different statuses
triggered_byTriggerInfoOptional information about what triggered this run

RUN_PROGRESS

Sent when one or more agent nodes change status. This webhook is useful for updating UI progress bars or timelines without polling.

Payload Structure

{
  "flag": "RUN_PROGRESS",
  "agent_id": "123e4567-e89b-12d3-a456-789012345678",
  "run_id": "7f8d9c2b-4a6e-8b3f-1d5c-9e2f3a4b5c6d",
  "status": "running",
  "node_status_counts": {
    "completed": 4,
    "in_progress": 3,
    "failed": 0
  },
  "updated_nodes": [
    {
      "original_node_id": "2ba7b810-9dad-11d1-80b4-00c04fd430c8",
      "status": "completed",
      "status_message": null
    }
  ],
  "triggered_by": {
    "type": "youtube",
    "channel_id": "UCxxxxxxxxxxxxxx",
    "video_id": "dQw4w9WgXcQ",
    "video_title": "Never Gonna Give You Up",
    "video_url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
    "triggered_at": "2024-01-15T10:30:00Z",
    "trigger_id": "8f7d6c5b-4a3e-2b1f-9d8c-1a2b3c4d5e6f"
  }
}

Field Descriptions

FieldTypeDescription
flag"RUN_PROGRESS"Webhook type identifier
agent_idstringUUID of the agent being executed
run_idstringUUID of the agent run (same as agent_state_id)
status"running"Current status of the run
node_status_countsNodeStatusCountsCounts of nodes in different statuses
updated_nodesUpdatedNode[]Optional list of nodes that changed status in this batch
triggered_byTriggerInfoOptional information about what triggered this run

UpdatedNode Structure

FieldTypeDescription
original_node_idstring | nullTemplate agent_node_id this runtime node was cloned from. Use this to map progress updates back to specific nodes in your agent.
statusstringCurrent status of the node (completed, partial_complete, failed, blocked, running, queued)
status_messagestring | nullOptional human-readable status message

RUN_FINISHED

Sent when an agent run completes processing (successfully or with failures). This webhook includes all final outputs produced by the run.

Payload Structure

{
  "flag": "RUN_FINISHED",
  "agent_id": "123e4567-e89b-12d3-a456-789012345678",
  "run_id": "7f8d9c2b-4a6e-8b3f-1d5c-9e2f3a4b5c6d",
  "status": "completed",
  "status_message": null,
  "inputs": [
    {
      "video_url": "https://storage.googleapis.com/.../input.mp4",
      "thumbnail_url": "https://storage.googleapis.com/.../input-thumb.jpg"
    }
  ],
  "outputs": [
    {
      "id": "7ba7b810-9dad-11d1-80b4-00c04fd430c8",
      "video_url": "https://storage.googleapis.com/.../output.mp4",
      "thumbnail_url": "https://storage.googleapis.com/.../thumb.jpg",
      "completed_at": "2024-01-15T10:35:00Z",
      "original_node_id": "2ba7b810-9dad-11d1-80b4-00c04fd430c8"
    }
  ],
  "node_status_counts": {
    "completed": 10,
    "in_progress": 0,
    "failed": 0
  },
  "triggered_by": {
    "type": "youtube",
    "channel_id": "UCxxxxxxxxxxxxxx",
    "video_id": "dQw4w9WgXcQ",
    "video_title": "Never Gonna Give You Up",
    "video_url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
    "triggered_at": "2024-01-15T10:30:00Z",
    "trigger_id": "8f7d6c5b-4a3e-2b1f-9d8c-1a2b3c4d5e6f"
  }
}

Field Descriptions

FieldTypeDescription
flag"RUN_FINISHED"Webhook type identifier
agent_idstringUUID of the agent that was executed
run_idstringUUID of the agent run (same as agent_state_id)
status"completed" | "partial_complete" | "failed"Final status of the run
status_messagestring | nullOptional human-readable message about the run status
inputsVideoInput[]Array of input videos that were processed
outputsVideoOutput[]Array of final output videos produced by the run
node_status_countsNodeStatusCountsCounts of nodes in different statuses
triggered_byTriggerInfoOptional information about what triggered this run

VideoOutput Structure

FieldTypeDescription
idstringUnique identifier for this output render. Use this to reference specific outputs in subsequent API calls.
video_urlstringSigned URL to download the rendered video (valid for 7 days)
thumbnail_urlstring | nullSigned URL to download the video thumbnail (valid for 7 days)
completed_atstringISO 8601 timestamp when this output finished rendering
original_node_idstring | nullTemplate agent_node_id this output originated from. Use this to map outputs back to specific nodes in your agent.
Tracking outputs across runs: Use original_node_id to reliably identify which node in your agent template produced each output. This allows you to consistently map outputs to your application logic even as the internal runtime node IDs change between runs.

Common Types

VideoInput Structure

FieldTypeDescription
video_urlstring | nullSigned URL to access the input video file
thumbnail_urlstring | nullSigned URL to access the input video thumbnail

NodeStatusCounts Structure

FieldTypeDescription
completedintegerNumber of nodes that finished successfully (status: "completed", "partial_complete")
in_progressintegerNumber of nodes currently processing or waiting (status: "running", "queued")
failedintegerNumber of nodes that failed or are blocked (status: "failed", "blocked")

TriggerInfo Types

Depending on what initiated the run, triggered_by will have one of the following structures:

YouTube Trigger

{
  "type": "youtube",
  "channel_id": "UCxxxxxxxxxxxxxx",
  "video_id": "dQw4w9WgXcQ",
  "video_title": "Video Title",
  "video_url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
  "triggered_at": "2024-01-15T10:30:00Z",
  "trigger_id": "8f7d6c5b-4a3e-2b1f-9d8c-1a2b3c4d5e6f"
}
FieldTypeDescription
type"youtube"Trigger type identifier
channel_idstring | nullYouTube channel ID that triggered the run (may be null for manual API runs)
video_idstringYouTube video ID that triggered the run
video_titlestringTitle of the YouTube video
video_urlstringFull YouTube URL of the video
triggered_atstringISO 8601 timestamp when the trigger fired
trigger_idstring | nullInternal trigger configuration ID (null for manual/API YouTube runs)

Schedule Trigger

{
  "type": "schedule",
  "scheduled_at": "2024-01-15T10:30:00Z",
  "schedule_id": "8f7d6c5b-4a3e-2b1f-9d8c-1a2b3c4d5e6f",
  "cron_expression": "0 9 * * 1"
}
FieldTypeDescription
type"schedule"Trigger type identifier
scheduled_atstringISO 8601 timestamp when run was scheduled
schedule_idstringInternal schedule configuration ID
cron_expressionstring | nullCron expression if applicable

Manual Trigger

{
  "type": "manual",
  "source": "api",
  "user_id": "user-uuid",
  "triggered_at": "2024-01-15T10:30:00Z"
}
FieldTypeDescription
type"manual"Trigger type identifier
source"api" | "ui"Whether triggered via API or UI
user_idstringID of user who triggered the run
triggered_atstringISO 8601 timestamp when the trigger fired

Notes

If a run is initiated manually via POST /agent/[agent_id]/run using a YouTube URL, triggered_by.type will still be "youtube", but trigger_id will be null because there is no saved channel-trigger configuration associated with the run.
In rare cases, triggered_by.channel_id may be null for manual YouTube runs if channel metadata is unavailable at run creation time. The webhook will still include video_id, video_title, and video_url.

Status Values

The status field in RUN_FINISHED can have the following values:
  • "completed" - All videos processed successfully with outputs generated
  • "partial_complete" - Some videos processed successfully, but others failed
  • "failed" - The entire run failed, no outputs generated
The node status field in UpdatedNode can have these values:
  • "completed" - Node finished successfully
  • "partial_complete" - Node partially completed (some outputs succeeded)
  • "running" - Node is currently processing
  • "queued" - Node is waiting to be processed
  • "failed" - Node failed with an error
  • "blocked" - Node is blocked by an upstream failure