Skip to main content
This document defines the standardized webhook payloads sent by the Mosaic platform. All webhook payloads are strictly typed using Pydantic models for consistency and reliability.

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_FINISHED - Sent when an agent run completes (successfully or with failures)
  3. TEST - Sent when testing your webhook endpoint

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"
    }
  ],
  "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
triggered_byTriggerInfoOptional information about what triggered this run

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",
  "inputs": [
    {
      "video_url": "https://storage.googleapis.com/.../input.mp4",
      "thumbnail_url": "https://storage.googleapis.com/.../input-thumb.jpg"
    }
  ],
  "outputs": [
    {
      "video_url": "https://storage.googleapis.com/.../output.mp4",
      "thumbnail_url": "https://storage.googleapis.com/.../thumb.jpg",
      "completed_at": "2024-01-15T10:35:00Z"
    }
  ],
  "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
inputsVideoInput[]Array of input videos that were processed
outputsVideoOutput[]Array of final output videos produced by the run
triggered_byTriggerInfoOptional information about what triggered this run
Triggered_by in RUN_STARTED and RUN_FINISHED is identical.

Status Values

The status field 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

TEST

Sent when testing your webhook endpoint via the webhook testing API. This webhook helps you verify that your endpoint is working correctly.

Payload Structure

{
  "flag": "TEST",
  "run_id": "test",
  "timestamp": "2024-01-15T10:30:00Z",
  "message": "This is a test webhook from Mosaic",
  "user_id": "fba7b810-9dad-11d1-80b4-00c04fd430c8",
  "test_data": {
    "status": "test",
    "description": "If you received this, your webhook endpoint is working!"
  }
}

Field Descriptions

FieldTypeDescription
flag"TEST"Webhook type identifier
run_id"test"Always “test” for test webhooks
timestampstringISO 8601 timestamp when test was sent
messagestringHuman-readable test message
user_idstringUUID of the user who initiated the test
test_dataobjectAdditional test data

Common Data Types

VideoInput

Input video information included in webhook payloads.
FieldTypeRequiredDescription
video_urlstringSigned URL to access the video file (expires after 1 hour)
thumbnail_urlstringSigned URL to access the video thumbnail

VideoOutput

Output video information included in webhook payloads.
FieldTypeRequiredDescription
video_urlstringSigned URL to download the rendered video (expires after 1 hour)
thumbnail_urlstringSigned URL to download the video thumbnail
completed_atstringISO 8601 timestamp when rendering completed

TriggerInfo

Information about what triggered the agent run. The structure varies by trigger type.

YouTube Trigger

{
  "type": "youtube",
  "channel_id": "UC123456789",
  "video_id": "dQw4w9WgXcQ",
  "video_title": "Amazing Video Title",
  "video_url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
  "triggered_at": "2024-01-15T10:30:00Z",
  "trigger_id": "aba7b810-9dad-11d1-80b4-00c04fd430c8"
}

Schedule Trigger

{
  "type": "schedule",
  "scheduled_at": "2024-01-15T10:30:00Z",
  "schedule_id": "schedule-uuid",
  "cron_expression": "0 10 * * *"
}

Manual Trigger

{
  "type": "manual",
  "source": "api",
  "user_id": "user-uuid",
  "triggered_at": "2024-01-15T10:30:00Z"
}

Webhook Response

Your webhook endpoint should return a JSON response with HTTP status 200-299 to indicate successful receipt. The response format is optional, but we recommend:
{
  "received": true,
  "message": "Webhook processed successfully",
  "processed_at": "2024-01-15T10:30:05Z"
}

Error Handling

  • Webhook delivery will be retried up to 3 times with exponential backoff if your endpoint returns a non-2xx status code
  • Webhooks will timeout after 30 seconds
  • Failed webhooks are logged and can be viewed in your dashboard

Setting Up Webhooks

For Agent Runs

Include the callback_url when starting an agent run:
curl -X POST "https://api.mosaic.so/agent/[agent_id]/run" \
  -H "Authorization: Bearer mk_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "video_ids": ["550e8400-e29b-41d4-a716-446655440000"],
    "callback_url": "https://your-app.com/webhooks/mosaic/abc123xyz"
  }'

For Triggers

Configure webhooks when setting up triggers to be notified of automatic runs:
curl -X POST "https://api.mosaic.so/agent/[agent_id]/triggers/lowest_youtube_id/add_listeners" \
  -H "Authorization: Bearer mk_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "youtube_channels": ["UCxxxxxxxxxxxxxx"],
    "trigger_callback_url": "https://your-app.com/webhooks/triggers/def456uvw"
  }'

TypeScript Types

For TypeScript users, here are the type definitions:
type WebhookFlag = 'RUN_STARTED' | 'RUN_FINISHED' | 'TEST';

interface VideoInput {
  video_url: string;
  thumbnail_url: string;
}

interface VideoOutput {
  video_url: string;
  thumbnail_url: string;
  completed_at: string;
}

interface YouTubeTriggerInfo {
  type: 'youtube';
  channel_id: string;
  video_id: string;
  video_title: string;
  video_url: string;
  triggered_at: string;
  trigger_id: string;
}

interface ScheduleTriggerInfo {
  type: 'schedule';
  scheduled_at: string;
  schedule_id: string;
  cron_expression?: string;
}

interface ManualTriggerInfo {
  type: 'manual';
  source: 'api' | 'ui';
  user_id: string;
  triggered_at: string;
}

type TriggerInfo = YouTubeTriggerInfo | ScheduleTriggerInfo | ManualTriggerInfo;

interface RunStartedWebhook {
  flag: 'RUN_STARTED';
  agent_id: string;
  run_id: string;
  status: 'running';
  inputs: VideoInput[];
  triggered_by?: TriggerInfo;
}

interface RunFinishedWebhook {
  flag: 'RUN_FINISHED';
  agent_id: string;
  run_id: string;
  status: 'completed' | 'partial_complete' | 'failed';
  inputs: VideoInput[];
  outputs: VideoOutput[];
  triggered_by?: TriggerInfo;
}

interface TestWebhook {
  flag: 'TEST';
  run_id: 'test';
  timestamp: string;
  message: string;
  user_id: string;
  test_data: {
    status: 'test';
    description: string;
  };
}

type WebhookPayload = RunStartedWebhook | RunFinishedWebhook | TestWebhook;

Next Steps