{
  "openapi": "3.1.0",
  "info": {
    "title": "SimilarClip API",
    "version": "1.0.0",
    "description": "Generate narrated, illustrated videos from a topic or a YouTube link, buy credit, and publish to YouTube. The same operations are available as MCP tools at /mcp. Agent guide: /llms-full.txt"
  },
  "servers": [
    {
      "url": "https://similarclip.com"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "tags": [
    {
      "name": "Account"
    },
    {
      "name": "Billing"
    },
    {
      "name": "Videos"
    },
    {
      "name": "Scenes"
    },
    {
      "name": "YouTube"
    },
    {
      "name": "Schedules"
    },
    {
      "name": "Webhooks"
    }
  ],
  "paths": {
    "/api/v1/me": {
      "get": {
        "operationId": "get_account",
        "summary": "Get account",
        "description": "Who the API key belongs to, plan/subscription status, AI credit balance, connected YouTube channels and saved defaults (style, voice, description footer). Call this first to see what the account can do.",
        "tags": [
          "Account"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-mcp-tool": "get_account"
      }
    },
    "/api/v1/options": {
      "get": {
        "operationId": "get_options",
        "summary": "List creative options",
        "description": "Every valid value for create_video and create_schedule: visual style presets (with their art direction), TTS providers and voices, narration vibes, speeds, duration limits and visibilities. Also returns this account's saved defaults.",
        "tags": [
          "Videos"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-mcp-tool": "get_options"
      }
    },
    "/api/v1/billing": {
      "get": {
        "operationId": "get_billing",
        "summary": "Get billing",
        "description": "Credit balance (plan credit + credit packs), the current plan, the purchasable plans (monthly and annual), credit packs and the estimated cost per minute of video. Use it to work out whether a video is affordable before creating it.",
        "tags": [
          "Billing"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-mcp-tool": "get_billing"
      }
    },
    "/api/v1/billing/checkout": {
      "post": {
        "operationId": "create_checkout",
        "summary": "Start a purchase",
        "description": "Start a purchase for the account: a subscription plan (monthly or annual) or a one-time credit pack (needs an active plan). Returns a checkout_url that a HUMAN must open to pay (agents never handle card details). Share the link with your user, wait for them to confirm, then check get_billing.",
        "tags": [
          "Billing"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": [
                      "subscription",
                      "topup"
                    ]
                  },
                  "plan": {
                    "description": "Plan name for type=subscription (see get_billing.plans).",
                    "type": "string"
                  },
                  "annual": {
                    "description": "type=subscription: bill yearly (10 months' price for 12; credit is still granted monthly).",
                    "type": "boolean"
                  },
                  "pack": {
                    "description": "Credit pack for type=topup (see get_billing.credit_packs).",
                    "type": "string",
                    "enum": [
                      "10min",
                      "30min"
                    ]
                  }
                },
                "required": [
                  "type"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-mcp-tool": "create_checkout"
      }
    },
    "/api/v1/videos/estimate": {
      "get": {
        "operationId": "estimate_video_cost",
        "summary": "Estimate video cost",
        "description": "Estimated USD cost of a video of the given length, compared with the current balance. Calibrated from this account's own recent videos when it has at least 3 (else the platform rate), and scaled by seconds_per_image and image_check, since images are most of the cost. Real billing is metered at exact AI cost; get_video.cost_breakdown shows where a finished video's money went.",
        "tags": [
          "Videos"
        ],
        "parameters": [
          {
            "name": "duration_min",
            "in": "query",
            "required": false,
            "schema": {
              "default": 5,
              "type": "number",
              "minimum": 0.25,
              "maximum": 15
            }
          },
          {
            "name": "seconds_per_image",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Planned seconds per image (default 5). More seconds = fewer images = cheaper.",
              "type": "number",
              "minimum": 2,
              "maximum": 15
            },
            "description": "Planned seconds per image (default 5). More seconds = fewer images = cheaper."
          },
          {
            "name": "image_check",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Planned image check setting (default on; off saves ~15%).",
              "type": "boolean"
            },
            "description": "Planned image check setting (default on; off saves ~15%)."
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-mcp-tool": "estimate_video_cost"
      }
    },
    "/api/v1/videos": {
      "post": {
        "operationId": "create_video",
        "summary": "Create a video",
        "description": "Generate a narrated, fully illustrated video. Give EITHER `topic` (SimilarClip researches it, picks an angle and writes an original script) OR `youtube_url` (it reimagines that clip with a fresh script, new visuals and a new voice; the source needs captions). Generation is asynchronous and takes several minutes: poll get_video until status is \"completed\" or \"failed\". Set `publish` to upload to YouTube automatically when done.",
        "tags": [
          "Videos"
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "topic": {
                    "description": "What the video is about, e.g. \"why octopuses have three hearts\".",
                    "type": "string",
                    "maxLength": 500
                  },
                  "youtube_url": {
                    "description": "A YouTube video to reimagine (must have captions).",
                    "type": "string"
                  },
                  "duration_min": {
                    "description": "Target length for topic videos, in minutes.",
                    "type": "integer",
                    "minimum": 3,
                    "maximum": 15
                  },
                  "style": {
                    "description": "Visual style preset (see get_options).",
                    "type": "string",
                    "enum": [
                      "colorful-doodle",
                      "stick-drawing",
                      "storybook",
                      "flat-vector",
                      "anime",
                      "cinematic",
                      "claymation",
                      "comic-book",
                      "pixel-art",
                      "watercolor",
                      "3d-isometric"
                    ]
                  },
                  "custom_style_prompt": {
                    "description": "Free-form art direction; overrides the preset when set.",
                    "type": "string",
                    "maxLength": 2000
                  },
                  "voice": {
                    "type": "object",
                    "properties": {
                      "provider": {
                        "description": "TTS provider. Defaults to the account's saved choice.",
                        "type": "string",
                        "enum": [
                          "xai",
                          "google"
                        ]
                      },
                      "voice": {
                        "description": "Voice id for the provider (see get_options). Invalid voices fall back to the provider default.",
                        "type": "string"
                      },
                      "vibe": {
                        "description": "Narration delivery preset.",
                        "type": "string",
                        "enum": [
                          "storyteller",
                          "professional",
                          "cheerleader",
                          "dramatic",
                          "sincere",
                          "calm"
                        ]
                      },
                      "instructions": {
                        "description": "Custom delivery instructions; overrides the vibe preset's wording.",
                        "type": "string",
                        "maxLength": 1000
                      },
                      "speed": {
                        "description": "Narration playback speed.",
                        "anyOf": [
                          {
                            "type": "number",
                            "const": 1
                          },
                          {
                            "type": "number",
                            "const": 1.25
                          },
                          {
                            "type": "number",
                            "const": 1.5
                          }
                        ]
                      }
                    },
                    "description": "Narration voice. Omitted fields use the account's saved defaults."
                  },
                  "creative": {
                    "type": "object",
                    "properties": {
                      "captions": {
                        "description": "Burned-in captions on or off.",
                        "type": "boolean"
                      },
                      "caption_style": {
                        "description": "word = one short line with the spoken word lit up (short-form style); phrase = classic two-line captions.",
                        "type": "string",
                        "enum": [
                          "word",
                          "phrase"
                        ]
                      },
                      "pop_words": {
                        "description": "Pop each scene's key word/number up on screen, big, the moment it is spoken.",
                        "type": "boolean"
                      },
                      "motion": {
                        "description": "Slow pan or zoom on every image (default on). false = still images.",
                        "type": "boolean"
                      },
                      "seconds_per_image": {
                        "description": "Target seconds each image stays on screen (default 5). Lower = more images = more cost.",
                        "type": "number",
                        "minimum": 2,
                        "maximum": 15
                      },
                      "transition": {
                        "description": "cut = hard cuts with motion on every image (default); crossfade = dissolves; fade = dips to black.",
                        "type": "string",
                        "enum": [
                          "cut",
                          "crossfade",
                          "fade"
                        ]
                      },
                      "music_volume": {
                        "description": "Background music level, 0 (none) to 100. 50 is the standard mix.",
                        "type": "number",
                        "minimum": 0,
                        "maximum": 100
                      },
                      "sound_effects": {
                        "description": "Story sound cues (crowd, rain, splash, crash…) on the words they happen on, plus soft ticks under pop-up words. Image and scene changes are silent.",
                        "type": "boolean"
                      },
                      "hook_style": {
                        "description": "How a topic script opens: cold_open (most shocking moment first, then the setup; default), bold_claim, question, story.",
                        "type": "string",
                        "enum": [
                          "cold_open",
                          "bold_claim",
                          "question",
                          "story"
                        ]
                      },
                      "image_check": {
                        "description": "Vision-check every image and redraw ones with mangled hands/faces, stray text, or a poor match to the line (default on).",
                        "type": "boolean"
                      }
                    },
                    "description": "Creative settings for this video. Omitted fields use the account's settings, then SimilarClip's defaults."
                  },
                  "title": {
                    "description": "Your own YouTube title; wins over the generated one.",
                    "type": "string",
                    "maxLength": 100
                  },
                  "description": {
                    "description": "Your own YouTube description; wins over the generated one.",
                    "type": "string",
                    "maxLength": 5000
                  },
                  "tags": {
                    "description": "Your own YouTube tags.",
                    "maxItems": 30,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "maxLength": 100
                    }
                  },
                  "review_script": {
                    "default": false,
                    "description": "true = stop once the script is written (status script_ready) so you can read, edit and approve it before paying for voice, images and rendering. Cheap way to vet many ideas.",
                    "type": "boolean"
                  },
                  "publish": {
                    "description": "Publish to YouTube automatically when the video completes.",
                    "type": "object",
                    "properties": {
                      "visibility": {
                        "default": "public",
                        "type": "string",
                        "enum": [
                          "public",
                          "unlisted",
                          "private"
                        ]
                      },
                      "description_footer": {
                        "description": "Appended to the YouTube description (links, socials). Omit to use the account's default footer; \"\" for none.",
                        "type": "string",
                        "maxLength": 1000
                      },
                      "channel_id": {
                        "description": "Connected channel to upload to (from list_youtube_channels). Omit for the default channel.",
                        "type": "string"
                      },
                      "contains_synthetic_media": {
                        "default": true,
                        "description": "YouTube's altered/synthetic content disclosure. SimilarClip videos are AI-generated, so keep true.",
                        "type": "boolean"
                      }
                    }
                  },
                  "start": {
                    "default": true,
                    "description": "false = create a draft only; start it later with start_video.",
                    "type": "boolean"
                  },
                  "idempotency_key": {
                    "description": "Any unique string (e.g. a UUID). Retrying with the same key returns the first call's result instead of acting, and charging, twice. REST clients can send an Idempotency-Key header instead.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-mcp-tool": "create_video"
      },
      "get": {
        "operationId": "list_videos",
        "summary": "List videos",
        "description": "The account's videos, newest first. Filter by status to find running or finished ones.",
        "tags": [
          "Videos"
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "draft",
                "queued",
                "processing",
                "script_ready",
                "completed",
                "failed",
                "paused",
                "stopped"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "default": 20,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-mcp-tool": "list_videos"
      }
    },
    "/api/v1/videos/{id}": {
      "get": {
        "operationId": "get_video",
        "summary": "Get a video",
        "description": "Full status of one video: progress, current pipeline step, errors (and whether they are resumable), the downloadable MP4 and thumbnail URLs once completed, generated YouTube SEO metadata, the latest YouTube publication, the resolved creative settings, and `render`: what the last render actually contained (motion, transition, caption style, pop-up word count, music, sound-effect count). Check `render` when a setting seems to have no effect.",
        "tags": [
          "Videos"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Video id."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-mcp-tool": "get_video"
      },
      "delete": {
        "operationId": "delete_video",
        "summary": "Delete a video",
        "description": "Permanently delete a video and its files. Running videos must be stopped first. Already-published YouTube uploads are not touched.",
        "tags": [
          "Videos"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-mcp-tool": "delete_video"
      }
    },
    "/api/v1/videos/{id}/start": {
      "post": {
        "operationId": "start_video",
        "summary": "Start a draft video",
        "description": "Start generating a draft video (one created with start=false, or refused earlier for billing).",
        "tags": [
          "Videos"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-mcp-tool": "start_video"
      }
    },
    "/api/v1/videos/{id}/resume": {
      "post": {
        "operationId": "resume_video",
        "summary": "Resume a video",
        "description": "Resume a paused video, or retry a failed one from the step it stopped at (when error.resumable is true).",
        "tags": [
          "Videos"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-mcp-tool": "resume_video"
      }
    },
    "/api/v1/videos/{id}/pause": {
      "post": {
        "operationId": "pause_video",
        "summary": "Pause a video",
        "description": "Pause a queued or processing video at the next step boundary. Resume later with resume_video.",
        "tags": [
          "Videos"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-mcp-tool": "pause_video"
      }
    },
    "/api/v1/videos/{id}/stop": {
      "post": {
        "operationId": "stop_video",
        "summary": "Stop a video",
        "description": "Stop a running or paused video for good (it cannot be resumed afterwards).",
        "tags": [
          "Videos"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-mcp-tool": "stop_video"
      }
    },
    "/api/v1/videos/{id}/publish": {
      "post": {
        "operationId": "publish_video",
        "summary": "Publish to YouTube",
        "description": "Upload a completed video to one of the account's connected YouTube channels, with the generated thumbnail. Title/description/tags default to the AI-generated SEO metadata. The upload runs in the background: poll get_video and read `publication` for the YouTube URL.",
        "tags": [
          "YouTube"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "visibility": {
                    "default": "public",
                    "type": "string",
                    "enum": [
                      "public",
                      "unlisted",
                      "private"
                    ]
                  },
                  "description_footer": {
                    "description": "Appended to the YouTube description (links, socials). Omit to use the account's default footer; \"\" for none.",
                    "type": "string",
                    "maxLength": 1000
                  },
                  "channel_id": {
                    "description": "Connected channel to upload to (from list_youtube_channels). Omit for the default channel.",
                    "type": "string"
                  },
                  "contains_synthetic_media": {
                    "default": true,
                    "description": "YouTube's altered/synthetic content disclosure. SimilarClip videos are AI-generated, so keep true.",
                    "type": "boolean"
                  },
                  "title": {
                    "type": "string",
                    "maxLength": 100
                  },
                  "description": {
                    "type": "string",
                    "maxLength": 5000
                  },
                  "tags": {
                    "maxItems": 30,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "maxLength": 100
                    }
                  },
                  "idempotency_key": {
                    "description": "Any unique string (e.g. a UUID). Retrying with the same key returns the first call's result instead of acting, and charging, twice. REST clients can send an Idempotency-Key header instead.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-mcp-tool": "publish_video"
      }
    },
    "/api/v1/videos/{id}/script": {
      "get": {
        "operationId": "get_script",
        "summary": "Get the script",
        "description": "The video's script, line by line (one line per scene), with word count and estimated narration length. Use it on a script_ready video before approve_script, or on any video to read what is narrated.",
        "tags": [
          "Videos"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-mcp-tool": "get_script"
      },
      "post": {
        "operationId": "update_script",
        "summary": "Edit the script",
        "description": "Replace the script of a script_ready video. Send every line in order: lines with a scene_id keep that scene (its text replaced), lines without one are new scenes, and scenes you leave out are deleted. To change lines of an already rendered video use edit_scene_line instead.",
        "tags": [
          "Videos"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "lines": {
                    "minItems": 1,
                    "maxItems": 120,
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "scene_id": {
                          "description": "Existing scene to keep (from get_script).",
                          "type": "string"
                        },
                        "text": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 1500,
                          "description": "Narration for this line (1-3 sentences)."
                        }
                      },
                      "required": [
                        "text"
                      ]
                    }
                  }
                },
                "required": [
                  "lines"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-mcp-tool": "update_script"
      }
    },
    "/api/v1/videos/{id}/script/approve": {
      "post": {
        "operationId": "approve_script",
        "summary": "Approve the script",
        "description": "Render a script_ready video: narration, images, captions, music and the final video. This is where most of the cost is spent, so it passes the same credit check as start_video.",
        "tags": [
          "Videos"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-mcp-tool": "approve_script"
      }
    },
    "/api/v1/videos/{id}/scenes": {
      "get": {
        "operationId": "list_scenes",
        "summary": "List scenes and images",
        "description": "Every scene of a video in order: its narration line, timing, and each image (slide) shown during it, with the image URL, the exact words it illustrates, the storyboarded visual it was drawn from, and the image check result (passed, redraws, issues). Also returns the key subjects every image was told to draw accurately. Use the ids with edit_scene_line, regenerate_scene_image and regenerate_slide_image.",
        "tags": [
          "Scenes"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-mcp-tool": "list_scenes"
      }
    },
    "/api/v1/videos/{id}/scenes/{scene_id}": {
      "post": {
        "operationId": "edit_scene_line",
        "summary": "Edit one line",
        "description": "Change one scene's narration on a completed or failed video. Only that line is re-voiced and only its images are redrawn; every other scene, the SEO and the thumbnail are kept, and the video is re-rendered.",
        "tags": [
          "Scenes"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "scene_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "text": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 1500
                  }
                },
                "required": [
                  "text"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-mcp-tool": "edit_scene_line"
      }
    },
    "/api/v1/videos/{id}/scenes/{scene_id}/regenerate-images": {
      "post": {
        "operationId": "regenerate_scene_image",
        "summary": "Redraw a scene's images",
        "description": "Redraw every image of one scene (text and voice untouched), then re-render the video.",
        "tags": [
          "Scenes"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "scene_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-mcp-tool": "regenerate_scene_image"
      }
    },
    "/api/v1/videos/{id}/slides/{slide_id}/regenerate": {
      "post": {
        "operationId": "regenerate_slide_image",
        "summary": "Redraw one image",
        "description": "Redraw a single image (slide) — e.g. one with a mangled hand or a poor match — then re-render the video. Everything else is kept.",
        "tags": [
          "Scenes"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "slide_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-mcp-tool": "regenerate_slide_image"
      }
    },
    "/api/v1/videos/{id}/regenerate-voice": {
      "post": {
        "operationId": "regenerate_voice",
        "summary": "Re-voice the video",
        "description": "Re-narrate a completed or failed video, optionally with a different voice, vibe or speed. Images, SEO and thumbnail are kept; image timing follows the new narration.",
        "tags": [
          "Scenes"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "voice": {
                    "type": "object",
                    "properties": {
                      "provider": {
                        "description": "TTS provider. Defaults to the account's saved choice.",
                        "type": "string",
                        "enum": [
                          "xai",
                          "google"
                        ]
                      },
                      "voice": {
                        "description": "Voice id for the provider (see get_options). Invalid voices fall back to the provider default.",
                        "type": "string"
                      },
                      "vibe": {
                        "description": "Narration delivery preset.",
                        "type": "string",
                        "enum": [
                          "storyteller",
                          "professional",
                          "cheerleader",
                          "dramatic",
                          "sincere",
                          "calm"
                        ]
                      },
                      "instructions": {
                        "description": "Custom delivery instructions; overrides the vibe preset's wording.",
                        "type": "string",
                        "maxLength": 1000
                      },
                      "speed": {
                        "description": "Narration playback speed.",
                        "anyOf": [
                          {
                            "type": "number",
                            "const": 1
                          },
                          {
                            "type": "number",
                            "const": 1.25
                          },
                          {
                            "type": "number",
                            "const": 1.5
                          }
                        ]
                      }
                    },
                    "description": "Narration voice. Omitted fields use the account's saved defaults."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-mcp-tool": "regenerate_voice"
      }
    },
    "/api/v1/videos/{id}/settings": {
      "post": {
        "operationId": "update_video_settings",
        "summary": "Change creative settings",
        "description": "Change a video's creative settings. On a completed or failed video, caption, pop-word, motion, transition, music and sound-effect changes re-render it from the existing images and voice (cheap, no new AI generation). seconds_per_image, hook_style and image_check only affect steps that haven't run yet.",
        "tags": [
          "Videos"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "creative": {
                    "type": "object",
                    "properties": {
                      "captions": {
                        "description": "Burned-in captions on or off.",
                        "type": "boolean"
                      },
                      "caption_style": {
                        "description": "word = one short line with the spoken word lit up (short-form style); phrase = classic two-line captions.",
                        "type": "string",
                        "enum": [
                          "word",
                          "phrase"
                        ]
                      },
                      "pop_words": {
                        "description": "Pop each scene's key word/number up on screen, big, the moment it is spoken.",
                        "type": "boolean"
                      },
                      "motion": {
                        "description": "Slow pan or zoom on every image (default on). false = still images.",
                        "type": "boolean"
                      },
                      "seconds_per_image": {
                        "description": "Target seconds each image stays on screen (default 5). Lower = more images = more cost.",
                        "type": "number",
                        "minimum": 2,
                        "maximum": 15
                      },
                      "transition": {
                        "description": "cut = hard cuts with motion on every image (default); crossfade = dissolves; fade = dips to black.",
                        "type": "string",
                        "enum": [
                          "cut",
                          "crossfade",
                          "fade"
                        ]
                      },
                      "music_volume": {
                        "description": "Background music level, 0 (none) to 100. 50 is the standard mix.",
                        "type": "number",
                        "minimum": 0,
                        "maximum": 100
                      },
                      "sound_effects": {
                        "description": "Story sound cues (crowd, rain, splash, crash…) on the words they happen on, plus soft ticks under pop-up words. Image and scene changes are silent.",
                        "type": "boolean"
                      },
                      "hook_style": {
                        "description": "How a topic script opens: cold_open (most shocking moment first, then the setup; default), bold_claim, question, story.",
                        "type": "string",
                        "enum": [
                          "cold_open",
                          "bold_claim",
                          "question",
                          "story"
                        ]
                      },
                      "image_check": {
                        "description": "Vision-check every image and redraw ones with mangled hands/faces, stray text, or a poor match to the line (default on).",
                        "type": "boolean"
                      }
                    },
                    "description": "Creative settings for this video. Omitted fields use the account's settings, then SimilarClip's defaults."
                  },
                  "rerender": {
                    "default": true,
                    "description": "Re-render a finished video to apply the change.",
                    "type": "boolean"
                  }
                },
                "required": [
                  "creative"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-mcp-tool": "update_video_settings"
      }
    },
    "/api/v1/videos/{id}/metadata": {
      "post": {
        "operationId": "set_video_metadata",
        "summary": "Set title, description and tags",
        "description": "Set your own YouTube title, description, tags and/or thumbnail headline (pick from get_video.seo_options or write your own). Applies now on a finished video and survives any later re-render. Changing thumbnail_headline also redraws the thumbnail.",
        "tags": [
          "YouTube"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "title": {
                    "description": "Your own YouTube title; wins over the generated one.",
                    "type": "string",
                    "maxLength": 100
                  },
                  "description": {
                    "description": "Your own YouTube description; wins over the generated one.",
                    "type": "string",
                    "maxLength": 5000
                  },
                  "tags": {
                    "description": "Your own YouTube tags.",
                    "maxItems": 30,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "maxLength": 100
                    }
                  },
                  "thumbnail_headline": {
                    "description": "2-4 words lettered on the thumbnail.",
                    "type": "string",
                    "maxLength": 40
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-mcp-tool": "set_video_metadata"
      }
    },
    "/api/v1/videos/{id}/thumbnail/regenerate": {
      "post": {
        "operationId": "regenerate_thumbnail",
        "summary": "Redraw the thumbnail",
        "description": "Redraw a completed video's thumbnail, optionally with a new headline (e.g. one of get_video.seo_options.thumbnail_headlines). Call it again for another variant.",
        "tags": [
          "YouTube"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "headline": {
                    "type": "string",
                    "maxLength": 40
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-mcp-tool": "regenerate_thumbnail"
      }
    },
    "/api/v1/youtube/stats": {
      "get": {
        "operationId": "get_video_stats",
        "summary": "Get YouTube performance",
        "description": "Live YouTube views, likes and comments for the account's published videos, next to the settings each was made with (topic, style, voice, vibe, creative settings, length), so you can learn what works. Pass video ids, or omit them for the 50 most recent.",
        "tags": [
          "YouTube"
        ],
        "parameters": [
          {
            "name": "video_ids",
            "in": "query",
            "required": false,
            "schema": {
              "description": "SimilarClip video ids (array, or comma-separated in a query string).",
              "anyOf": [
                {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                },
                {
                  "type": "string"
                }
              ]
            },
            "description": "SimilarClip video ids (array, or comma-separated in a query string)."
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-mcp-tool": "get_video_stats"
      }
    },
    "/api/v1/youtube/channels": {
      "get": {
        "operationId": "list_youtube_channels",
        "summary": "List YouTube channels",
        "description": "The YouTube channels connected to the account for publishing. Connecting a channel needs a human (Google OAuth): if none are connected, give your user the connect_url.",
        "tags": [
          "YouTube"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-mcp-tool": "list_youtube_channels"
      }
    },
    "/api/v1/schedules": {
      "get": {
        "operationId": "list_schedules",
        "summary": "List schedules",
        "description": "Autopilot schedules: each turns a queue of topics into videos on a cadence (daily, every 2 days, weekly) and can auto-publish them to YouTube.",
        "tags": [
          "Schedules"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-mcp-tool": "list_schedules"
      },
      "post": {
        "operationId": "create_schedule",
        "summary": "Create a schedule",
        "description": "Put a channel on autopilot: SimilarClip produces one video per run from the topic queue (queue topics via `topics`, add_schedule_topics or generate_schedule_topics; a run with an empty queue is skipped) and optionally auto-publishes each to YouTube.",
        "tags": [
          "Schedules"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 100
                  },
                  "niche": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 500,
                    "description": "The channel's niche/theme, e.g. \"weird animal facts\"."
                  },
                  "frequency": {
                    "default": "daily",
                    "type": "string",
                    "enum": [
                      "daily",
                      "every_2_days",
                      "weekly"
                    ]
                  },
                  "time_of_day": {
                    "default": "09:00",
                    "description": "24h local time, HH:MM.",
                    "type": "string",
                    "pattern": "^\\d{1,2}:\\d{2}$"
                  },
                  "timezone": {
                    "default": "UTC",
                    "description": "IANA timezone, e.g. America/New_York.",
                    "type": "string"
                  },
                  "duration_min": {
                    "default": 5,
                    "type": "integer",
                    "minimum": 3,
                    "maximum": 15
                  },
                  "style": {
                    "type": "string",
                    "enum": [
                      "colorful-doodle",
                      "stick-drawing",
                      "storybook",
                      "flat-vector",
                      "anime",
                      "cinematic",
                      "claymation",
                      "comic-book",
                      "pixel-art",
                      "watercolor",
                      "3d-isometric"
                    ]
                  },
                  "custom_style_prompt": {
                    "type": "string",
                    "maxLength": 2000
                  },
                  "voice": {
                    "type": "object",
                    "properties": {
                      "provider": {
                        "description": "TTS provider. Defaults to the account's saved choice.",
                        "type": "string",
                        "enum": [
                          "xai",
                          "google"
                        ]
                      },
                      "voice": {
                        "description": "Voice id for the provider (see get_options). Invalid voices fall back to the provider default.",
                        "type": "string"
                      },
                      "vibe": {
                        "description": "Narration delivery preset.",
                        "type": "string",
                        "enum": [
                          "storyteller",
                          "professional",
                          "cheerleader",
                          "dramatic",
                          "sincere",
                          "calm"
                        ]
                      },
                      "instructions": {
                        "description": "Custom delivery instructions; overrides the vibe preset's wording.",
                        "type": "string",
                        "maxLength": 1000
                      },
                      "speed": {
                        "description": "Narration playback speed.",
                        "anyOf": [
                          {
                            "type": "number",
                            "const": 1
                          },
                          {
                            "type": "number",
                            "const": 1.25
                          },
                          {
                            "type": "number",
                            "const": 1.5
                          }
                        ]
                      }
                    },
                    "description": "Narration voice. Omitted fields use the account's saved defaults."
                  },
                  "auto_publish": {
                    "default": true,
                    "type": "boolean"
                  },
                  "visibility": {
                    "default": "public",
                    "type": "string",
                    "enum": [
                      "public",
                      "unlisted",
                      "private"
                    ]
                  },
                  "channel_id": {
                    "description": "Connected channel to auto-publish to; omit for the default.",
                    "type": "string"
                  },
                  "topics": {
                    "description": "Initial topic queue.",
                    "maxItems": 100,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "maxLength": 500
                    }
                  },
                  "creative": {
                    "type": "object",
                    "properties": {
                      "captions": {
                        "description": "Burned-in captions on or off.",
                        "type": "boolean"
                      },
                      "caption_style": {
                        "description": "word = one short line with the spoken word lit up (short-form style); phrase = classic two-line captions.",
                        "type": "string",
                        "enum": [
                          "word",
                          "phrase"
                        ]
                      },
                      "pop_words": {
                        "description": "Pop each scene's key word/number up on screen, big, the moment it is spoken.",
                        "type": "boolean"
                      },
                      "motion": {
                        "description": "Slow pan or zoom on every image (default on). false = still images.",
                        "type": "boolean"
                      },
                      "seconds_per_image": {
                        "description": "Target seconds each image stays on screen (default 5). Lower = more images = more cost.",
                        "type": "number",
                        "minimum": 2,
                        "maximum": 15
                      },
                      "transition": {
                        "description": "cut = hard cuts with motion on every image (default); crossfade = dissolves; fade = dips to black.",
                        "type": "string",
                        "enum": [
                          "cut",
                          "crossfade",
                          "fade"
                        ]
                      },
                      "music_volume": {
                        "description": "Background music level, 0 (none) to 100. 50 is the standard mix.",
                        "type": "number",
                        "minimum": 0,
                        "maximum": 100
                      },
                      "sound_effects": {
                        "description": "Story sound cues (crowd, rain, splash, crash…) on the words they happen on, plus soft ticks under pop-up words. Image and scene changes are silent.",
                        "type": "boolean"
                      },
                      "hook_style": {
                        "description": "How a topic script opens: cold_open (most shocking moment first, then the setup; default), bold_claim, question, story.",
                        "type": "string",
                        "enum": [
                          "cold_open",
                          "bold_claim",
                          "question",
                          "story"
                        ]
                      },
                      "image_check": {
                        "description": "Vision-check every image and redraw ones with mangled hands/faces, stray text, or a poor match to the line (default on).",
                        "type": "boolean"
                      }
                    },
                    "description": "Creative settings for this video. Omitted fields use the account's settings, then SimilarClip's defaults."
                  },
                  "description_footer": {
                    "description": "Appended to each auto-published description; omit for the account default.",
                    "type": "string",
                    "maxLength": 1000
                  },
                  "idempotency_key": {
                    "description": "Any unique string (e.g. a UUID). Retrying with the same key returns the first call's result instead of acting, and charging, twice. REST clients can send an Idempotency-Key header instead.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  }
                },
                "required": [
                  "name",
                  "niche"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-mcp-tool": "create_schedule"
      }
    },
    "/api/v1/schedules/{id}": {
      "get": {
        "operationId": "get_schedule",
        "summary": "Get a schedule",
        "description": "One schedule with its topic queue (pending, generating, completed, failed topics and their video ids).",
        "tags": [
          "Schedules"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-mcp-tool": "get_schedule"
      },
      "post": {
        "operationId": "update_schedule",
        "summary": "Edit a schedule",
        "description": "Change any of a schedule's settings. Only the fields you send change. Changing frequency, time_of_day or timezone re-plans the next run.",
        "tags": [
          "Schedules"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 100
                  },
                  "niche": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 500
                  },
                  "frequency": {
                    "type": "string",
                    "enum": [
                      "daily",
                      "every_2_days",
                      "weekly"
                    ]
                  },
                  "time_of_day": {
                    "type": "string",
                    "pattern": "^\\d{1,2}:\\d{2}$"
                  },
                  "timezone": {
                    "type": "string"
                  },
                  "duration_min": {
                    "type": "integer",
                    "minimum": 3,
                    "maximum": 15
                  },
                  "style": {
                    "type": "string",
                    "enum": [
                      "colorful-doodle",
                      "stick-drawing",
                      "storybook",
                      "flat-vector",
                      "anime",
                      "cinematic",
                      "claymation",
                      "comic-book",
                      "pixel-art",
                      "watercolor",
                      "3d-isometric"
                    ]
                  },
                  "custom_style_prompt": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 2000
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "voice": {
                    "type": "object",
                    "properties": {
                      "provider": {
                        "description": "TTS provider. Defaults to the account's saved choice.",
                        "type": "string",
                        "enum": [
                          "xai",
                          "google"
                        ]
                      },
                      "voice": {
                        "description": "Voice id for the provider (see get_options). Invalid voices fall back to the provider default.",
                        "type": "string"
                      },
                      "vibe": {
                        "description": "Narration delivery preset.",
                        "type": "string",
                        "enum": [
                          "storyteller",
                          "professional",
                          "cheerleader",
                          "dramatic",
                          "sincere",
                          "calm"
                        ]
                      },
                      "instructions": {
                        "description": "Custom delivery instructions; overrides the vibe preset's wording.",
                        "type": "string",
                        "maxLength": 1000
                      },
                      "speed": {
                        "description": "Narration playback speed.",
                        "anyOf": [
                          {
                            "type": "number",
                            "const": 1
                          },
                          {
                            "type": "number",
                            "const": 1.25
                          },
                          {
                            "type": "number",
                            "const": 1.5
                          }
                        ]
                      }
                    },
                    "description": "Narration voice. Omitted fields use the account's saved defaults."
                  },
                  "auto_publish": {
                    "type": "boolean"
                  },
                  "visibility": {
                    "type": "string",
                    "enum": [
                      "public",
                      "unlisted",
                      "private"
                    ]
                  },
                  "channel_id": {
                    "description": "null = the default channel.",
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "creative": {
                    "description": "Merged into the schedule's existing creative settings.",
                    "type": "object",
                    "properties": {
                      "captions": {
                        "description": "Burned-in captions on or off.",
                        "type": "boolean"
                      },
                      "caption_style": {
                        "description": "word = one short line with the spoken word lit up (short-form style); phrase = classic two-line captions.",
                        "type": "string",
                        "enum": [
                          "word",
                          "phrase"
                        ]
                      },
                      "pop_words": {
                        "description": "Pop each scene's key word/number up on screen, big, the moment it is spoken.",
                        "type": "boolean"
                      },
                      "motion": {
                        "description": "Slow pan or zoom on every image (default on). false = still images.",
                        "type": "boolean"
                      },
                      "seconds_per_image": {
                        "description": "Target seconds each image stays on screen (default 5). Lower = more images = more cost.",
                        "type": "number",
                        "minimum": 2,
                        "maximum": 15
                      },
                      "transition": {
                        "description": "cut = hard cuts with motion on every image (default); crossfade = dissolves; fade = dips to black.",
                        "type": "string",
                        "enum": [
                          "cut",
                          "crossfade",
                          "fade"
                        ]
                      },
                      "music_volume": {
                        "description": "Background music level, 0 (none) to 100. 50 is the standard mix.",
                        "type": "number",
                        "minimum": 0,
                        "maximum": 100
                      },
                      "sound_effects": {
                        "description": "Story sound cues (crowd, rain, splash, crash…) on the words they happen on, plus soft ticks under pop-up words. Image and scene changes are silent.",
                        "type": "boolean"
                      },
                      "hook_style": {
                        "description": "How a topic script opens: cold_open (most shocking moment first, then the setup; default), bold_claim, question, story.",
                        "type": "string",
                        "enum": [
                          "cold_open",
                          "bold_claim",
                          "question",
                          "story"
                        ]
                      },
                      "image_check": {
                        "description": "Vision-check every image and redraw ones with mangled hands/faces, stray text, or a poor match to the line (default on).",
                        "type": "boolean"
                      }
                    }
                  },
                  "description_footer": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 1000
                      },
                      {
                        "type": "null"
                      }
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-mcp-tool": "update_schedule"
      },
      "delete": {
        "operationId": "delete_schedule",
        "summary": "Delete a schedule",
        "description": "Delete a schedule and its topic queue. Videos it already made are kept.",
        "tags": [
          "Schedules"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-mcp-tool": "delete_schedule"
      }
    },
    "/api/v1/schedules/{id}/topics": {
      "post": {
        "operationId": "add_schedule_topics",
        "summary": "Queue schedule topics",
        "description": "Append topics to a schedule's queue (duplicates are skipped). One topic is consumed per run.",
        "tags": [
          "Schedules"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "topics": {
                    "minItems": 1,
                    "maxItems": 100,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 500
                    }
                  }
                },
                "required": [
                  "topics"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-mcp-tool": "add_schedule_topics"
      }
    },
    "/api/v1/schedules/{id}/topics/generate": {
      "post": {
        "operationId": "generate_schedule_topics",
        "summary": "Brainstorm schedule topics",
        "description": "Have the AI brainstorm fresh, non-duplicate topics from the schedule's niche and append them to its queue.",
        "tags": [
          "Schedules"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "count": {
                    "default": 10,
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 20
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-mcp-tool": "generate_schedule_topics"
      }
    },
    "/api/v1/schedules/{id}/topics/{topic_id}": {
      "delete": {
        "operationId": "delete_schedule_topic",
        "summary": "Remove a queued topic",
        "description": "Remove a pending topic from a schedule's queue (topics already turned into videos stay in the history).",
        "tags": [
          "Schedules"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "topic_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-mcp-tool": "delete_schedule_topic"
      }
    },
    "/api/v1/schedules/{id}/enabled": {
      "post": {
        "operationId": "set_schedule_enabled",
        "summary": "Enable or pause a schedule",
        "description": "Turn a schedule on or off.",
        "tags": [
          "Schedules"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "enabled": {
                    "type": "boolean"
                  }
                },
                "required": [
                  "enabled"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-mcp-tool": "set_schedule_enabled"
      }
    },
    "/api/v1/schedules/{id}/run": {
      "post": {
        "operationId": "run_schedule_now",
        "summary": "Run a schedule now",
        "description": "Produce the schedule's next video immediately instead of waiting for its next slot.",
        "tags": [
          "Schedules"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-mcp-tool": "run_schedule_now"
      }
    },
    "/api/v1/me/settings": {
      "post": {
        "operationId": "update_account_settings",
        "summary": "Update account settings",
        "description": "Account-wide defaults that create_video and create_schedule use when a field is omitted: style, custom_style_prompt and voice (provider, voice, vibe, instructions, speed), plus description_footer, appended to every YouTube description this account publishes (links, socials, a call to action). Omitted fields are left as they are; \"\" clears custom_style_prompt, voice.instructions or description_footer. Returns the saved settings.",
        "tags": [
          "Account"
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "style": {
                    "description": "Default visual style preset (see get_options).",
                    "type": "string",
                    "enum": [
                      "colorful-doodle",
                      "stick-drawing",
                      "storybook",
                      "flat-vector",
                      "anime",
                      "cinematic",
                      "claymation",
                      "comic-book",
                      "pixel-art",
                      "watercolor",
                      "3d-isometric"
                    ]
                  },
                  "custom_style_prompt": {
                    "description": "Default free-form art direction; overrides the preset when set. \"\" clears it.",
                    "type": "string",
                    "maxLength": 2000
                  },
                  "voice": {
                    "type": "object",
                    "properties": {
                      "provider": {
                        "description": "TTS provider. Defaults to the account's saved choice.",
                        "type": "string",
                        "enum": [
                          "xai",
                          "google"
                        ]
                      },
                      "voice": {
                        "description": "Voice id for the provider (see get_options). Invalid voices fall back to the provider default.",
                        "type": "string"
                      },
                      "vibe": {
                        "description": "Narration delivery preset.",
                        "type": "string",
                        "enum": [
                          "storyteller",
                          "professional",
                          "cheerleader",
                          "dramatic",
                          "sincere",
                          "calm"
                        ]
                      },
                      "instructions": {
                        "description": "Custom delivery instructions; overrides the vibe preset's wording.",
                        "type": "string",
                        "maxLength": 1000
                      },
                      "speed": {
                        "description": "Narration playback speed.",
                        "anyOf": [
                          {
                            "type": "number",
                            "const": 1
                          },
                          {
                            "type": "number",
                            "const": 1.25
                          },
                          {
                            "type": "number",
                            "const": 1.5
                          }
                        ]
                      }
                    },
                    "description": "Narration voice. Omitted fields use the account's saved defaults."
                  },
                  "description_footer": {
                    "type": "string",
                    "maxLength": 1000
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-mcp-tool": "update_account_settings"
      }
    },
    "/api/v1/webhooks": {
      "get": {
        "operationId": "list_webhooks",
        "summary": "List webhooks",
        "description": "The account's webhook endpoints, the events each receives, and how the last delivery went.",
        "tags": [
          "Webhooks"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-mcp-tool": "list_webhooks"
      },
      "post": {
        "operationId": "create_webhook",
        "summary": "Create a webhook",
        "description": "Have SimilarClip POST to your HTTPS endpoint when a video's script is ready, it completes or fails, or a publish succeeds or fails, instead of polling. The response includes the signing secret ONCE: verify X-SimilarClip-Signature (t=<unix>,v1=<hex HMAC-SHA256 of \"<t>.<raw body>\">) with it. Failed deliveries retry with backoff for about 15 minutes.",
        "tags": [
          "Webhooks"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "maxLength": 2000,
                    "format": "uri",
                    "description": "https:// endpoint on a public host."
                  },
                  "events": {
                    "description": "Events to receive; omit for all of them.",
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "video.script_ready",
                        "video.completed",
                        "video.failed",
                        "video.published",
                        "video.publish_failed"
                      ]
                    }
                  }
                },
                "required": [
                  "url"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-mcp-tool": "create_webhook"
      }
    },
    "/api/v1/webhooks/{id}": {
      "delete": {
        "operationId": "delete_webhook",
        "summary": "Delete a webhook",
        "description": "Stop sending events to an endpoint.",
        "tags": [
          "Webhooks"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-mcp-tool": "delete_webhook"
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Personal API key (sc_live_…), created at https://similarclip.com/app/settings?tab=api"
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string"
              },
              "message": {
                "type": "string"
              },
              "details": {
                "type": "object"
              }
            },
            "required": [
              "code",
              "message"
            ]
          }
        }
      }
    }
  }
}