Koskamo

AwesomeVideo MCP

An MCP server for AI agents to perform video processing tasks including transcription, translation, dubbing, and burning styled captions into video files. It supports creating short clips from long videos, managing custom caption presets, and handling file uploads via public URLs or multipart uploads. The server shares credentials and credit balance with the REST API.

Endpoint and access

No sign-in to connect and list tools. Individual tools may still need a vendor account, credentials, or permissions; check the documented prerequisites.

AwesomeVideo MCP logo, by AwesomeVideoVendor evidenceStreamable HTTPNo sign-inEndpoint checked 2026-11-01Operated by AwesomeVideo
MCP endpoint (Streamable HTTP)
https://api.awesomevideoeditor.com/mcp
Vendor documentation

What you can do with it

  • Transcribe audio from video files and translate subtitles
  • Burn styled captions into video for specific social platforms
  • Create short vertical clips from long-form video content
  • Dub video content using AI-generated voices

Source and maintenance

Vendor evidenceRegistry 0.3.0

Protocol and capabilities

Server
awesomevideo 0.4.0
MCP protocol
2025-06-18
Tools
27 advertised
Resources
Not advertised
Resource templates
Not advertised
Prompts
Not advertised
Server-advertised capabilities
{
  "tools": {
    "listChanged": true
  }
}

Server-provided instructions

Untrusted server output shown for inspection. It is not Koskamo guidance and is excluded from knowledge search.

AwesomeVideo transcribes, translates, dubs, trims, clips, and burns styled captions into video. For the common case (a video in, a video with burned subtitles out) call caption_video once: pass sourceUrl (a public link) or fileId (from upload or import_url); it transcribes, optionally translates, burns, waits up to ~45 s, and returns the MP4, SRT, VTT, and transcript. Prepaid credits: 1 credit = 1 cent. Free without a key: create_key, estimate, get_catalog. Call estimate with steps first: it prices a whole pipeline and reports limitViolations; paid tools reject over-limit input with limit_exceeded before charging. Every other tool needs a key: call create_key (0 credits), then reconnect with Authorization: Bearer <token>. Paid tools return 402 insufficient_balance with checkoutUrl ($5 = 500 credits) when the balance is short; nothing is charged. Errors carry hint (what to call next) and retryable. Pass maxCredits to cap a job. Docs: /llms.txt.

Tools

27 advertised

create_key — Create API key
Advertised by the server during the last successful anonymous check.

Free. Create a new AwesomeVideo API key with 0 credits, no sign-in. Works without a key. Returns the token once; store it and send it as Authorization: Bearer <token> on the MCP connection or REST calls. Paid tools then return 402 with a checkoutUrl ($5 = 500 credits, 1 credit = 1 cent). Limited to a few keys per network per day.

create_key input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "name": {
      "type": "string",
      "maxLength": 80,
      "description": "Optional label, e.g. the agent's name."
    }
  }
}
create_key output schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "key": {
      "description": "Key record: id, name, tokenPrefix."
    },
    "next": {
      "description": "Suggested next calls (e.g. create_checkout (without product))."
    },
    "token": {
      "type": "string",
      "description": "The API key (av_live_...). Shown once: store it and send it as Authorization: Bearer <token>."
    },
    "message": {
      "type": "string",
      "description": "What to do next."
    },
    "balanceCents": {
      "type": "number",
      "description": "Starting balance in credits (0)."
    }
  },
  "description": "The new key.",
  "additionalProperties": {}
}
create_key annotations
{
  "title": "Create API key",
  "readOnlyHint": false,
  "openWorldHint": false,
  "idempotentHint": false,
  "destructiveHint": false
}
import_url — Import from URL
Advertised by the server during the last successful anonymous check.
Open-world

Free. Download a public video or audio link into AwesomeVideo and get a fileId (same as upload {action:'start'}), without downloading it yourself. Accepts direct https/http file links (chat attachment URLs, CDNs, S3 presigned URLs), Google Drive share links (large-file confirm page handled), Dropbox share links, and OneDrive links. Up to 2048 MB when the host sends Content-Length (streamed to storage), 80 MB otherwise (422 limit_exceeded, charged:false). YouTube, TikTok, and Instagram links are refused with 422: upload the file instead. Private, local, and non-standard-port addresses are blocked. Up to 30 per hour. caption_video accepts sourceUrl directly, so you only need this to reuse one file across several tools.

import_url input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "required": [
    "url"
  ],
  "properties": {
    "url": {
      "type": "string",
      "description": "Public link to the file."
    },
    "filename": {
      "type": "string",
      "maxLength": 200,
      "description": "File name to store, with extension (e.g. talk.mp4); used for the content type and download name. Max 200 characters."
    }
  }
}
import_url output schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "total": {
      "type": "number",
      "description": "Total number of items (paginated lists)."
    },
    "result": {
      "description": "The value, when the tool returns something other than an object."
    },
    "hasMore": {
      "type": "boolean",
      "description": "true when more items are available (paginated lists)."
    },
    "nextCursor": {
      "type": "string",
      "description": "Pass as cursor for the next page (paginated lists)."
    }
  },
  "description": "Tool result as JSON.",
  "additionalProperties": {}
}
import_url annotations
{
  "title": "Import from URL",
  "readOnlyHint": false,
  "openWorldHint": true,
  "idempotentHint": false,
  "destructiveHint": false
}
caption_video — Caption video (one call)
Advertised by the server during the last successful anonymous check.
Open-world

PREFER THIS for 'add/burn subtitles to this video'. One call: transcribe, optional translate (translateTo), burn; returns the MP4 plus SRT, VTT and JSON transcript. Source: sourceUrl (public link, Drive, Dropbox; not YouTube) or fileId from upload/import_url. Price: 5 credits per audio minute, 7 with translateTo (1 credit = 1 cent); failures refund. Waits up to waitSeconds (max 50), then returns the job to poll with get_job (or use webhookUrl/notifyEmail). review:true sends a reviewUrl and charges the burn only on approval. To edit text yourself: transcribe, edit_transcript, burn_captions.

caption_video input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "wait": {
      "type": "boolean",
      "description": "Block until done, up to waitSeconds. Default true."
    },
    "fileId": {
      "type": "string",
      "description": "Id from upload {action:'start'}, import_url, or upload {action:'inline'}."
    },
    "preset": {
      "type": "string",
      "description": "Caption style preset id or name (get_catalog {kind:'presets'}), or your own saved preset as custom:cp_... (manage_preset {action:'create', type:'custom'}). Default Clarity."
    },
    "review": {
      "type": "boolean",
      "description": "Human review first: transcribes now, returns reviewUrl for the person; the burn runs and is charged only when they approve. Not with translateTo."
    },
    "autoFit": {
      "type": "boolean",
      "description": "Default true: caption size, words per caption (4 on 9:16, 5 on 1:1, 7 on 16:9), and a default safe zone follow the video shape, so text reads the same at 720p and 1080p and stays clear of app UI. Pass false only when the user wants the preset's exact fixed pixel sizes. Same price."
    },
    "glossary": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Names and brand terms to spell correctly, e.g. ['AwesomeVideo']."
    },
    "language": {
      "type": "string",
      "description": "Spoken language (BCP-47, e.g. es, en). Omit for auto-detect."
    },
    "platform": {
      "type": "string",
      "description": "Target platform: tiktok, instagram_reels, youtube_shorts, youtube, ... (aliases reels, shorts). Keeps captions clear of the app UI. Same price."
    },
    "faceAvoid": {
      "type": "boolean",
      "description": "true = move captions off faces (samples faces at 2 fps, same price; result.faceAvoid.faceLayout). Shortcut for styleOverrides.faceAvoid."
    },
    "sourceUrl": {
      "type": "string",
      "description": "Public link to the video/audio. Direct https file, chat attachment URL, Google Drive or Dropbox share link. Not YouTube."
    },
    "maxCredits": {
      "type": "number",
      "minimum": 0,
      "description": "Refuse the job if it would cost more than this many credits."
    },
    "webhookUrl": {
      "type": "string",
      "description": "Public https URL, POSTed a signed JSON body when the job finishes."
    },
    "audioVisual": {
      "type": "object",
      "properties": {
        "ink": {
          "type": "string",
          "description": "Text/line colour #hex. Default: the design's, or auto from the paper."
        },
        "width": {
          "type": "integer",
          "maximum": 9007199254740991,
          "minimum": -9007199254740991
        },
        "accent": {
          "type": "string",
          "description": "Accent colour #hex (spoken word, needle, seal...). Default: the design's."
        },
        "aspect": {
          "enum": [
            "9:16",
            "16:9",
            "1:1",
            "4:5"
          ],
          "type": "string",
          "description": "Frame shape; default from platform, else 9:16."
        },
        "height": {
          "type": "integer",
          "maximum": 9007199254740991,
          "minimum": -9007199254740991
        },
        "enabled": {
          "type": "boolean",
          "description": "false: paper + captions, no design."
        },
        "episode": {
          "anyOf": [
            {
              "type": "string",
              "maxLength": 12
            },
            {
              "type": "number"
            }
          ],
          "description": "Episode label or number (max 12 chars), printed after Nº. Empty: left out."
        },
        "speaker": {
          "type": "string",
          "maxLength": 60,
          "description": "Speaker / host name for bylines (max 60). Empty: left out."
        },
        "variant": {
          "type": "string",
          "description": "Design id: swiss-grid | braun-radio | riso | editorial-cover | bauhaus | continuous-line | vinyl | type-wave | duotone-portrait | ma (default editorial-cover). Retired ids still work as aliases with a warning: bars→swiss-grid, ribbon→continuous-line, rings→ma, spectrogram→riso, skyline→bauhaus, silkline→type-wave, ivory→editorial-cover, halo→vinyl, needle→braun-radio, mono→duotone-portrait. get_catalog {kind:'audio_visuals'} describes each design."
        },
        "overlays": {
          "type": "array",
          "items": {
            "type": "object",
            "propertyNames": {
              "type": "string"
            },
            "additionalProperties": {}
          },
          "maxItems": 8,
          "description": "Up to 8 image (imageUrl, PNG/JPEG/WebP <=5 MB) or text items {kind, x, y, width, height, start, end, ...} in frame pixels."
        },
        "showName": {
          "type": "string",
          "maxLength": 60,
          "description": "Show / podcast name (max 60). Empty: left out (mastheads fall back to Podcast)."
        },
        "background": {
          "type": "string",
          "description": "Paper colour #rgb/#rrggbb (default: the design's). Ink switches automatically for contrast."
        },
        "captionMode": {
          "enum": [
            "integrated",
            "preset"
          ],
          "type": "string",
          "description": "integrated (default): the design typesets the captions word by word; preset: your caption preset draws them."
        },
        "coverFileId": {
          "type": "string",
          "description": "Same as coverImageUrl but a fileId from upload {action:'start'}."
        },
        "contrastGuard": {
          "type": "boolean",
          "description": "Preset mode (default true): white text on a light design switches to the design's ink so it stays legible."
        },
        "coverImageUrl": {
          "type": "string",
          "description": "Public https PNG/JPEG/WebP (max 5 MB) for the cover/host image slot (vinyl, duotone-portrait). Fetched before any charge."
        }
      },
      "description": "Audio-only input (mp3, m4a, wav...): an editorial podcast design plus captions, drawn on the server by the web editor's own code, same price as the burn. {variant: swiss-grid | braun-radio | riso | editorial-cover | bauhaus | continuous-line | vinyl | type-wave | duotone-portrait | ma (default editorial-cover), showName (<=60), episode (<=12), speaker (<=60), coverImageUrl (https) or coverFileId (PNG/JPEG/WebP <=5 MB; shown by vinyl, duotone-portrait), background/accent/ink (#hex; ink auto from paper), captionMode integrated (default: the design typesets the captions) | preset (your caption preset draws), contrastGuard (default true), aspect 9:16|16:9|1:1|4:5 or width+height, overlays (<=8)}. Retired ids still work as aliases with a warning: bars→swiss-grid, ribbon→continuous-line, rings→ma, spectrogram→riso, skyline→bauhaus, silkline→type-wave, ivory→editorial-cover, halo→vinyl, needle→braun-radio, mono→duotone-portrait. On a video input: 422 audio_visual_needs_audio_input, not charged. Catalog: GET /v1/audio-visuals (MCP get_catalog {kind:'audio_visuals'}), free.",
      "additionalProperties": {}
    },
    "notifyEmail": {
      "type": "string",
      "description": "Email when the job finishes. Free."
    },
    "translateTo": {
      "type": "string",
      "description": "Burn subtitles translated to this language (ISO 639-1, e.g. en). Adds 2 credits/min."
    },
    "waitSeconds": {
      "type": "integer",
      "maximum": 50,
      "minimum": 0,
      "description": "Default 45, max 50."
    },
    "instructions": {
      "type": "string",
      "maxLength": 500,
      "description": "review only: note shown to the reviewer."
    },
    "brandPresetId": {
      "type": "string",
      "description": "Saved brand preset (font, colors, position, logo)."
    },
    "highlightColor": {
      "type": "string",
      "description": "#RRGGBB for highlightWords. Default #FACC15."
    },
    "highlightWords": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "maxItems": 200,
      "description": "Shortcut: words or phrases to color in every caption (accent/case-insensitive), e.g. [\"AwesomeVideo\", \"gratis\"]. Maps to styleOverrides.wordHighlights rule {id:\"custom\", words, color}. Same price."
    },
    "idempotencyKey": {
      "type": "string",
      "maxLength": 200,
      "description": "Same key returns the same job instead of charging twice."
    },
    "styleOverrides": {
      "type": "object",
      "description": "Per-call style changes deep-merged onto the preset (same fields as get_catalog {kind:'presets'} style; null removes a field), validated with the renderer schema and bundled fonts. Example {\"fontSize\":72,\"maxWordsPerCaption\":2,\"wordEntrance\":\"bounce\"}. Same price. No need to manage_preset {action:'create', type:'custom'}. Every field with examples: get_catalog {kind:'styles'}.",
      "propertyNames": {
        "type": "string"
      },
      "additionalProperties": {}
    },
    "durationSeconds": {
      "type": "number",
      "description": "Media length in seconds. Lets the price be computed without fetching media (quoteOnly, quote, plan).",
      "exclusiveMinimum": 0
    }
  }
}
caption_video output schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "id": {
      "type": "string",
      "description": "Job id: pass it to get_job, resume_job, edit_transcript or as transcriptionJobId."
    },
    "kind": {
      "type": "string",
      "description": "Job kind (transcribe, burn, caption, clips, shorts, trim, dub, translate, preview, metadata...)."
    },
    "step": {
      "type": "string",
      "description": "Current pipeline step while running."
    },
    "error": {
      "description": "Failure reason when status is failed."
    },
    "result": {
      "description": "Result when succeeded: url, files[{name, url}], clips, text..."
    },
    "status": {
      "type": "string",
      "description": "queued, running, succeeded or failed."
    },
    "progress": {
      "description": "Progress (0-1) and ETA while running."
    },
    "warnings": {
      "type": "array",
      "items": {},
      "description": "Non-blocking notes."
    },
    "costCents": {
      "type": "number",
      "description": "Credits charged (1 credit = 1 cent)."
    },
    "expiresAt": {
      "description": "When the result files are deleted."
    },
    "refundedCents": {
      "type": "number",
      "description": "Credits refunded after a failure."
    }
  },
  "description": "A job: poll get_job with id until status is succeeded or failed.",
  "additionalProperties": {}
}
caption_video annotations
{
  "title": "Caption video (one call)",
  "readOnlyHint": false,
  "openWorldHint": true,
  "idempotentHint": false,
  "destructiveHint": false
}
transcribe — Transcribe
Advertised by the server during the last successful anonymous check.
Open-world

Transcribe speech in a video or audio file to captions with Workers AI Whisper (large-v3-turbo); returns SRT, VTT or JSON with word timestamps (format). Paid: 1 credit per audio minute (1 credit = 1 cent); a short balance gets 402 insufficient_balance (requiredCents, balanceCents, checkoutUrl) and no job starts. Use it when you only need the text or want to edit it before burning (then edit_transcript -> burn_captions). For burned-in subtitles in one call use caption_video; for highlights use create_clips. Audio is extracted to 16 kHz mono (video frames are not decoded). Language defaults to auto-detect; the saved glossary is applied. Results are cached per key, language, format and duration; another key cannot read them.

transcribe input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "fileId": {
      "type": "string",
      "description": "Id from upload {action:'start'}, upload {action:'inline'}, or POST /v1/uploads."
    },
    "format": {
      "enum": [
        "srt",
        "vtt",
        "json"
      ],
      "type": "string",
      "description": "Default json, including word timestamps."
    },
    "glossary": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Names and terms. Used as the Whisper prompt and to fix close spellings. Included in the transcription price."
    },
    "language": {
      "type": "string",
      "description": "BCP-47 language, or omit for auto."
    },
    "mediaUrl": {
      "type": "string",
      "format": "uri",
      "description": "HTTPS URL of the audio or video file."
    },
    "maxCredits": {
      "type": "number",
      "minimum": 0,
      "description": "Refuse the job when the debit would exceed this many cents."
    },
    "webhookUrl": {
      "type": "string",
      "description": "Public https URL. POSTed an HMAC-signed JSON body when the job finishes. Three tries."
    },
    "notifyEmail": {
      "type": "string",
      "description": "Optional completion email. Free. Needs the email binding."
    },
    "durationSeconds": {
      "type": "number",
      "description": "Optional duration hint used before probe.",
      "exclusiveMinimum": 0
    },
    "useSavedGlossary": {
      "type": "boolean",
      "description": "Default true: also apply the saved glossary (update_glossary {action:'save'}) with its alias fixes, e.g. 'awesome video' -> 'AwesomeVideo'. Free."
    }
  }
}
transcribe output schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "id": {
      "type": "string",
      "description": "Job id: pass it to get_job, resume_job, edit_transcript or as transcriptionJobId."
    },
    "kind": {
      "type": "string",
      "description": "Job kind (transcribe, burn, caption, clips, shorts, trim, dub, translate, preview, metadata...)."
    },
    "step": {
      "type": "string",
      "description": "Current pipeline step while running."
    },
    "error": {
      "description": "Failure reason when status is failed."
    },
    "result": {
      "description": "Result when succeeded: url, files[{name, url}], clips, text..."
    },
    "status": {
      "type": "string",
      "description": "queued, running, succeeded or failed."
    },
    "progress": {
      "description": "Progress (0-1) and ETA while running."
    },
    "warnings": {
      "type": "array",
      "items": {},
      "description": "Non-blocking notes."
    },
    "costCents": {
      "type": "number",
      "description": "Credits charged (1 credit = 1 cent)."
    },
    "expiresAt": {
      "description": "When the result files are deleted."
    },
    "refundedCents": {
      "type": "number",
      "description": "Credits refunded after a failure."
    }
  },
  "description": "A job: poll get_job with id until status is succeeded or failed.",
  "additionalProperties": {}
}
transcribe annotations
{
  "title": "Transcribe",
  "readOnlyHint": false,
  "openWorldHint": true,
  "idempotentHint": false,
  "destructiveHint": false
}
edit_transcript — Edit transcript
Advertised by the server during the last successful anonymous check.
Advertised destructive

Replace the cues of a finished transcription (from transcribe or caption_video) with corrected text or timing, without transcribing again. Free; needs the key that owns the job. Pass cues [{start, end, text}] in seconds or subtitles (SRT, VTT or JSON); the old cues are overwritten. A later burn_captions, translate or remove_silences with this transcriptionJobId uses the edited cues and pays only its own step. To fix spellings for every future job use update_glossary {action:'save'} instead. Returns the job with the new SRT, VTT and JSON URLs.

edit_transcript input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "required": [
    "jobId"
  ],
  "properties": {
    "cues": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "start",
          "end",
          "text"
        ],
        "properties": {
          "end": {
            "type": "number"
          },
          "text": {
            "type": "string"
          },
          "start": {
            "type": "number"
          }
        }
      },
      "description": "Corrected cues [{start, end, text}] with start/end in seconds. Pass this or subtitles."
    },
    "jobId": {
      "type": "string",
      "description": "Id of the finished transcribe or caption_video job whose cues to replace."
    },
    "subtitles": {
      "type": "string",
      "description": "Corrected captions as SRT, WebVTT or JSON. Pass this or cues."
    }
  }
}
edit_transcript output schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "id": {
      "type": "string",
      "description": "Job id: pass it to get_job, resume_job, edit_transcript or as transcriptionJobId."
    },
    "kind": {
      "type": "string",
      "description": "Job kind (transcribe, burn, caption, clips, shorts, trim, dub, translate, preview, metadata...)."
    },
    "step": {
      "type": "string",
      "description": "Current pipeline step while running."
    },
    "error": {
      "description": "Failure reason when status is failed."
    },
    "result": {
      "description": "Result when succeeded: url, files[{name, url}], clips, text..."
    },
    "status": {
      "type": "string",
      "description": "queued, running, succeeded or failed."
    },
    "progress": {
      "description": "Progress (0-1) and ETA while running."
    },
    "warnings": {
      "type": "array",
      "items": {},
      "description": "Non-blocking notes."
    },
    "costCents": {
      "type": "number",
      "description": "Credits charged (1 credit = 1 cent)."
    },
    "expiresAt": {
      "description": "When the result files are deleted."
    },
    "refundedCents": {
      "type": "number",
      "description": "Credits refunded after a failure."
    }
  },
  "description": "A job: poll get_job with id until status is succeeded or failed.",
  "additionalProperties": {}
}
edit_transcript annotations
{
  "title": "Edit transcript",
  "readOnlyHint": false,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": true
}
batch — Batch jobs
Advertised by the server during the last successful anonymous check.
Open-world

Run the same operation (transcribe or burn) on up to 10 media items in one call, priced together. Paid: the sum of the per-item prices (transcribe 1 credit/min, burn 4 credits/min). dryRun: true returns the total quote and starts nothing. Otherwise the whole batch is refused with 402 insufficient_balance (or 422 when over maxCredits) before any item starts, so it never half-runs for lack of credits. Use it for many files at once; for one file prefer caption_video, transcribe or burn_captions. Returns the quote plus one job per item; poll each with get_job.

batch input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "required": [
    "operation",
    "items"
  ],
  "properties": {
    "items": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "fileId": {
            "type": "string"
          },
          "format": {
            "enum": [
              "srt",
              "vtt",
              "json"
            ],
            "type": "string"
          },
          "preset": {
            "type": "string"
          },
          "combined": {
            "type": "boolean"
          },
          "glossary": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "language": {
            "type": "string"
          },
          "mediaUrl": {
            "type": "string"
          },
          "faceAvoid": {
            "type": "boolean",
            "description": "true = move captions off faces (samples faces at 2 fps, same price; result.faceAvoid.faceLayout). Shortcut for styleOverrides.faceAvoid."
          },
          "subtitles": {
            "type": "string"
          },
          "highlightColor": {
            "type": "string",
            "description": "#RRGGBB for highlightWords. Default #FACC15."
          },
          "highlightWords": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "maxItems": 200,
            "description": "Shortcut: words or phrases to color in every caption (accent/case-insensitive), e.g. [\"AwesomeVideo\", \"gratis\"]. Maps to styleOverrides.wordHighlights rule {id:\"custom\", words, color}. Same price."
          },
          "styleOverrides": {
            "type": "object",
            "description": "Per-call style changes deep-merged onto the preset (same fields as get_catalog {kind:'presets'} style; null removes a field), validated with the renderer schema and bundled fonts. Example {\"fontSize\":72,\"maxWordsPerCaption\":2,\"wordEntrance\":\"bounce\"}. Same price. No need to manage_preset {action:'create', type:'custom'}. Every field with examples: get_catalog {kind:'styles'}.",
            "propertyNames": {
              "type": "string"
            },
            "additionalProperties": {}
          },
          "durationSeconds": {
            "type": "number",
            "exclusiveMinimum": 0
          },
          "transcriptionJobId": {
            "type": "string"
          }
        }
      },
      "maxItems": 10,
      "minItems": 1,
      "description": "1-10 items, each {mediaUrl or fileId, language?, subtitles?, transcriptionJobId?, preset?}."
    },
    "dryRun": {
      "type": "boolean",
      "description": "true = return the total quote only; nothing is charged or started."
    },
    "preset": {
      "type": "string",
      "description": "Preset for every burn item (an item's own preset wins)."
    },
    "operation": {
      "enum": [
        "transcribe",
        "burn"
      ],
      "type": "string",
      "description": "'transcribe' or 'burn', applied to every item."
    },
    "maxCredits": {
      "type": "number",
      "minimum": 0,
      "description": "Cap for the whole batch in credits; refused before any item starts when the total is higher."
    }
  }
}
batch output schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "total": {
      "type": "number",
      "description": "Total number of items (paginated lists)."
    },
    "result": {
      "description": "The value, when the tool returns something other than an object."
    },
    "hasMore": {
      "type": "boolean",
      "description": "true when more items are available (paginated lists)."
    },
    "nextCursor": {
      "type": "string",
      "description": "Pass as cursor for the next page (paginated lists)."
    }
  },
  "description": "Tool result as JSON.",
  "additionalProperties": {}
}
batch annotations
{
  "title": "Batch jobs",
  "readOnlyHint": false,
  "openWorldHint": true,
  "idempotentHint": false,
  "destructiveHint": false
}
translate — Translate subtitles
Advertised by the server during the last successful anonymous check.
Open-world

Translate existing captions (subtitles or transcriptionJobId) into another language with Workers AI m2m100, keeping cue timing; returns SRT, VTT and JSON. Paid: 2 credits per minute; burn: true also burns the translation into the video (+4 credits/min; needs mediaUrl or fileId and a preset). Word-level highlight timing is not kept. To transcribe, translate and burn in one call use caption_video with translateTo; for a spoken (voice) translation use dub. Saved do-not-translate glossary terms are kept as is. 402 insufficient_balance with checkoutUrl when short; failed jobs refund.

translate input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "required": [
    "targetLanguage"
  ],
  "properties": {
    "burn": {
      "type": "boolean",
      "description": "true = also burn the translated captions into the video (+4 credits/min; needs mediaUrl or fileId and a preset)."
    },
    "fileId": {
      "type": "string",
      "description": "Uploaded media to burn into when burn is true."
    },
    "preset": {
      "type": "string",
      "description": "Preset for the burn when burn is true."
    },
    "mediaUrl": {
      "type": "string",
      "description": "Media to burn into when burn is true."
    },
    "faceAvoid": {
      "type": "boolean",
      "description": "true = move captions off faces (samples faces at 2 fps, same price; result.faceAvoid.faceLayout). Shortcut for styleOverrides.faceAvoid."
    },
    "subtitles": {
      "type": "string",
      "description": "Existing captions as SRT, WebVTT or AwesomeVideo JSON text. Skips transcription (no transcription charge)."
    },
    "maxCredits": {
      "type": "number",
      "minimum": 0,
      "description": "Spending cap for this call in credits (1 credit = 1 cent). If the price is higher the call fails with 422 before charging."
    },
    "highlightColor": {
      "type": "string",
      "description": "#RRGGBB for highlightWords. Default #FACC15."
    },
    "highlightWords": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "maxItems": 200,
      "description": "Shortcut: words or phrases to color in every caption (accent/case-insensitive), e.g. [\"AwesomeVideo\", \"gratis\"]. Maps to styleOverrides.wordHighlights rule {id:\"custom\", words, color}. Same price."
    },
    "sourceLanguage": {
      "type": "string",
      "description": "Language of the input captions or speech (ISO 639-1, e.g. en). Omit to auto-detect."
    },
    "styleOverrides": {
      "type": "object",
      "description": "Per-call style changes deep-merged onto the preset (same fields as get_catalog {kind:'presets'} style; null removes a field), validated with the renderer schema and bundled fonts. Example {\"fontSize\":72,\"maxWordsPerCaption\":2,\"wordEntrance\":\"bounce\"}. Same price. No need to manage_preset {action:'create', type:'custom'}. Every field with examples: get_catalog {kind:'styles'}.",
      "propertyNames": {
        "type": "string"
      },
      "additionalProperties": {}
    },
    "targetLanguage": {
      "type": "string",
      "description": "ISO 639-1 code such as es, fr, de, pt, it, ja, zh. Unsupported codes return invalid_language."
    },
    "transcriptionJobId": {
      "type": "string",
      "description": "Id of a finished transcribe or caption_video job whose transcript to reuse (no new transcription charge)."
    }
  }
}
translate output schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "id": {
      "type": "string",
      "description": "Job id: pass it to get_job, resume_job, edit_transcript or as transcriptionJobId."
    },
    "kind": {
      "type": "string",
      "description": "Job kind (transcribe, burn, caption, clips, shorts, trim, dub, translate, preview, metadata...)."
    },
    "step": {
      "type": "string",
      "description": "Current pipeline step while running."
    },
    "error": {
      "description": "Failure reason when status is failed."
    },
    "result": {
      "description": "Result when succeeded: url, files[{name, url}], clips, text..."
    },
    "status": {
      "type": "string",
      "description": "queued, running, succeeded or failed."
    },
    "progress": {
      "description": "Progress (0-1) and ETA while running."
    },
    "warnings": {
      "type": "array",
      "items": {},
      "description": "Non-blocking notes."
    },
    "costCents": {
      "type": "number",
      "description": "Credits charged (1 credit = 1 cent)."
    },
    "expiresAt": {
      "description": "When the result files are deleted."
    },
    "refundedCents": {
      "type": "number",
      "description": "Credits refunded after a failure."
    }
  },
  "description": "A job: poll get_job with id until status is succeeded or failed.",
  "additionalProperties": {}
}
translate annotations
{
  "title": "Translate subtitles",
  "readOnlyHint": false,
  "openWorldHint": true,
  "idempotentHint": false,
  "destructiveHint": false
}
dub — Dub video into another language
Advertised by the server during the last successful anonymous check.
Open-world

Dub a video into targetLanguage: transcribes, translates, voices each line fitted to the original timing, and mixes it over the original audio (ducked by default, or muted); returns an MP4 plus target-language SRT/VTT/JSON (audioTrack:true adds an M4A). Price per target language: 5 credits per source minute (voiceTier basic) or 12 (standard), plus transcription 1/min and translation 2/min unless you reuse transcriptionJobId/subtitles and translationJobId/translatedSubtitles. Voices: get_catalog kind voices. Unsupported languages fail before charging. No voice cloning or lip sync.

dub input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "required": [
    "targetLanguage"
  ],
  "properties": {
    "voice": {
      "type": "string",
      "description": "Voice id from get_catalog {kind:'voices'} (listen to sampleUrl first). Omit for the default voice of the language and tier."
    },
    "fileId": {
      "type": "string",
      "description": "Id of a file already uploaded with upload {action:'start'}, upload {action:'start_multipart'}, upload {action:'inline'} or import_url. Pass this or the media URL."
    },
    "mediaUrl": {
      "type": "string",
      "description": "Public https link to the video or audio (direct file, chat attachment URL, Google Drive or Dropbox share link; YouTube is refused). Pass this or fileId."
    },
    "subtitles": {
      "type": "string",
      "description": "Source-language SRT, VTT, or JSON."
    },
    "voiceTier": {
      "enum": [
        "basic",
        "standard"
      ],
      "type": "string",
      "description": "Defaults to the voice's tier, else basic."
    },
    "audioTrack": {
      "type": "boolean",
      "description": "Also return the dubbed audio as M4A."
    },
    "maxCredits": {
      "type": "number",
      "minimum": 0,
      "description": "Spending cap for this call in credits (1 credit = 1 cent). If the price is higher the call fails with 422 before charging."
    },
    "sourceLanguage": {
      "type": "string",
      "description": "Language of the input captions or speech (ISO 639-1, e.g. en). Omit to auto-detect."
    },
    "targetLanguage": {
      "type": "string",
      "description": "ISO 639-1: en, es, fr, zh, ja, ko, hi, ar, bn, pt, ru, ur, id, de, tr, it, vi."
    },
    "translationJobId": {
      "type": "string",
      "description": "A translate job into targetLanguage."
    },
    "keepOriginalAudio": {
      "enum": [
        "duck",
        "mute"
      ],
      "type": "string",
      "description": "'duck' (default) keeps the original audio at -18 dB under the dubbed voice; 'mute' removes it."
    },
    "transcriptionJobId": {
      "type": "string",
      "description": "Reuses its cues and its stored media."
    },
    "translatedSubtitles": {
      "type": "string",
      "description": "Target-language SRT, VTT, or JSON."
    }
  }
}
dub output schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "id": {
      "type": "string",
      "description": "Job id: pass it to get_job, resume_job, edit_transcript or as transcriptionJobId."
    },
    "kind": {
      "type": "string",
      "description": "Job kind (transcribe, burn, caption, clips, shorts, trim, dub, translate, preview, metadata...)."
    },
    "step": {
      "type": "string",
      "description": "Current pipeline step while running."
    },
    "error": {
      "description": "Failure reason when status is failed."
    },
    "result": {
      "description": "Result when succeeded: url, files[{name, url}], clips, text..."
    },
    "status": {
      "type": "string",
      "description": "queued, running, succeeded or failed."
    },
    "progress": {
      "description": "Progress (0-1) and ETA while running."
    },
    "warnings": {
      "type": "array",
      "items": {},
      "description": "Non-blocking notes."
    },
    "costCents": {
      "type": "number",
      "description": "Credits charged (1 credit = 1 cent)."
    },
    "expiresAt": {
      "description": "When the result files are deleted."
    },
    "refundedCents": {
      "type": "number",
      "description": "Credits refunded after a failure."
    }
  },
  "description": "A job: poll get_job with id until status is succeeded or failed.",
  "additionalProperties": {}
}
dub annotations
{
  "title": "Dub video into another language",
  "readOnlyHint": false,
  "openWorldHint": true,
  "idempotentHint": false,
  "destructiveHint": false
}
generate_metadata — Titles, description, hashtags and chapters
Advertised by the server during the last successful anonymous check.
Open-world

Write publishing metadata from what is said: title options (titleCount, default 5), description, hashtags and YouTube chapters with timestamps, per platform (youtube default, shorts, tiktok, instagram). Pass transcriptionJobId or subtitles (1 credit per platform), or only media (adds 1 credit per minute to transcribe). Written in the video's language unless language is set; context adds creator notes. Waits ~40 s, else poll get_job. Result: platforms.<platform>.{titles, description, hashtags, chapters}.

generate_metadata input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "fileId": {
      "type": "string",
      "description": "Id of a file already uploaded with upload {action:'start'}, upload {action:'start_multipart'}, upload {action:'inline'} or import_url. Pass this or the media URL."
    },
    "context": {
      "type": "string",
      "maxLength": 500,
      "description": "Optional notes for the writer (audience, tone, channel, keywords), max 500 characters."
    },
    "language": {
      "type": "string",
      "description": "Output language. Default: the video's language."
    },
    "mediaUrl": {
      "type": "string",
      "description": "Public https link to the video or audio (direct file, chat attachment URL, Google Drive or Dropbox share link; YouTube is refused). Pass this or fileId."
    },
    "platforms": {
      "type": "array",
      "items": {
        "enum": [
          "youtube",
          "shorts",
          "tiktok",
          "instagram"
        ],
        "type": "string"
      },
      "maxItems": 4,
      "minItems": 1,
      "description": "Platforms to write for (youtube, shorts, tiktok, instagram), 1-4. Default youtube."
    },
    "quoteOnly": {
      "type": "boolean",
      "description": "Free: return the price without starting a job or charging. With media only (no transcript) pass durationSeconds."
    },
    "subtitles": {
      "type": "string",
      "description": "SRT, VTT, or transcript JSON."
    },
    "maxCredits": {
      "type": "number",
      "minimum": 0,
      "description": "Spending cap for this call in credits (1 credit = 1 cent). If the price is higher the call fails with 422 before charging."
    },
    "titleCount": {
      "type": "integer",
      "maximum": 10,
      "minimum": 1,
      "description": "How many title options to return, 1-10. Default 5."
    },
    "durationSeconds": {
      "type": "number",
      "description": "Media length in seconds. Lets the price be computed without fetching media (quoteOnly, quote, plan).",
      "exclusiveMinimum": 0
    },
    "transcriptionJobId": {
      "type": "string",
      "description": "Finished job with captions (transcribe, caption_video, remove_silences, translate)."
    }
  }
}
generate_metadata output schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "id": {
      "type": "string",
      "description": "Job id: pass it to get_job, resume_job, edit_transcript or as transcriptionJobId."
    },
    "kind": {
      "type": "string",
      "description": "Job kind (transcribe, burn, caption, clips, shorts, trim, dub, translate, preview, metadata...)."
    },
    "step": {
      "type": "string",
      "description": "Current pipeline step while running."
    },
    "error": {
      "description": "Failure reason when status is failed."
    },
    "result": {
      "description": "Result when succeeded: url, files[{name, url}], clips, text..."
    },
    "status": {
      "type": "string",
      "description": "queued, running, succeeded or failed."
    },
    "progress": {
      "description": "Progress (0-1) and ETA while running."
    },
    "warnings": {
      "type": "array",
      "items": {},
      "description": "Non-blocking notes."
    },
    "costCents": {
      "type": "number",
      "description": "Credits charged (1 credit = 1 cent)."
    },
    "expiresAt": {
      "description": "When the result files are deleted."
    },
    "refundedCents": {
      "type": "number",
      "description": "Credits refunded after a failure."
    }
  },
  "description": "A job: poll get_job with id until status is succeeded or failed.",
  "additionalProperties": {}
}
generate_metadata annotations
{
  "title": "Titles, description, hashtags and chapters",
  "readOnlyHint": false,
  "openWorldHint": true,
  "idempotentHint": false,
  "destructiveHint": false
}
remove_silences — Remove silences and filler words
Advertised by the server during the last successful anonymous check.
Open-world

Cut silences and filler words (uh, um, este...) from a talking video. Needs a transcript (transcriptionJobId or subtitles) plus the media. Returns the cut MP4, retimed SRT/VTT/JSON and stats (kept and removed seconds, cuts). silenceGapSeconds and paddingSeconds tune cuts; fillerMode clear (default) or aggressive (also like, you know, o sea...); removeFillers:false keeps fillers. burnCaptions:true also burns the retimed captions. Price: 3 credits per kept minute, +4 with burnCaptions; quoteOnly:true prices it free. For highlights use create_clips.

remove_silences input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "fileId": {
      "type": "string",
      "description": "Id of a file already uploaded with upload {action:'start'}, upload {action:'start_multipart'}, upload {action:'inline'} or import_url. Pass this or the media URL."
    },
    "preset": {
      "type": "string",
      "description": "With burnCaptions: preset id or name (or custom:cp_...). Default Clarity."
    },
    "autoFit": {
      "type": "boolean",
      "description": "Default true: caption size, words per caption and a safe zone follow the video shape. false keeps the preset's exact sizes."
    },
    "fillers": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "maxItems": 50,
      "description": "Extra fillers to always cut, words or phrases."
    },
    "mediaUrl": {
      "type": "string",
      "description": "Public https link to the video or audio (direct file, chat attachment URL, Google Drive or Dropbox share link; YouTube is refused). Pass this or fileId."
    },
    "platform": {
      "type": "string",
      "description": "With burnCaptions: tiktok, reels, shorts, ... for safe zones."
    },
    "faceAvoid": {
      "type": "boolean",
      "description": "true = move captions off faces (samples faces at 2 fps, same price; result.faceAvoid.faceLayout). Shortcut for styleOverrides.faceAvoid."
    },
    "quoteOnly": {
      "type": "boolean",
      "description": "Free: return the price for durationSeconds without starting a job or charging (upper bound: every second kept)."
    },
    "subtitles": {
      "type": "string",
      "description": "Existing captions as SRT, WebVTT or AwesomeVideo JSON text. Skips transcription (no transcription charge)."
    },
    "fillerMode": {
      "enum": [
        "clear",
        "aggressive"
      ],
      "type": "string",
      "description": "'clear' (default) cuts only unambiguous fillers (uh, um, er, hmm); 'aggressive' also cuts standalone like, you know, I mean, o sea, bueno..."
    },
    "maxCredits": {
      "type": "number",
      "minimum": 0,
      "description": "Spending cap for this call in credits (1 credit = 1 cent). If the price is higher the call fails with 422 before charging."
    },
    "keepFillers": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "maxItems": 50,
      "description": "Fillers to keep, e.g. ['like']."
    },
    "burnCaptions": {
      "type": "boolean",
      "description": "Burn the retimed captions in the same job."
    },
    "brandPresetId": {
      "type": "string",
      "description": "Id from manage_preset {action:'create', type:'brand'}: applies its font, color, position and logo on top of the preset."
    },
    "removeFillers": {
      "type": "boolean",
      "description": "Default true: cut filler words (uh, um...). false keeps every filler."
    },
    "detectSilences": {
      "type": "boolean",
      "description": "Default true: ffmpeg silencedetect also cuts long pauses."
    },
    "highlightColor": {
      "type": "string",
      "description": "#RRGGBB for highlightWords. Default #FACC15."
    },
    "highlightWords": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "maxItems": 200,
      "description": "Shortcut: words or phrases to color in every caption (accent/case-insensitive), e.g. [\"AwesomeVideo\", \"gratis\"]. Maps to styleOverrides.wordHighlights rule {id:\"custom\", words, color}. Same price."
    },
    "paddingSeconds": {
      "type": "number",
      "maximum": 0.3,
      "minimum": 0,
      "description": "Kept on each side of a cut. Default 0.08."
    },
    "silenceNoiseDb": {
      "type": "number",
      "maximum": -10,
      "minimum": -80,
      "description": "Silence threshold in dB. Default -35."
    },
    "styleOverrides": {
      "type": "object",
      "description": "Per-call style changes deep-merged onto the preset (same fields as get_catalog {kind:'presets'} style; null removes a field), validated with the renderer schema and bundled fonts. Example {\"fontSize\":72,\"maxWordsPerCaption\":2,\"wordEntrance\":\"bounce\"}. Same price. No need to manage_preset {action:'create', type:'custom'}. Every field with examples: get_catalog {kind:'styles'}.",
      "propertyNames": {
        "type": "string"
      },
      "additionalProperties": {}
    },
    "durationSeconds": {
      "type": "number",
      "description": "Source length for quoteOnly.",
      "exclusiveMinimum": 0
    },
    "silenceGapSeconds": {
      "type": "number",
      "maximum": 3,
      "minimum": 0.2,
      "description": "Cut pauses longer than this. Default 0.5."
    },
    "transcriptionJobId": {
      "type": "string",
      "description": "Id of a finished transcribe or caption_video job whose transcript to reuse (no new transcription charge)."
    }
  }
}
remove_silences output schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "id": {
      "type": "string",
      "description": "Job id: pass it to get_job, resume_job, edit_transcript or as transcriptionJobId."
    },
    "kind": {
      "type": "string",
      "description": "Job kind (transcribe, burn, caption, clips, shorts, trim, dub, translate, preview, metadata...)."
    },
    "step": {
      "type": "string",
      "description": "Current pipeline step while running."
    },
    "error": {
      "description": "Failure reason when status is failed."
    },
    "result": {
      "description": "Result when succeeded: url, files[{name, url}], clips, text..."
    },
    "status": {
      "type": "string",
      "description": "queued, running, succeeded or failed."
    },
    "progress": {
      "description": "Progress (0-1) and ETA while running."
    },
    "warnings": {
      "type": "array",
      "items": {},
      "description": "Non-blocking notes."
    },
    "costCents": {
      "type": "number",
      "description": "Credits charged (1 credit = 1 cent)."
    },
    "expiresAt": {
      "description": "When the result files are deleted."
    },
    "refundedCents": {
      "type": "number",
      "description": "Credits refunded after a failure."
    }
  },
  "description": "A job: poll get_job with id until status is succeeded or failed.",
  "additionalProperties": {}
}
remove_silences annotations
{
  "title": "Remove silences and filler words",
  "readOnlyHint": false,
  "openWorldHint": true,
  "idempotentHint": false,
  "destructiveHint": false
}
request_review — Request human review before burning
Advertised by the server during the last successful anonymous check.
Open-world

Free. Use when a person wants to check the captions before they are burned (names, slang, brand words). Pass a finished transcriptionJobId and the preset or brandPresetId. Returns reviewUrl: a private web editor link (no login, up to 7 days) where they fix text and timing and press Approve or Reject. Only on Approve does the burn run and charge (4 credits per minute). Follow with get_review, or webhookUrl / notifyEmail for review.approved, review.rejected and review.expired events.

request_review input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "required": [
    "transcriptionJobId"
  ],
  "properties": {
    "preset": {
      "type": "string",
      "description": "Preset id or name for the burn after approval."
    },
    "autoFit": {
      "type": "boolean",
      "description": "Default true: caption size, words per caption (4 on 9:16, 5 on 1:1, 7 on 16:9), and a default safe zone follow the video shape, so text reads the same at 720p and 1080p and stays clear of app UI. Pass false only when the user wants the preset's exact fixed pixel sizes. Same price."
    },
    "combined": {
      "type": "boolean",
      "description": "Also return SRT/VTT with the burned MP4."
    },
    "platform": {
      "type": "string",
      "description": "Target platform (tiktok, reels, shorts, ...) for safe-zone placement, when supported by burn_captions."
    },
    "faceAvoid": {
      "type": "boolean",
      "description": "true = move captions off faces (samples faces at 2 fps, same price; result.faceAvoid.faceLayout). Shortcut for styleOverrides.faceAvoid."
    },
    "maxCredits": {
      "type": "number",
      "minimum": 0,
      "description": "Refuse the burn on approval if it would exceed this many cents."
    },
    "webhookUrl": {
      "type": "string",
      "description": "Gets review.approved / review.rejected / review.expired events and the burn job result when it finishes."
    },
    "notifyEmail": {
      "type": "string",
      "description": "Email address that gets a link when the job finishes or fails."
    },
    "instructions": {
      "type": "string",
      "maxLength": 500,
      "description": "Shown to the reviewer, e.g. 'Revisa nombres de productos'."
    },
    "brandPresetId": {
      "type": "string",
      "description": "Id from manage_preset {action:'create', type:'brand'}: applies its font, color, position and logo on top of the preset."
    },
    "expiresInDays": {
      "type": "number",
      "maximum": 7,
      "minimum": 1,
      "description": "Default 7."
    },
    "highlightColor": {
      "type": "string",
      "description": "#RRGGBB for highlightWords. Default #FACC15."
    },
    "highlightWords": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "maxItems": 200,
      "description": "Shortcut: words or phrases to color in every caption (accent/case-insensitive), e.g. [\"AwesomeVideo\", \"gratis\"]. Maps to styleOverrides.wordHighlights rule {id:\"custom\", words, color}. Same price."
    },
    "styleOverrides": {
      "type": "object",
      "description": "Per-call style changes deep-merged onto the preset (same fields as get_catalog {kind:'presets'} style; null removes a field), validated with the renderer schema and bundled fonts. Example {\"fontSize\":72,\"maxWordsPerCaption\":2,\"wordEntrance\":\"bounce\"}. Same price. No need to manage_preset {action:'create', type:'custom'}. Every field with examples: get_catalog {kind:'styles'}.",
      "propertyNames": {
        "type": "string"
      },
      "additionalProperties": {}
    },
    "transcriptionJobId": {
      "type": "string",
      "description": "Succeeded transcribe job id. Its media must still be stored (48 h)."
    }
  }
}
request_review output schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "total": {
      "type": "number",
      "description": "Total number of items (paginated lists)."
    },
    "result": {
      "description": "The value, when the tool returns something other than an object."
    },
    "hasMore": {
      "type": "boolean",
      "description": "true when more items are available (paginated lists)."
    },
    "nextCursor": {
      "type": "string",
      "description": "Pass as cursor for the next page (paginated lists)."
    }
  },
  "description": "Tool result as JSON.",
  "additionalProperties": {}
}
request_review annotations
{
  "title": "Request human review before burning",
  "readOnlyHint": false,
  "openWorldHint": true,
  "idempotentHint": false,
  "destructiveHint": false
}
get_review — Get review
Advertised by the server during the last successful anonymous check.
Advertised read-only

Check a human review created by request_review: awaiting_review, approved (with burnJobId and, when finished, the burned video URL), rejected (note says why; nothing charged), or expired. Free, read-only; needs the key that created it. Poll it after sharing reviewUrl; once burnJobId exists you can also poll get_job for that burn.

get_review input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "required": [
    "reviewId"
  ],
  "properties": {
    "reviewId": {
      "type": "string",
      "description": "Review id returned by request_review."
    }
  }
}
get_review output schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "total": {
      "type": "number",
      "description": "Total number of items (paginated lists)."
    },
    "result": {
      "description": "The value, when the tool returns something other than an object."
    },
    "hasMore": {
      "type": "boolean",
      "description": "true when more items are available (paginated lists)."
    },
    "nextCursor": {
      "type": "string",
      "description": "Pass as cursor for the next page (paginated lists)."
    }
  },
  "description": "Tool result as JSON.",
  "additionalProperties": {}
}
get_review annotations
{
  "title": "Get review",
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
get_glossary — Get saved glossary
Advertised by the server during the last successful anonymous check.
Advertised read-only

Read the saved transcription glossary of this account (or key): correct spellings with their aliases (what speech-to-text writes instead) and do-not-translate terms. Free, read-only; needs a key. Every transcribe and translate applies it automatically, so read it to check why a word came out as it did. Change it with update_glossary {action:'save'} or update_glossary {action:'delete'}.

get_glossary input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {}
}
get_glossary output schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "count": {
      "type": "number",
      "description": "Number of terms."
    },
    "entries": {
      "type": "array",
      "items": {},
      "description": "Saved terms: {term, aliases, doNotTranslate}."
    }
  },
  "description": "Saved glossary.",
  "additionalProperties": {}
}
get_glossary annotations
{
  "title": "Get saved glossary",
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
get_job — Get job
Advertised by the server during the last successful anonymous check.
Advertised read-only

Read any job. Includes status, step (queued, transcribe, translate, burn, finalize, done, failed), progress (0-100, burn uses real ffmpeg progress), eta_seconds and estimatedCompletionAt (from media length x rolling per-step averages), pollAfterSeconds (wait that long before the next poll), cost, and an expiring result URL when the job succeeded. A failed caption job with resumable:true can be restarted with resume_job.

get_job input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "required": [
    "jobId"
  ],
  "properties": {
    "jobId": {
      "type": "string",
      "description": "Job id returned by transcribe or burn_captions."
    }
  }
}
get_job output schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "id": {
      "type": "string",
      "description": "Job id: pass it to get_job, resume_job, edit_transcript or as transcriptionJobId."
    },
    "kind": {
      "type": "string",
      "description": "Job kind (transcribe, burn, caption, clips, shorts, trim, dub, translate, preview, metadata...)."
    },
    "step": {
      "type": "string",
      "description": "Current pipeline step while running."
    },
    "error": {
      "description": "Failure reason when status is failed."
    },
    "result": {
      "description": "Result when succeeded: url, files[{name, url}], clips, text..."
    },
    "status": {
      "type": "string",
      "description": "queued, running, succeeded or failed."
    },
    "progress": {
      "description": "Progress (0-1) and ETA while running."
    },
    "warnings": {
      "type": "array",
      "items": {},
      "description": "Non-blocking notes."
    },
    "costCents": {
      "type": "number",
      "description": "Credits charged (1 credit = 1 cent)."
    },
    "expiresAt": {
      "description": "When the result files are deleted."
    },
    "refundedCents": {
      "type": "number",
      "description": "Credits refunded after a failure."
    }
  },
  "description": "A job: poll get_job with id until status is succeeded or failed.",
  "additionalProperties": {}
}
get_job annotations
{
  "title": "Get job",
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
list_jobs — List jobs
Advertised by the server during the last successful anonymous check.
Advertised read-only

List recent jobs (transcribe, burn, caption_video, clips, dub, trim...) newest first for this key, or for every key on the account when the key is claimed: id, kind, status, created time, credits charged, and a download URL while the result is still stored. Free, read-only; needs a key. Paginated: limit (default 50, max 100) and cursor = nextCursor from the previous page. For one job's full status, progress and files use get_job; for credit totals per day use get_account.

list_jobs input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "limit": {
      "type": "integer",
      "maximum": 100,
      "description": "Page size, 1-100. Default 50.",
      "exclusiveMinimum": 0
    },
    "cursor": {
      "type": "string",
      "description": "Opaque nextCursor from the previous page. Omit for the first page."
    }
  }
}
list_jobs output schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "jobs": {
      "type": "array",
      "items": {},
      "description": "Jobs, newest first: id, kind, status, created, credits charged, download URL while available."
    },
    "nextCursor": {
      "description": "Pass as cursor for the next page; null on the last page."
    }
  },
  "description": "Page of jobs.",
  "additionalProperties": {}
}
list_jobs annotations
{
  "title": "List jobs",
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
resume_job — Resume a failed caption job
Advertised by the server during the last successful anonymous check.
Open-world

Continue a failed job (caption_video, transcribe, create_clips, dub, remove_silences, generate_metadata) from where it stopped instead of starting over. Reuses saved transcription chunks and finished steps, so you pay only what is left (often just the burn); the failed job stays refunded. Idempotent: repeating returns the same resumed job, never a second charge. Returns a new job id to poll with get_job. 422 resume_not_supported or resume_media_expired: call the original tool again. 409 job_not_resumable (no_speech): nothing to resume.

resume_job input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "required": [
    "jobId"
  ],
  "properties": {
    "jobId": {
      "type": "string",
      "description": "Id of the failed caption_video job."
    },
    "maxCredits": {
      "type": "number",
      "minimum": 0,
      "description": "Refuse if resuming would cost more than this."
    },
    "webhookUrl": {
      "type": "string",
      "description": "https URL that receives a POST with the finished job (status, result URLs, credits charged)."
    },
    "notifyEmail": {
      "type": "string",
      "description": "Email address that gets a link when the job finishes or fails."
    }
  }
}
resume_job output schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "id": {
      "type": "string",
      "description": "Job id: pass it to get_job, resume_job, edit_transcript or as transcriptionJobId."
    },
    "kind": {
      "type": "string",
      "description": "Job kind (transcribe, burn, caption, clips, shorts, trim, dub, translate, preview, metadata...)."
    },
    "step": {
      "type": "string",
      "description": "Current pipeline step while running."
    },
    "error": {
      "description": "Failure reason when status is failed."
    },
    "result": {
      "description": "Result when succeeded: url, files[{name, url}], clips, text..."
    },
    "status": {
      "type": "string",
      "description": "queued, running, succeeded or failed."
    },
    "progress": {
      "description": "Progress (0-1) and ETA while running."
    },
    "warnings": {
      "type": "array",
      "items": {},
      "description": "Non-blocking notes."
    },
    "costCents": {
      "type": "number",
      "description": "Credits charged (1 credit = 1 cent)."
    },
    "expiresAt": {
      "description": "When the result files are deleted."
    },
    "refundedCents": {
      "type": "number",
      "description": "Credits refunded after a failure."
    }
  },
  "description": "A job: poll get_job with id until status is succeeded or failed.",
  "additionalProperties": {}
}
resume_job annotations
{
  "title": "Resume a failed caption job",
  "readOnlyHint": false,
  "openWorldHint": true,
  "idempotentHint": false,
  "destructiveHint": false
}
upload — Upload a file
Advertised by the server during the last successful anonymous check.
Advertised destructive

Free. Put your own video or audio file into AwesomeVideo and get a fileId for caption_video, transcribe, burn_captions, create_clips, remove_silences or preview. action start: one single-use PUT URL (valid 15 min, files up to 80 MB); start_multipart: parts[] of PUT URLs for files over 80 MB (up to 2048 MB / 3 h) or flaky connections; status: missingParts of a multipart upload; complete: finish a multipart upload after every part is PUT; abort: cancel an unfinished multipart upload (deletes its parts); inline: send a clip of up to 10 MB as base64 in one call. For a public link use import_url instead. Up to 30 uploads per hour.

upload input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "required": [
    "action"
  ],
  "properties": {
    "data": {
      "type": "string",
      "description": "File bytes as base64 (a data: URL prefix is accepted)."
    },
    "action": {
      "enum": [
        "start",
        "start_multipart",
        "status",
        "complete",
        "abort",
        "inline"
      ],
      "type": "string",
      "description": "start (single PUT URL), start_multipart, status, complete, abort, or inline (base64 up to 10 MB)."
    },
    "fileId": {
      "anyOf": [
        {
          "type": "string",
          "description": "fileId from upload {action:'start_multipart'}."
        },
        {
          "type": "string",
          "description": "fileId returned by upload {action:'start_multipart'}, after every part has been PUT."
        },
        {
          "type": "string",
          "description": "fileId of an unfinished upload from upload {action:'start_multipart'}. Completed uploads are not affected."
        }
      ],
      "description": "fileId from upload {action:'start_multipart'}."
    },
    "filename": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 200,
          "description": "File name, e.g. clip.mp4."
        },
        {
          "type": "string",
          "maxLength": 200,
          "description": "File name, e.g. talk.mp4."
        },
        {
          "type": "string",
          "maxLength": 200,
          "description": "File name to store, with extension (e.g. talk.mp4); used for the content type and download name. Max 200 characters."
        }
      ],
      "description": "File name, e.g. clip.mp4."
    },
    "sizeBytes": {
      "anyOf": [
        {
          "type": "integer",
          "maximum": 9007199254740991,
          "description": "Exact file size in bytes (the PUT must match).",
          "exclusiveMinimum": 0
        },
        {
          "type": "integer",
          "maximum": 9007199254740991,
          "description": "Exact file size in bytes.",
          "exclusiveMinimum": 0
        }
      ],
      "description": "Exact file size in bytes (the PUT must match)."
    },
    "contentType": {
      "anyOf": [
        {
          "type": "string",
          "description": "video/* or audio/*, e.g. video/mp4."
        },
        {
          "type": "string",
          "description": "video/* or audio/*."
        }
      ],
      "description": "video/* or audio/*, e.g. video/mp4."
    },
    "partSizeBytes": {
      "type": "integer",
      "maximum": 9007199254740991,
      "description": "Bytes per part, 5242880-99614720. Default 67108864 (64 MB).",
      "exclusiveMinimum": 0
    }
  }
}
upload output schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "total": {
      "type": "number",
      "description": "Total number of items (paginated lists)."
    },
    "result": {
      "description": "The value, when the tool returns something other than an object."
    },
    "hasMore": {
      "type": "boolean",
      "description": "true when more items are available (paginated lists)."
    },
    "nextCursor": {
      "type": "string",
      "description": "Pass as cursor for the next page (paginated lists)."
    }
  },
  "description": "Tool result as JSON.",
  "additionalProperties": {}
}
upload annotations
{
  "title": "Upload a file",
  "readOnlyHint": false,
  "openWorldHint": false,
  "idempotentHint": false,
  "destructiveHint": true
}
burn_captions — Burn captions into a video
Advertised by the server during the last successful anonymous check.
Open-world

Burn existing captions (subtitles or transcriptionJobId) into a video with a preset or brandPresetId. mode server (default): renders the MP4 on our servers, 4 credits per audio minute (1 credit = 1 cent), 402 insufficient_balance with checkoutUrl when short. mode client_script: free, returns an ASS script and resolved style to burn in your own player or browser; nothing runs or is charged. platform keeps captions inside that app's safe zone at the same price ('subtítulos para TikTok' -> platform=tiktok). For video in, video out in one call use caption_video.

burn_captions input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "mode": {
      "enum": [
        "server",
        "client_script"
      ],
      "type": "string",
      "description": "server (default): paid MP4 render, 4 credits per audio minute. client_script: free ASS script to burn in your own player or browser; nothing is charged."
    },
    "width": {
      "type": "integer",
      "maximum": 9007199254740991,
      "description": "Output width in pixels for the ASS PlayRes. Default 1280.",
      "exclusiveMinimum": 0
    },
    "fileId": {
      "type": "string",
      "description": "Id of a file already uploaded with upload {action:'start'}, upload {action:'start_multipart'}, upload {action:'inline'} or import_url. Pass this or the media URL."
    },
    "height": {
      "type": "integer",
      "maximum": 9007199254740991,
      "description": "Output height in pixels for the ASS PlayRes. Default 720.",
      "exclusiveMinimum": 0
    },
    "preset": {
      "anyOf": [
        {
          "type": "string",
          "description": "Preset id or name, or custom:cp_... for your own saved preset. Use presetId or presetName too."
        },
        {
          "type": "string",
          "description": "Caption preset: id, slug or name from get_catalog {kind:'presets'} (e.g. 'hormozi-style', 'Clarity') or custom:cp_... from manage_preset {action:'create', type:'custom'}."
        }
      ],
      "description": "Preset id or name, or custom:cp_... for your own saved preset. Use presetId or presetName too."
    },
    "autoFit": {
      "type": "boolean",
      "description": "Default true: caption size, words per caption (4 on 9:16, 5 on 1:1, 7 on 16:9), and a default safe zone follow the video shape, so text reads the same at 720p and 1080p and stays clear of app UI. Pass false only when the user wants the preset's exact fixed pixel sizes. Same price."
    },
    "combined": {
      "type": "boolean",
      "description": "Also return SRT, VTT, and transcript JSON. Same burn price."
    },
    "mediaUrl": {
      "type": "string",
      "format": "uri",
      "description": "Public https link to the video or audio (direct file, chat attachment URL, Google Drive or Dropbox share link; YouTube is refused). Pass this or fileId."
    },
    "platform": {
      "type": "string",
      "description": "Where the video will be posted: tiktok, instagram_reels, youtube_shorts, facebook_reels, snapchat_spotlight, linkedin, youtube, x (aliases like reels, instagram, shorts, snap, twitter; case-insensitive). Keeps captions out of that app's buttons and text. If the user says \"para TikTok\" / \"for Reels\", pass it; if they did not say and it matters, ask. Same price. Unknown values return 422 invalid_platform before any charge. See get_catalog {kind:'platforms'}."
    },
    "presetId": {
      "type": "string",
      "description": "Same as preset (kept for older clients): a preset id from get_catalog {kind:'presets'} or custom:cp_...."
    },
    "faceAvoid": {
      "type": "boolean",
      "description": "true = move captions off faces (samples faces at 2 fps, same price; result.faceAvoid.faceLayout). Shortcut for styleOverrides.faceAvoid."
    },
    "subtitles": {
      "anyOf": [
        {
          "type": "string",
          "description": "SRT, VTT, or JSON cues."
        },
        {
          "type": "string",
          "description": "Existing captions as SRT, WebVTT or AwesomeVideo JSON text. Skips transcription (no transcription charge)."
        }
      ],
      "description": "SRT, VTT, or JSON cues."
    },
    "maxCredits": {
      "type": "number",
      "minimum": 0,
      "description": "Spending cap for this call in credits (1 credit = 1 cent). If the price is higher the call fails with 422 before charging."
    },
    "presetName": {
      "type": "string",
      "description": "Same as preset, by display name (e.g. 'Clarity')."
    },
    "webhookUrl": {
      "type": "string",
      "description": "https URL that receives a POST with the finished job (status, result URLs, credits charged)."
    },
    "audioVisual": {
      "type": "object",
      "properties": {
        "ink": {
          "type": "string",
          "description": "Text/line colour #hex. Default: the design's, or auto from the paper."
        },
        "width": {
          "type": "integer",
          "maximum": 9007199254740991,
          "minimum": -9007199254740991
        },
        "accent": {
          "type": "string",
          "description": "Accent colour #hex (spoken word, needle, seal...). Default: the design's."
        },
        "aspect": {
          "enum": [
            "9:16",
            "16:9",
            "1:1",
            "4:5"
          ],
          "type": "string",
          "description": "Frame shape; default from platform, else 9:16."
        },
        "height": {
          "type": "integer",
          "maximum": 9007199254740991,
          "minimum": -9007199254740991
        },
        "enabled": {
          "type": "boolean",
          "description": "false: paper + captions, no design."
        },
        "episode": {
          "anyOf": [
            {
              "type": "string",
              "maxLength": 12
            },
            {
              "type": "number"
            }
          ],
          "description": "Episode label or number (max 12 chars), printed after Nº. Empty: left out."
        },
        "speaker": {
          "type": "string",
          "maxLength": 60,
          "description": "Speaker / host name for bylines (max 60). Empty: left out."
        },
        "variant": {
          "type": "string",
          "description": "Design id: swiss-grid | braun-radio | riso | editorial-cover | bauhaus | continuous-line | vinyl | type-wave | duotone-portrait | ma (default editorial-cover). Retired ids still work as aliases with a warning: bars→swiss-grid, ribbon→continuous-line, rings→ma, spectrogram→riso, skyline→bauhaus, silkline→type-wave, ivory→editorial-cover, halo→vinyl, needle→braun-radio, mono→duotone-portrait. get_catalog {kind:'audio_visuals'} describes each design."
        },
        "overlays": {
          "type": "array",
          "items": {
            "type": "object",
            "propertyNames": {
              "type": "string"
            },
            "additionalProperties": {}
          },
          "maxItems": 8,
          "description": "Up to 8 image (imageUrl, PNG/JPEG/WebP <=5 MB) or text items {kind, x, y, width, height, start, end, ...} in frame pixels."
        },
        "showName": {
          "type": "string",
          "maxLength": 60,
          "description": "Show / podcast name (max 60). Empty: left out (mastheads fall back to Podcast)."
        },
        "background": {
          "type": "string",
          "description": "Paper colour #rgb/#rrggbb (default: the design's). Ink switches automatically for contrast."
        },
        "captionMode": {
          "enum": [
            "integrated",
            "preset"
          ],
          "type": "string",
          "description": "integrated (default): the design typesets the captions word by word; preset: your caption preset draws them."
        },
        "coverFileId": {
          "type": "string",
          "description": "Same as coverImageUrl but a fileId from upload {action:'start'}."
        },
        "contrastGuard": {
          "type": "boolean",
          "description": "Preset mode (default true): white text on a light design switches to the design's ink so it stays legible."
        },
        "coverImageUrl": {
          "type": "string",
          "description": "Public https PNG/JPEG/WebP (max 5 MB) for the cover/host image slot (vinyl, duotone-portrait). Fetched before any charge."
        }
      },
      "description": "Audio-only input (mp3, m4a, wav...): an editorial podcast design plus captions, drawn on the server by the web editor's own code, same price as the burn. {variant: swiss-grid | braun-radio | riso | editorial-cover | bauhaus | continuous-line | vinyl | type-wave | duotone-portrait | ma (default editorial-cover), showName (<=60), episode (<=12), speaker (<=60), coverImageUrl (https) or coverFileId (PNG/JPEG/WebP <=5 MB; shown by vinyl, duotone-portrait), background/accent/ink (#hex; ink auto from paper), captionMode integrated (default: the design typesets the captions) | preset (your caption preset draws), contrastGuard (default true), aspect 9:16|16:9|1:1|4:5 or width+height, overlays (<=8)}. Retired ids still work as aliases with a warning: bars→swiss-grid, ribbon→continuous-line, rings→ma, spectrogram→riso, skyline→bauhaus, silkline→type-wave, ivory→editorial-cover, halo→vinyl, needle→braun-radio, mono→duotone-portrait. On a video input: 422 audio_visual_needs_audio_input, not charged. Catalog: GET /v1/audio-visuals (MCP get_catalog {kind:'audio_visuals'}), free.",
      "additionalProperties": {}
    },
    "notifyEmail": {
      "type": "string",
      "description": "Email address that gets a link when the job finishes or fails."
    },
    "brandPresetId": {
      "type": "string",
      "description": "Saved font, color, position, and optional logo."
    },
    "highlightColor": {
      "type": "string",
      "description": "#RRGGBB for highlightWords. Default #FACC15."
    },
    "highlightWords": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "maxItems": 200,
      "description": "Shortcut: words or phrases to color in every caption (accent/case-insensitive), e.g. [\"AwesomeVideo\", \"gratis\"]. Maps to styleOverrides.wordHighlights rule {id:\"custom\", words, color}. Same price."
    },
    "styleOverrides": {
      "type": "object",
      "description": "Per-call style changes deep-merged onto the preset (same fields as get_catalog {kind:'presets'} style; null removes a field), validated with the renderer schema and bundled fonts. Example {\"fontSize\":72,\"maxWordsPerCaption\":2,\"wordEntrance\":\"bounce\"}. Same price. No need to manage_preset {action:'create', type:'custom'}. Every field with examples: get_catalog {kind:'styles'}.",
      "propertyNames": {
        "type": "string"
      },
      "additionalProperties": {}
    },
    "durationSeconds": {
      "type": "number",
      "description": "Media length in seconds. Lets the price be computed without fetching media (quoteOnly, quote, plan).",
      "exclusiveMinimum": 0
    },
    "transcriptionJobId": {
      "type": "string",
      "description": "Id of a finished transcribe or caption_video job whose transcript to reuse (no new transcription charge)."
    }
  }
}
burn_captions output schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "id": {
      "type": "string",
      "description": "Job id: pass it to get_job, resume_job, edit_transcript or as transcriptionJobId."
    },
    "kind": {
      "type": "string",
      "description": "Job kind (transcribe, burn, caption, clips, shorts, trim, dub, translate, preview, metadata...)."
    },
    "step": {
      "type": "string",
      "description": "Current pipeline step while running."
    },
    "error": {
      "description": "Failure reason when status is failed."
    },
    "result": {
      "description": "Result when succeeded: url, files[{name, url}], clips, text..."
    },
    "status": {
      "type": "string",
      "description": "queued, running, succeeded or failed."
    },
    "progress": {
      "description": "Progress (0-1) and ETA while running."
    },
    "warnings": {
      "type": "array",
      "items": {},
      "description": "Non-blocking notes."
    },
    "costCents": {
      "type": "number",
      "description": "Credits charged (1 credit = 1 cent)."
    },
    "expiresAt": {
      "description": "When the result files are deleted."
    },
    "refundedCents": {
      "type": "number",
      "description": "Credits refunded after a failure."
    }
  },
  "description": "A job: poll get_job with id until status is succeeded or failed.",
  "additionalProperties": {}
}
burn_captions annotations
{
  "title": "Burn captions into a video",
  "readOnlyHint": false,
  "openWorldHint": true,
  "idempotentHint": false,
  "destructiveHint": false
}
get_catalog — Read the AwesomeVideo catalog
Advertised by the server during the last successful anonymous check.
Advertised read-only

Free, read-only, works without a key. Everything you can choose from, by kind: presets (built-in, approved community and, with a key, your custom presets, plus bundled fonts), styles (every caption style field with type, range and examples), voices (dub voices with tier, price and sampleUrl; filter with language and tier), platforms (where videos are posted, with safe zones), audio_visuals (the ten editorial podcast designs for audio-only input). Paginated with limit and cursor; response_format concise (default) drops nested objects such as full style JSON, detailed returns them. Pass ids you find here as preset, voice, platform or audioVisual to the job tools.

get_catalog input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "required": [
    "kind"
  ],
  "properties": {
    "kind": {
      "enum": [
        "presets",
        "styles",
        "voices",
        "platforms",
        "audio_visuals"
      ],
      "type": "string",
      "description": "Which catalog: presets, styles, voices, platforms or audio_visuals."
    },
    "tier": {
      "enum": [
        "basic",
        "standard"
      ],
      "type": "string",
      "description": "'basic' (5 credits/min) or 'standard' (12 credits/min). Omit for both."
    },
    "limit": {
      "type": "integer",
      "maximum": 100,
      "minimum": 1,
      "description": "Page size for the returned list, 1-100. Default 50."
    },
    "cursor": {
      "type": "string",
      "description": "nextCursor from the previous page. Omit for the first page."
    },
    "language": {
      "type": "string",
      "description": "Only voices for this language (ISO 639-1, e.g. es). Omit for all languages."
    },
    "response_format": {
      "enum": [
        "concise",
        "detailed"
      ],
      "type": "string",
      "description": "concise (default): short list items without nested style/example objects, to save tokens. detailed: full objects."
    }
  }
}
get_catalog output schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "total": {
      "type": "number",
      "description": "Total number of items (paginated lists)."
    },
    "result": {
      "description": "The value, when the tool returns something other than an object."
    },
    "hasMore": {
      "type": "boolean",
      "description": "true when more items are available (paginated lists)."
    },
    "nextCursor": {
      "type": "string",
      "description": "Pass as cursor for the next page (paginated lists)."
    }
  },
  "description": "Tool result as JSON.",
  "additionalProperties": {}
}
get_catalog annotations
{
  "title": "Read the AwesomeVideo catalog",
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
estimate — Estimate price and limits (free)
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

Free, never charges, works without a key. Without steps: the credits one operation would cost (operation caption, transcribe, burn, preview, translate, shorts, trim, dub or preview {mode:'sample'}) from durationSeconds, or from mediaUrl/fileId with a key. With steps: prices a whole pipeline of 1-10 steps, checks every limit before you pay (limitViolations with a fix for each), suggests free alternatives and, with a key, says whether the balance covers it. 1 credit = 1 cent. Call it before any paid tool when the cost matters.

estimate input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "steps": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "op"
        ],
        "properties": {
          "op": {
            "enum": [
              "caption",
              "transcribe",
              "translate",
              "burn",
              "shorts",
              "trim",
              "preview",
              "dub",
              "preview {mode:'sample'}"
            ],
            "type": "string"
          },
          "count": {
            "type": "integer",
            "maximum": 9007199254740991,
            "minimum": -9007199254740991
          },
          "voice": {
            "type": "string"
          },
          "reframe": {
            "enum": [
              "face",
              "center"
            ],
            "type": "string"
          },
          "platform": {
            "type": "string",
            "description": "burn, preview, shorts: platform id or alias. Validated, same price."
          },
          "renderer": {
            "enum": [
              "server",
              "client"
            ],
            "type": "string"
          },
          "voiceTier": {
            "enum": [
              "basic",
              "standard"
            ],
            "type": "string"
          },
          "maxSeconds": {
            "type": "number"
          },
          "minSeconds": {
            "type": "number"
          },
          "keepSeconds": {
            "type": "number"
          },
          "translateTo": {
            "type": "string",
            "description": "caption only."
          },
          "sourceLanguage": {
            "type": "string"
          },
          "targetLanguage": {
            "type": "string"
          }
        }
      },
      "maxItems": 10,
      "minItems": 1,
      "description": "Ordered pipeline, 1-10 steps: [{op: caption|transcribe|translate|burn|shorts|trim|preview|dub|preview {mode:'sample'}, ...op options}]."
    },
    "fileId": {
      "type": "string",
      "description": "Uploaded file id; its duration is read when durationSeconds is not given (needs a key)."
    },
    "source": {
      "type": "object",
      "properties": {
        "via": {
          "enum": [
            "upload",
            "url"
          ],
          "type": "string"
        },
        "bytes": {
          "type": "number",
          "minimum": 0
        },
        "mediaUrl": {
          "type": "string"
        },
        "transcriptCues": {
          "type": "integer",
          "maximum": 9007199254740991,
          "minimum": 0
        },
        "durationSeconds": {
          "type": "number",
          "exclusiveMinimum": 0
        }
      },
      "description": "What you know about the input: {durationSeconds, bytes, via: url|upload, transcriptCues, mediaUrl}. Used to price and check limits."
    },
    "mediaUrl": {
      "type": "string",
      "description": "Public media link; its duration is probed when durationSeconds is not given (needs a key)."
    },
    "operation": {
      "enum": [
        "caption",
        "transcribe",
        "burn",
        "preview",
        "translate",
        "shorts",
        "trim",
        "dub",
        "preview {mode:'sample'}"
      ],
      "type": "string",
      "description": "What to price: caption (one-call caption_video), transcribe, burn, preview, translate, shorts, trim, dub or preview {mode:'sample'} (always 0)."
    },
    "voiceTier": {
      "enum": [
        "basic",
        "standard"
      ],
      "type": "string",
      "description": "dub only."
    },
    "translateTo": {
      "type": "string",
      "description": "caption only: include translation in the price."
    },
    "hasTranscript": {
      "type": "boolean",
      "description": "true when you already have a transcript (subtitles or transcriptionJobId): transcription is not priced."
    },
    "hasTranslation": {
      "type": "boolean",
      "description": "true when you already have the translated captions: translation is not priced."
    },
    "targetLanguage": {
      "type": "string",
      "description": "dub only. Checked against the supported voices."
    },
    "durationSeconds": {
      "type": "number",
      "description": "Media length in seconds. Enough on its own: no key or media needed.",
      "exclusiveMinimum": 0
    }
  }
}
estimate output schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "total": {
      "type": "number",
      "description": "Total number of items (paginated lists)."
    },
    "result": {
      "description": "The value, when the tool returns something other than an object."
    },
    "hasMore": {
      "type": "boolean",
      "description": "true when more items are available (paginated lists)."
    },
    "nextCursor": {
      "type": "string",
      "description": "Pass as cursor for the next page (paginated lists)."
    }
  },
  "description": "Tool result as JSON.",
  "additionalProperties": {}
}
estimate annotations
{
  "title": "Estimate price and limits (free)",
  "readOnlyHint": true,
  "openWorldHint": true,
  "idempotentHint": true,
  "destructiveHint": false
}
preview — Preview captions on the video
Advertised by the server during the last successful anonymous check.
Open-world

See captions on the real video before paying for a burn. mode sample: FREE contact sheet comparing up to 12 presets on real frames (no transcription, 30 sheets/hour); returns sheetUrl, per-preset frames and captionVideoArgs to pass to caption_video. mode still (default): one preset as a PNG exactly as burn_captions draws it; mode clip: an MP4 of up to 5 s. still and clip cost at most 1 credit flat and need captions (subtitles or transcriptionJobId). Media: mediaUrl/sourceUrl or fileId.

preview input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "mode": {
      "enum": [
        "sample",
        "still",
        "clip"
      ],
      "type": "string",
      "description": "sample: FREE contact sheet comparing up to 12 presets on the real frame, never charges. still (default): one preset as a PNG, at most 1 credit. clip: one preset as an MP4 of up to 5 s, at most 1 credit."
    },
    "text": {
      "type": "string",
      "maxLength": 80,
      "description": "Preview only: sample phrase."
    },
    "fileId": {
      "type": "string",
      "description": "Id of a file already uploaded with upload {action:'start'}, upload {action:'start_multipart'}, upload {action:'inline'} or import_url. Pass this or the media URL."
    },
    "preset": {
      "anyOf": [
        {
          "type": "string",
          "description": "Caption preset: id, slug or name from get_catalog {kind:'presets'} (e.g. 'hormozi-style', 'Clarity') or custom:cp_... from manage_preset {action:'create', type:'custom'}."
        },
        {
          "type": "string",
          "description": "One preset (same as caption_video)."
        }
      ],
      "description": "Caption preset: id, slug or name from get_catalog {kind:'presets'} (e.g. 'hormozi-style', 'Clarity') or custom:cp_... from manage_preset {action:'create', type:'custom'}."
    },
    "autoFit": {
      "anyOf": [
        {
          "type": "boolean",
          "description": "Default true: caption size, words per caption (4 on 9:16, 5 on 1:1, 7 on 16:9), and a default safe zone follow the video shape, so text reads the same at 720p and 1080p and stays clear of app UI. Pass false only when the user wants the preset's exact fixed pixel sizes. Same price."
        },
        {
          "type": "boolean",
          "description": "Default true: caption size, words per caption and a safe zone follow the video shape. false keeps the preset's exact sizes."
        }
      ],
      "description": "Default true: caption size, words per caption (4 on 9:16, 5 on 1:1, 7 on 16:9), and a default safe zone follow the video shape, so text reads the same at 720p and 1080p and stays clear of app UI. Pass false only when the user wants the preset's exact fixed pixel sizes. Same price."
    },
    "presets": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "maxItems": 12,
      "description": "Up to 12 presets to compare; default 6 that fit the video shape."
    },
    "fullText": {
      "type": "boolean",
      "description": "Preview only: show all words in one caption (does not match a burn)."
    },
    "language": {
      "type": "string",
      "description": "Spoken language (ISO 639-1) for the quick transcript of the sampled seconds. Omit to auto-detect."
    },
    "mediaUrl": {
      "anyOf": [
        {
          "type": "string",
          "description": "Public https link to the video or audio (direct file, chat attachment URL, Google Drive or Dropbox share link; YouTube is refused). Pass this or fileId."
        },
        {
          "type": "string",
          "description": "Alias of sourceUrl."
        }
      ],
      "description": "Public https link to the video or audio (direct file, chat attachment URL, Google Drive or Dropbox share link; YouTube is refused). Pass this or fileId."
    },
    "platform": {
      "anyOf": [
        {
          "type": "string",
          "description": "Where the video will be posted: tiktok, instagram_reels, youtube_shorts, facebook_reels, snapchat_spotlight, linkedin, youtube, x (aliases like reels, instagram, shorts, snap, twitter; case-insensitive). Keeps captions out of that app's buttons and text. If the user says \"para TikTok\" / \"for Reels\", pass it; if they did not say and it matters, ask. Same price. Unknown values return 422 invalid_platform before any charge. See get_catalog {kind:'platforms'}."
        },
        {
          "type": "string",
          "description": "Where the video will be posted (tiktok, instagram_reels, youtube_shorts, facebook_reels, snapchat_spotlight, linkedin, youtube, x; aliases like reels, shorts, twitter). Keeps captions inside that app's safe zone at the same price."
        }
      ],
      "description": "Where the video will be posted: tiktok, instagram_reels, youtube_shorts, facebook_reels, snapchat_spotlight, linkedin, youtube, x (aliases like reels, instagram, shorts, snap, twitter; case-insensitive). Keeps captions out of that app's buttons and text. If the user says \"para TikTok\" / \"for Reels\", pass it; if they did not say and it matters, ask. Same price. Unknown values return 422 invalid_platform before any charge. See get_catalog {kind:'platforms'}."
    },
    "presetId": {
      "type": "string",
      "description": "Same as preset (kept for older clients): a preset id from get_catalog {kind:'presets'} or custom:cp_...."
    },
    "atSeconds": {
      "anyOf": [
        {
          "type": "number",
          "minimum": 0,
          "description": "Second of the video for the frame (or clip start). Default 0."
        },
        {
          "anyOf": [
            {
              "type": "number",
              "minimum": 0
            },
            {
              "type": "array",
              "items": {
                "type": "number",
                "minimum": 0
              },
              "maxItems": 3,
              "minItems": 1
            }
          ],
          "description": "Preview only: second(s) of the video to show; up to 3 = one sheet."
        }
      ],
      "description": "Second of the video for the frame (or clip start). Default 0."
    },
    "faceAvoid": {
      "anyOf": [
        {
          "type": "boolean",
          "description": "true = move captions off faces (samples faces at 2 fps, same price; result.faceAvoid.faceLayout). Shortcut for styleOverrides.faceAvoid."
        },
        {
          "type": "boolean",
          "description": "true = move captions off faces (samples faces at 2 fps, same price)."
        }
      ],
      "description": "true = move captions off faces (samples faces at 2 fps, same price; result.faceAvoid.faceLayout). Shortcut for styleOverrides.faceAvoid."
    },
    "sourceUrl": {
      "type": "string",
      "description": "Same as caption_video."
    },
    "subtitles": {
      "anyOf": [
        {
          "type": "string",
          "description": "Existing captions as SRT, WebVTT or AwesomeVideo JSON text. Skips transcription (no transcription charge)."
        },
        {
          "type": "string",
          "description": "Preview only: SRT/VTT/JSON captions to show instead of a sample phrase."
        }
      ],
      "description": "Existing captions as SRT, WebVTT or AwesomeVideo JSON text. Skips transcription (no transcription charge)."
    },
    "maxCredits": {
      "type": "number",
      "minimum": 0,
      "description": "Spending cap for this call in credits (1 credit = 1 cent). If the price is higher the call fails with 422 before charging."
    },
    "audioVisual": {
      "type": "object",
      "properties": {
        "ink": {
          "type": "string",
          "description": "Text/line colour #hex. Default: the design's, or auto from the paper."
        },
        "width": {
          "type": "integer",
          "maximum": 9007199254740991,
          "minimum": -9007199254740991
        },
        "accent": {
          "type": "string",
          "description": "Accent colour #hex (spoken word, needle, seal...). Default: the design's."
        },
        "aspect": {
          "enum": [
            "9:16",
            "16:9",
            "1:1",
            "4:5"
          ],
          "type": "string",
          "description": "Frame shape; default from platform, else 9:16."
        },
        "height": {
          "type": "integer",
          "maximum": 9007199254740991,
          "minimum": -9007199254740991
        },
        "enabled": {
          "type": "boolean",
          "description": "false: paper + captions, no design."
        },
        "episode": {
          "anyOf": [
            {
              "type": "string",
              "maxLength": 12
            },
            {
              "type": "number"
            }
          ],
          "description": "Episode label or number (max 12 chars), printed after Nº. Empty: left out."
        },
        "speaker": {
          "type": "string",
          "maxLength": 60,
          "description": "Speaker / host name for bylines (max 60). Empty: left out."
        },
        "variant": {
          "type": "string",
          "description": "Design id: swiss-grid | braun-radio | riso | editorial-cover | bauhaus | continuous-line | vinyl | type-wave | duotone-portrait | ma (default editorial-cover). Retired ids still work as aliases with a warning: bars→swiss-grid, ribbon→continuous-line, rings→ma, spectrogram→riso, skyline→bauhaus, silkline→type-wave, ivory→editorial-cover, halo→vinyl, needle→braun-radio, mono→duotone-portrait. get_catalog {kind:'audio_visuals'} describes each design."
        },
        "overlays": {
          "type": "array",
          "items": {
            "type": "object",
            "propertyNames": {
              "type": "string"
            },
            "additionalProperties": {}
          },
          "maxItems": 8,
          "description": "Up to 8 image (imageUrl, PNG/JPEG/WebP <=5 MB) or text items {kind, x, y, width, height, start, end, ...} in frame pixels."
        },
        "showName": {
          "type": "string",
          "maxLength": 60,
          "description": "Show / podcast name (max 60). Empty: left out (mastheads fall back to Podcast)."
        },
        "background": {
          "type": "string",
          "description": "Paper colour #rgb/#rrggbb (default: the design's). Ink switches automatically for contrast."
        },
        "captionMode": {
          "enum": [
            "integrated",
            "preset"
          ],
          "type": "string",
          "description": "integrated (default): the design typesets the captions word by word; preset: your caption preset draws them."
        },
        "coverFileId": {
          "type": "string",
          "description": "Same as coverImageUrl but a fileId from upload {action:'start'}."
        },
        "contrastGuard": {
          "type": "boolean",
          "description": "Preset mode (default true): white text on a light design switches to the design's ink so it stays legible."
        },
        "coverImageUrl": {
          "type": "string",
          "description": "Public https PNG/JPEG/WebP (max 5 MB) for the cover/host image slot (vinyl, duotone-portrait). Fetched before any charge."
        }
      },
      "description": "Audio-only input (mp3, m4a, wav...): an editorial podcast design plus captions, drawn on the server by the web editor's own code, same price as the burn. {variant: swiss-grid | braun-radio | riso | editorial-cover | bauhaus | continuous-line | vinyl | type-wave | duotone-portrait | ma (default editorial-cover), showName (<=60), episode (<=12), speaker (<=60), coverImageUrl (https) or coverFileId (PNG/JPEG/WebP <=5 MB; shown by vinyl, duotone-portrait), background/accent/ink (#hex; ink auto from paper), captionMode integrated (default: the design typesets the captions) | preset (your caption preset draws), contrastGuard (default true), aspect 9:16|16:9|1:1|4:5 or width+height, overlays (<=8)}. Retired ids still work as aliases with a warning: bars→swiss-grid, ribbon→continuous-line, rings→ma, spectrogram→riso, skyline→bauhaus, silkline→type-wave, ivory→editorial-cover, halo→vinyl, needle→braun-radio, mono→duotone-portrait. On a video input: 422 audio_visual_needs_audio_input, not charged. Catalog: GET /v1/audio-visuals (MCP get_catalog {kind:'audio_visuals'}), free.",
      "additionalProperties": {}
    },
    "clipSeconds": {
      "type": "number",
      "maximum": 5,
      "description": "Clip length for mode clip, 0.5-5 seconds. Default 5.",
      "exclusiveMinimum": 0
    },
    "translateTo": {
      "type": "string",
      "description": "Same as caption_video; the default sample phrase uses this language."
    },
    "brandPresetId": {
      "type": "string",
      "description": "Id from manage_preset {action:'create', type:'brand'}: applies its font, color, position and logo on top of the preset."
    },
    "highlightColor": {
      "anyOf": [
        {
          "type": "string",
          "description": "#RRGGBB for highlightWords. Default #FACC15."
        },
        {
          "type": "string",
          "description": "#RRGGBB color for highlightWords. Default #FACC15."
        }
      ],
      "description": "#RRGGBB for highlightWords. Default #FACC15."
    },
    "highlightWords": {
      "anyOf": [
        {
          "type": "array",
          "items": {
            "type": "string"
          },
          "maxItems": 200,
          "description": "Shortcut: words or phrases to color in every caption (accent/case-insensitive), e.g. [\"AwesomeVideo\", \"gratis\"]. Maps to styleOverrides.wordHighlights rule {id:\"custom\", words, color}. Same price."
        },
        {
          "type": "array",
          "items": {
            "type": "string"
          },
          "maxItems": 200,
          "description": "Words or phrases to color in every caption (accent- and case-insensitive), max 200."
        }
      ],
      "description": "Shortcut: words or phrases to color in every caption (accent/case-insensitive), e.g. [\"AwesomeVideo\", \"gratis\"]. Maps to styleOverrides.wordHighlights rule {id:\"custom\", words, color}. Same price."
    },
    "styleOverrides": {
      "anyOf": [
        {
          "type": "object",
          "description": "Per-call style changes deep-merged onto the preset (same fields as get_catalog {kind:'presets'} style; null removes a field), validated with the renderer schema and bundled fonts. Example {\"fontSize\":72,\"maxWordsPerCaption\":2,\"wordEntrance\":\"bounce\"}. Same price. No need to manage_preset {action:'create', type:'custom'}. Every field with examples: get_catalog {kind:'styles'}.",
          "propertyNames": {
            "type": "string"
          },
          "additionalProperties": {}
        },
        {
          "type": "object",
          "description": "Same as caption_video, applied to every preset.",
          "propertyNames": {
            "type": "string"
          },
          "additionalProperties": {}
        }
      ],
      "description": "Per-call style changes deep-merged onto the preset (same fields as get_catalog {kind:'presets'} style; null removes a field), validated with the renderer schema and bundled fonts. Example {\"fontSize\":72,\"maxWordsPerCaption\":2,\"wordEntrance\":\"bounce\"}. Same price. No need to manage_preset {action:'create', type:'custom'}. Every field with examples: get_catalog {kind:'styles'}."
    },
    "transcriptionJobId": {
      "anyOf": [
        {
          "type": "string",
          "description": "Id of a finished transcribe or caption_video job whose transcript to reuse (no new transcription charge)."
        },
        {
          "type": "string",
          "description": "Preview only: show real captions from this transcription (no new transcription)."
        }
      ],
      "description": "Id of a finished transcribe or caption_video job whose transcript to reuse (no new transcription charge)."
    }
  }
}
preview output schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "id": {
      "type": "string",
      "description": "Job id: pass it to get_job, resume_job, edit_transcript or as transcriptionJobId."
    },
    "kind": {
      "type": "string",
      "description": "Job kind (transcribe, burn, caption, clips, shorts, trim, dub, translate, preview, metadata...)."
    },
    "step": {
      "type": "string",
      "description": "Current pipeline step while running."
    },
    "error": {
      "description": "Failure reason when status is failed."
    },
    "result": {
      "description": "Result when succeeded: url, files[{name, url}], clips, text..."
    },
    "status": {
      "type": "string",
      "description": "queued, running, succeeded or failed."
    },
    "progress": {
      "description": "Progress (0-1) and ETA while running."
    },
    "warnings": {
      "type": "array",
      "items": {},
      "description": "Non-blocking notes."
    },
    "costCents": {
      "type": "number",
      "description": "Credits charged (1 credit = 1 cent)."
    },
    "expiresAt": {
      "description": "When the result files are deleted."
    },
    "refundedCents": {
      "type": "number",
      "description": "Credits refunded after a failure."
    }
  },
  "description": "A job: poll get_job with id until status is succeeded or failed.",
  "additionalProperties": {}
}
preview annotations
{
  "title": "Preview captions on the video",
  "readOnlyHint": false,
  "openWorldHint": true,
  "idempotentHint": false,
  "destructiveHint": false
}
get_presets — Read your saved presets
Advertised by the server during the last successful anonymous check.
Advertised read-only

Free, read-only, needs a key. action list (default): your saved presets, type custom (full caption styles from manage_preset, ids custom:cp_...) or brand (font, color, position and logo overlays); paginated with limit and cursor, response_format concise (default) or detailed. action get: one custom preset with its full style by id. action validate: check a style document (style, or basePreset + overrides) against the renderer schema before saving; returns valid, the normalized style or errors [{path, message}]. Built-in and community presets are in get_catalog kind presets.

get_presets input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "id": {
      "type": "string",
      "description": "Preset id: cp_... or custom:cp_... as returned by manage_preset {action:'create', type:'custom'} / get_presets {type:'custom'}."
    },
    "type": {
      "enum": [
        "custom",
        "brand"
      ],
      "type": "string",
      "description": "For list: custom (default) or brand presets."
    },
    "limit": {
      "type": "integer",
      "maximum": 100,
      "minimum": 1,
      "description": "Page size for the returned list, 1-100. Default 50."
    },
    "style": {
      "type": "object",
      "description": "Full caption style document to validate.",
      "propertyNames": {
        "type": "string"
      },
      "additionalProperties": {}
    },
    "action": {
      "enum": [
        "list",
        "get",
        "validate"
      ],
      "type": "string",
      "description": "list (default), get (needs id) or validate (style, or basePreset + overrides)."
    },
    "cursor": {
      "type": "string",
      "description": "nextCursor from the previous page. Omit for the first page."
    },
    "overrides": {
      "type": "object",
      "description": "Fields deep-merged on top of basePreset before validating.",
      "propertyNames": {
        "type": "string"
      },
      "additionalProperties": {}
    },
    "basePreset": {
      "type": "string",
      "description": "Validate basePreset + overrides instead of a full style (custom:cp_... bases need a key)."
    },
    "response_format": {
      "enum": [
        "concise",
        "detailed"
      ],
      "type": "string",
      "description": "concise (default): short list items without nested style/example objects, to save tokens. detailed: full objects."
    }
  }
}
get_presets output schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "total": {
      "type": "number",
      "description": "Total number of items (paginated lists)."
    },
    "result": {
      "description": "The value, when the tool returns something other than an object."
    },
    "hasMore": {
      "type": "boolean",
      "description": "true when more items are available (paginated lists)."
    },
    "nextCursor": {
      "type": "string",
      "description": "Pass as cursor for the next page (paginated lists)."
    }
  },
  "description": "Tool result as JSON.",
  "additionalProperties": {}
}
get_presets annotations
{
  "title": "Read your saved presets",
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
manage_preset — Create, change, delete or publish a preset
Advertised by the server during the last successful anonymous check.
Advertised destructiveOpen-world

Free, needs a key. Saves your own looks for reuse. action create: type custom saves a full caption style (name + style, or basePreset + overrides; returns id custom:cp_...); type brand saves a font/color/position/logo overlay (returns brandPresetId). action update: changes a custom preset in place (overwrites). action delete: permanently removes a custom or brand preset by id. action submit: proposes a custom preset for the public community gallery (moderated; visible to everyone once approved). Check a style first with get_presets action validate.

manage_preset input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "required": [
    "action"
  ],
  "properties": {
    "id": {
      "anyOf": [
        {
          "type": "string",
          "description": "Preset id: cp_... or custom:cp_... as returned by manage_preset {action:'create', type:'custom'} / get_presets {type:'custom'}."
        },
        {
          "type": "string",
          "description": "Id of your saved custom preset to submit (cp_... or custom:cp_...)."
        }
      ],
      "description": "Preset id: cp_... or custom:cp_... as returned by manage_preset {action:'create', type:'custom'} / get_presets {type:'custom'}."
    },
    "name": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 80,
          "description": "Display name (max 80 characters)."
        },
        {
          "type": "string",
          "description": "Name for this brand preset (e.g. the brand or channel)."
        },
        {
          "type": "string",
          "maxLength": 80,
          "description": "New name (max 80 characters). Omit to keep."
        }
      ],
      "description": "Display name (max 80 characters)."
    },
    "tags": {
      "type": "array",
      "items": {
        "type": "string",
        "maxLength": 24
      },
      "maxItems": 8,
      "description": "Up to 8 gallery tags, max 24 characters each (e.g. bold, podcast)."
    },
    "type": {
      "enum": [
        "custom",
        "brand"
      ],
      "type": "string",
      "description": "custom (default) or brand. Used by create and delete."
    },
    "color": {
      "type": "string",
      "description": "Caption text color as #RRGGBB."
    },
    "style": {
      "anyOf": [
        {
          "type": "object",
          "description": "Full caption style JSON, the same document get_catalog {kind:'presets'} returns in style and the web editor stores: fontFamily, fontWeight, fontSize (px at 720p), color, strokeWidth/strokeColor, backgroundEnabled/backgroundColor/backgroundOpacity/paddingX/paddingY/borderRadius, shadow*, position (top|center|bottom), margin, subtitleWidth, textTransform, letterSpacing, revealMode (none|full|progressive|word-by-word), animationEnabled + animation (Fade|Zoom In|Zoom Out|Slide Up|Slide Down), motion*, wordStateStyles {active|past|upcoming|future: partial style}, wordHighlights {rules,customLists}, smartEmphasis, segmentColorCycle. Unknown fields are rejected. fontFamily (also inside wordStateStyles) must be a bundled font: Inter, Poppins, Oswald, Roboto, Anton, Bebas Neue, Playfair Display, Caveat, IBM Plex Mono (get_catalog {kind:'presets'} returns fonts). Caption forms: maxWordsPerCaption 1-8 (1 = one big word at a time; wins over the autoFit words cap). activeWordReflow true = a scaled active word pushes neighbours aside. wordEntrance bounce|slide-up|fade (+ wordEntranceDuration seconds) animates each word when spoken. positionMode cycle|keyword (+ positionCycle [top|center|bottom], positionKeywords [words], keywordPosition) moves captions, always inside the safe zone. captionLayout stacked = poster, one word per line with a bigger hero word (posterHeroScale 1-3). faceAvoid true = burns detect faces and move captions off them; the result returns faceAvoid.faceLayout, store it as style.faceLayout to reuse.",
          "propertyNames": {
            "type": "string"
          },
          "additionalProperties": {}
        },
        {
          "type": "object",
          "description": "Full caption style JSON (same document get_catalog {kind:'presets'} returns in style; fields in get_catalog {kind:'styles'}). Replaces the whole style.",
          "propertyNames": {
            "type": "string"
          },
          "additionalProperties": {}
        }
      ],
      "description": "Full caption style JSON, the same document get_catalog {kind:'presets'} returns in style and the web editor stores: fontFamily, fontWeight, fontSize (px at 720p), color, strokeWidth/strokeColor, backgroundEnabled/backgroundColor/backgroundOpacity/paddingX/paddingY/borderRadius, shadow*, position (top|center|bottom), margin, subtitleWidth, textTransform, letterSpacing, revealMode (none|full|progressive|word-by-word), animationEnabled + animation (Fade|Zoom In|Zoom Out|Slide Up|Slide Down), motion*, wordStateStyles {active|past|upcoming|future: partial style}, wordHighlights {rules,customLists}, smartEmphasis, segmentColorCycle. Unknown fields are rejected. fontFamily (also inside wordStateStyles) must be a bundled font: Inter, Poppins, Oswald, Roboto, Anton, Bebas Neue, Playfair Display, Caveat, IBM Plex Mono (get_catalog {kind:'presets'} returns fonts). Caption forms: maxWordsPerCaption 1-8 (1 = one big word at a time; wins over the autoFit words cap). activeWordReflow true = a scaled active word pushes neighbours aside. wordEntrance bounce|slide-up|fade (+ wordEntranceDuration seconds) animates each word when spoken. positionMode cycle|keyword (+ positionCycle [top|center|bottom], positionKeywords [words], keywordPosition) moves captions, always inside the safe zone. captionLayout stacked = poster, one word per line with a bigger hero word (posterHeroScale 1-3). faceAvoid true = burns detect faces and move captions off them; the result returns faceAvoid.faceLayout, store it as style.faceLayout to reuse."
    },
    "action": {
      "enum": [
        "create",
        "update",
        "delete",
        "submit"
      ],
      "type": "string",
      "description": "create, update (custom only), delete or submit (custom only, to the public gallery)."
    },
    "author": {
      "type": "string",
      "maxLength": 80,
      "description": "Public credit, e.g. the agent or person name. Default 'AI agent'."
    },
    "position": {
      "enum": [
        "top",
        "center",
        "bottom"
      ],
      "type": "string",
      "description": "Caption position: top, center or bottom."
    },
    "overrides": {
      "anyOf": [
        {
          "type": "object",
          "description": "Style fields to change on top of basePreset (or of style).",
          "propertyNames": {
            "type": "string"
          },
          "additionalProperties": {}
        },
        {
          "type": "object",
          "description": "Style fields deep-merged on top of basePreset or the current style; null removes a field.",
          "propertyNames": {
            "type": "string"
          },
          "additionalProperties": {}
        }
      ],
      "description": "Style fields to change on top of basePreset (or of style)."
    },
    "basePreset": {
      "anyOf": [
        {
          "type": "string",
          "description": "Start from this preset (id, slug, name, or custom:cp_...) instead of a full style."
        },
        {
          "type": "string",
          "description": "Start from this preset (id, slug, name or custom:cp_...) instead of a full style."
        }
      ],
      "description": "Start from this preset (id, slug, name, or custom:cp_...) instead of a full style."
    },
    "fontFamily": {
      "type": "string",
      "description": "One of the bundled fonts: Inter, Poppins, Oswald, Roboto, Anton, Bebas Neue, Playfair Display, Caveat, IBM Plex Mono."
    },
    "logoBase64": {
      "type": "string",
      "description": "Optional logo as base64 PNG, JPEG or WebP under 1 MB, drawn on videos burned with this brand preset."
    },
    "description": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 500,
          "description": "Short description shown with the preset (max 500 characters)."
        },
        {
          "type": "string",
          "maxLength": 500,
          "description": "New description (max 500 characters). Omit to keep."
        },
        {
          "type": "string",
          "maxLength": 500,
          "description": "Public description for the gallery (max 500 characters)."
        }
      ],
      "description": "Short description shown with the preset (max 500 characters)."
    },
    "previewText": {
      "type": "string",
      "maxLength": 140,
      "description": "Sample caption text for the gallery preview (max 140 characters)."
    }
  }
}
manage_preset output schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "total": {
      "type": "number",
      "description": "Total number of items (paginated lists)."
    },
    "result": {
      "description": "The value, when the tool returns something other than an object."
    },
    "hasMore": {
      "type": "boolean",
      "description": "true when more items are available (paginated lists)."
    },
    "nextCursor": {
      "type": "string",
      "description": "Pass as cursor for the next page (paginated lists)."
    }
  },
  "description": "Tool result as JSON.",
  "additionalProperties": {}
}
manage_preset annotations
{
  "title": "Create, change, delete or publish a preset",
  "readOnlyHint": false,
  "openWorldHint": true,
  "idempotentHint": false,
  "destructiveHint": true
}
create_clips — Long video to short clips
Advertised by the server during the last successful anonymous check.
Open-world

PREFER THIS for 'turn this long video/podcast into shorts/clips'. engine highlights (default): transcribes (or reuses transcriptionJobId/subtitles), an LLM picks the count (default 3, max 10) best self-contained moments of minSeconds-maxSeconds, renders each MP4 (reframe face, center or none) with captions, and returns clips with title, hook, score and url. Price: 1 credit per source minute to transcribe (0 with a transcript) + 1 per 10 source minutes + 3 per output minute; quoteOnly:true prices it free. engine shorts: quick 1-5 vertical 9:16 cuts from an existing transcript, 6 credits per source minute. Long jobs: poll get_job.

create_clips input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "wait": {
      "type": "boolean",
      "description": "Block until done, up to waitSeconds. Default true."
    },
    "count": {
      "anyOf": [
        {
          "type": "integer",
          "maximum": 9007199254740991,
          "minimum": -9007199254740991,
          "description": "Clips to return, 1-10. Default 3. Out of range: 422 limit_exceeded before any charge."
        },
        {
          "type": "integer",
          "maximum": 9007199254740991,
          "minimum": -9007199254740991,
          "description": "1-5 clips. Out of range returns limit_exceeded before any charge."
        }
      ],
      "description": "Clips to return, 1-10. Default 3. Out of range: 422 limit_exceeded before any charge."
    },
    "engine": {
      "enum": [
        "highlights",
        "shorts"
      ],
      "type": "string",
      "description": "highlights (default): LLM-ranked best moments, up to 10, any shape, transcribes if needed. shorts: quick 1-5 vertical 9:16 cuts when you already have the transcript (6 credits per source minute)."
    },
    "fileId": {
      "anyOf": [
        {
          "type": "string",
          "description": "Id from upload {action:'start'}, import_url, or upload {action:'inline'}."
        },
        {
          "type": "string",
          "description": "Id of a file already uploaded with upload {action:'start'}, upload {action:'start_multipart'}, upload {action:'inline'} or import_url. Pass this or the media URL."
        }
      ],
      "description": "Id from upload {action:'start'}, import_url, or upload {action:'inline'}."
    },
    "preset": {
      "anyOf": [
        {
          "type": "string",
          "description": "Caption preset id or name, or custom:cp_.... Default Clarity."
        },
        {
          "type": "string",
          "description": "Caption preset: id, slug or name from get_catalog {kind:'presets'} (e.g. 'hormozi-style', 'Clarity') or custom:cp_... from manage_preset {action:'create', type:'custom'}."
        }
      ],
      "description": "Caption preset id or name, or custom:cp_.... Default Clarity."
    },
    "autoFit": {
      "anyOf": [
        {
          "type": "boolean",
          "description": "Default true. Same rule as caption_video."
        },
        {
          "type": "boolean",
          "description": "Default true: caption size, words per caption (4 on 9:16, 5 on 1:1, 7 on 16:9), and a default safe zone follow the video shape, so text reads the same at 720p and 1080p and stays clear of app UI. Pass false only when the user wants the preset's exact fixed pixel sizes. Same price."
        }
      ],
      "description": "Default true. Same rule as caption_video."
    },
    "reframe": {
      "anyOf": [
        {
          "enum": [
            "center",
            "face",
            "none"
          ],
          "type": "string",
          "description": "face (default): 9:16 crop that follows the speaker, center fallback. center: plain center crop. none: keep the source aspect. Same price."
        },
        {
          "enum": [
            "face",
            "center"
          ],
          "type": "string",
          "description": "face (default): track the main speaker. center: plain center crop. Same price."
        }
      ],
      "description": "face (default): 9:16 crop that follows the speaker, center fallback. center: plain center crop. none: keep the source aspect. Same price."
    },
    "captions": {
      "type": "boolean",
      "description": "Burn captions into each clip. Default true. Same price."
    },
    "glossary": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Extra terms to spell correctly in this job only (brand names, people). The saved glossary (update_glossary {action:'save'}) is applied as well."
    },
    "language": {
      "type": "string",
      "description": "Spoken language (BCP-47). Omit for auto-detect."
    },
    "mediaUrl": {
      "type": "string",
      "description": "Public https link to the video or audio (direct file, chat attachment URL, Google Drive or Dropbox share link; YouTube is refused). Pass this or fileId."
    },
    "platform": {
      "anyOf": [
        {
          "type": "string",
          "description": "tiktok, instagram_reels, youtube_shorts, ... (see get_catalog {kind:'platforms'}). Keeps captions clear of the app UI. Same price."
        },
        {
          "type": "string",
          "description": "Where the video will be posted: tiktok, instagram_reels, youtube_shorts, facebook_reels, snapchat_spotlight, linkedin, youtube, x (aliases like reels, instagram, shorts, snap, twitter; case-insensitive). Keeps captions out of that app's buttons and text. If the user says \"para TikTok\" / \"for Reels\", pass it; if they did not say and it matters, ask. Same price. Unknown values return 422 invalid_platform before any charge. See get_catalog {kind:'platforms'}."
        }
      ],
      "description": "tiktok, instagram_reels, youtube_shorts, ... (see get_catalog {kind:'platforms'}). Keeps captions clear of the app UI. Same price."
    },
    "faceAvoid": {
      "type": "boolean",
      "description": "true = move captions off faces (samples faces at 2 fps, same price; result.faceAvoid.faceLayout). Shortcut for styleOverrides.faceAvoid."
    },
    "quoteOnly": {
      "type": "boolean",
      "description": "Return the price for durationSeconds (and count/maxSeconds) without starting a job."
    },
    "sourceUrl": {
      "type": "string",
      "description": "Public link to the video. Not YouTube, TikTok or Instagram."
    },
    "subtitles": {
      "anyOf": [
        {
          "type": "string",
          "description": "Reuse an SRT, VTT, or JSON transcript (JSON keeps word timing for tighter cuts)."
        },
        {
          "type": "string",
          "description": "Existing captions as SRT, WebVTT or AwesomeVideo JSON text. Skips transcription (no transcription charge)."
        }
      ],
      "description": "Reuse an SRT, VTT, or JSON transcript (JSON keeps word timing for tighter cuts)."
    },
    "maxCredits": {
      "anyOf": [
        {
          "type": "number",
          "minimum": 0,
          "description": "Refuse the job if it would cost more than this many credits."
        },
        {
          "type": "number",
          "minimum": 0,
          "description": "Spending cap for this call in credits (1 credit = 1 cent). If the price is higher the call fails with 422 before charging."
        }
      ],
      "description": "Refuse the job if it would cost more than this many credits."
    },
    "maxSeconds": {
      "anyOf": [
        {
          "type": "number",
          "description": "Longest clip, minSeconds-90 s. Default 60."
        },
        {
          "type": "number",
          "description": "Longest clip, minSeconds-60 seconds."
        }
      ],
      "description": "Longest clip, minSeconds-90 s. Default 60."
    },
    "minSeconds": {
      "anyOf": [
        {
          "type": "number",
          "description": "Shortest clip, 5-90 s. Default 15."
        },
        {
          "type": "number",
          "description": "Shortest clip, 5-60 seconds. Default 15."
        }
      ],
      "description": "Shortest clip, 5-90 s. Default 15."
    },
    "webhookUrl": {
      "type": "string",
      "description": "https URL that receives a POST with the finished job (status, result URLs, credits charged)."
    },
    "notifyEmail": {
      "type": "string",
      "description": "Email address that gets a link when the job finishes or fails."
    },
    "waitSeconds": {
      "type": "integer",
      "maximum": 50,
      "minimum": 0,
      "description": "Default 45, max 50."
    },
    "brandPresetId": {
      "type": "string",
      "description": "Id from manage_preset {action:'create', type:'brand'}: applies its font, color, position and logo on top of the preset."
    },
    "highlightColor": {
      "type": "string",
      "description": "#RRGGBB for highlightWords. Default #FACC15."
    },
    "highlightWords": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "maxItems": 200,
      "description": "Shortcut: words or phrases to color in every caption (accent/case-insensitive), e.g. [\"AwesomeVideo\", \"gratis\"]. Maps to styleOverrides.wordHighlights rule {id:\"custom\", words, color}. Same price."
    },
    "idempotencyKey": {
      "type": "string",
      "maxLength": 200,
      "description": "Your own unique key for this request (max 200 chars). Retrying with the same key returns the first job instead of charging again."
    },
    "styleOverrides": {
      "type": "object",
      "description": "Per-call style changes deep-merged onto the preset (same fields as get_catalog {kind:'presets'} style; null removes a field), validated with the renderer schema and bundled fonts. Example {\"fontSize\":72,\"maxWordsPerCaption\":2,\"wordEntrance\":\"bounce\"}. Same price. No need to manage_preset {action:'create', type:'custom'}. Every field with examples: get_catalog {kind:'styles'}.",
      "propertyNames": {
        "type": "string"
      },
      "additionalProperties": {}
    },
    "durationSeconds": {
      "type": "number",
      "description": "Media length in seconds. Lets the price be computed without fetching media (quoteOnly, quote, plan).",
      "exclusiveMinimum": 0
    },
    "transcriptionJobId": {
      "anyOf": [
        {
          "type": "string",
          "description": "Reuse a finished transcription: no transcription charge."
        },
        {
          "type": "string",
          "description": "Id of a finished transcribe or caption_video job whose transcript to reuse (no new transcription charge)."
        }
      ],
      "description": "Reuse a finished transcription: no transcription charge."
    }
  }
}
create_clips output schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "id": {
      "type": "string",
      "description": "Job id: pass it to get_job, resume_job, edit_transcript or as transcriptionJobId."
    },
    "kind": {
      "type": "string",
      "description": "Job kind (transcribe, burn, caption, clips, shorts, trim, dub, translate, preview, metadata...)."
    },
    "step": {
      "type": "string",
      "description": "Current pipeline step while running."
    },
    "error": {
      "description": "Failure reason when status is failed."
    },
    "result": {
      "description": "Result when succeeded: url, files[{name, url}], clips, text..."
    },
    "status": {
      "type": "string",
      "description": "queued, running, succeeded or failed."
    },
    "progress": {
      "description": "Progress (0-1) and ETA while running."
    },
    "warnings": {
      "type": "array",
      "items": {},
      "description": "Non-blocking notes."
    },
    "costCents": {
      "type": "number",
      "description": "Credits charged (1 credit = 1 cent)."
    },
    "expiresAt": {
      "description": "When the result files are deleted."
    },
    "refundedCents": {
      "type": "number",
      "description": "Credits refunded after a failure."
    }
  },
  "description": "A job: poll get_job with id until status is succeeded or failed.",
  "additionalProperties": {}
}
create_clips annotations
{
  "title": "Long video to short clips",
  "readOnlyHint": false,
  "openWorldHint": true,
  "idempotentHint": false,
  "destructiveHint": false
}
update_glossary — Save or delete glossary terms
Advertised by the server during the last successful anonymous check.
Advertised destructive

Free, needs a key. Changes the saved transcription glossary that every later transcription of this account uses (brand names, people, slang spellings, doNotTranslate terms). action save: entries [{term, aliases?, doNotTranslate?}] merged by term (mode merge, default) or replacing the whole glossary (mode replace). action delete: remove terms, or all:true to clear it. Returns the glossary after the change. Read it with get_glossary.

update_glossary input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "required": [
    "action"
  ],
  "properties": {
    "all": {
      "type": "boolean",
      "description": "true = delete the whole glossary. Pass this or terms."
    },
    "mode": {
      "enum": [
        "merge",
        "replace"
      ],
      "type": "string",
      "description": "'merge' (default) adds or updates by term; 'replace' overwrites the whole glossary."
    },
    "terms": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Terms to remove (exact term text). Pass this or all."
    },
    "action": {
      "enum": [
        "save",
        "delete"
      ],
      "type": "string",
      "description": "save (entries) or delete (terms or all)."
    },
    "entries": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "term"
        ],
        "properties": {
          "note": {
            "type": "string",
            "maxLength": 200
          },
          "term": {
            "type": "string",
            "maxLength": 80
          },
          "aliases": {
            "type": "array",
            "items": {
              "type": "string",
              "maxLength": 80
            },
            "maxItems": 10
          },
          "doNotTranslate": {
            "type": "boolean"
          }
        }
      },
      "description": "Terms to save: [{term, aliases?: string[] (max 10), doNotTranslate?: boolean}], up to 200 terms in total."
    }
  }
}
update_glossary output schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "total": {
      "type": "number",
      "description": "Total number of items (paginated lists)."
    },
    "result": {
      "description": "The value, when the tool returns something other than an object."
    },
    "hasMore": {
      "type": "boolean",
      "description": "true when more items are available (paginated lists)."
    },
    "nextCursor": {
      "type": "string",
      "description": "Pass as cursor for the next page (paginated lists)."
    }
  },
  "description": "Tool result as JSON.",
  "additionalProperties": {}
}
update_glossary annotations
{
  "title": "Save or delete glossary terms",
  "readOnlyHint": false,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": true
}
create_checkout — Buy credits
Advertised by the server during the last successful anonymous check.
Open-world

Free to call; returns a checkout URL your human opens to pay. Without product: $5 = 500 credits for this exact key, works on unclaimed self-serve keys. With product (key claimed at https://awesomevideoeditor.com/account): pack_5 $5=500, pack_20 $20=2,200, pack_50 $50=6,000 credits; plans creator $9/mo=1,200, pro $29/mo=4,500, scale $99/mo=18,000 credits/month (interval year = 10x monthly). 1 credit = 1 cent. Credits arrive after payment; then retry the call that returned 402.

create_checkout input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "product": {
      "enum": [
        "pack_5",
        "pack_20",
        "pack_50",
        "creator",
        "pro",
        "scale"
      ],
      "type": "string",
      "description": "Pack or plan. Omit for $5 = 500 credits on this key (no account needed)."
    },
    "interval": {
      "enum": [
        "month",
        "year"
      ],
      "type": "string",
      "description": "Billing interval for plans: month (default) or year (10x the monthly price, 12 grants). Ignored for packs."
    }
  }
}
create_checkout output schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "total": {
      "type": "number",
      "description": "Total number of items (paginated lists)."
    },
    "result": {
      "description": "The value, when the tool returns something other than an object."
    },
    "hasMore": {
      "type": "boolean",
      "description": "true when more items are available (paginated lists)."
    },
    "nextCursor": {
      "type": "string",
      "description": "Pass as cursor for the next page (paginated lists)."
    }
  },
  "description": "Tool result as JSON.",
  "additionalProperties": {}
}
create_checkout annotations
{
  "title": "Buy credits",
  "readOnlyHint": false,
  "openWorldHint": true,
  "idempotentHint": false,
  "destructiveHint": false
}
get_account — Get balance and usage
Advertised by the server during the last successful anonymous check.
Advertised read-only

Free, read-only, needs a key. This key's spendable balance (balanceCents in credits, 1 credit = 1 cent, and as transcription seconds), the per-minute prices, and credit usage over a range (usage: per day and total, split into transcription and server burn; default the last 30 days; from and to in unix ms). response_format concise (default) returns usage totals only; detailed adds the per-day rows. Call it before a paid job or after a 402; top up with create_checkout; individual jobs are in list_jobs.

get_account input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "to": {
      "type": "number",
      "description": "End of the range, unix milliseconds. Default now."
    },
    "from": {
      "type": "number",
      "description": "Start of the range, unix milliseconds. Default 30 days ago."
    },
    "response_format": {
      "enum": [
        "concise",
        "detailed"
      ],
      "type": "string",
      "description": "concise (default): usage totals only. detailed: also per-day usage rows."
    }
  }
}
get_account output schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "total": {
      "type": "number",
      "description": "Total number of items (paginated lists)."
    },
    "result": {
      "description": "The value, when the tool returns something other than an object."
    },
    "hasMore": {
      "type": "boolean",
      "description": "true when more items are available (paginated lists)."
    },
    "nextCursor": {
      "type": "string",
      "description": "Pass as cursor for the next page (paginated lists)."
    }
  },
  "description": "Tool result as JSON.",
  "additionalProperties": {}
}
get_account annotations
{
  "title": "Get balance and usage",
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}

Prompts

Not advertised

No prompt definitions available.

Resources

Not advertised

No resource definitions available.

30-day availability

Aggregated from read-only remote checks; this is not a tool-execution or security guarantee.

Successful checks
1 of 1 (100%)
Average latency
1052 ms
95th percentile latency
1052 ms

Maintenance history

Public check and source-refresh events. Editorial and ownership records remain private.

  • · probe · passed · 1052 ms · metadata changed · 27 tool(s)

Connect from your client

Each snippet registers the same endpoint; pick the client you use.

This server is operated by the named third party. Listing and endpoint checks are not an endorsement or a security audit. Review the operator's permissions, terms, and data handling before connecting. How listings are checked and corrected.

Claude Code

Run this once in a terminal. It registers the remote server. Use --scope project to write .mcp.json for the repo.
Claude Code configuration
claude mcp add --transport http awesomevideo-mcp https://api.awesomevideoeditor.com/mcp

Codex

Run this once. Codex stores MCP servers in ~/.codex/config.toml (or .codex/config.toml in a trusted project).
Codex configuration
codex mcp add awesomevideo-mcp --url https://api.awesomevideoeditor.com/mcp

Cursor

Merge this server into .cursor/mcp.json in your project, then enable awesomevideo-mcp in your MCP settings.
Cursor configuration
{
  "mcpServers": {
    "awesomevideo-mcp": {
      "url": "https://api.awesomevideoeditor.com/mcp"
    }
  }
}

Cline

Merge this into cline_mcp_settings.json (Cline → MCP Servers → Configure).
Cline configuration
{
  "mcpServers": {
    "awesomevideo-mcp": {
      "type": "streamableHttp",
      "url": "https://api.awesomevideoeditor.com/mcp",
      "disabled": false
    }
  }
}

VS Code

Merge this server into .vscode/mcp.json. Use MCP: List Servers to start awesomevideo-mcp and inspect its tools.
VS Code configuration
{
  "servers": {
    "awesomevideo-mcp": {
      "type": "http",
      "url": "https://api.awesomevideoeditor.com/mcp"
    }
  }
}

Gemini CLI

Run this once. It writes .gemini/settings.json in the current project; pass --scope user for ~/.gemini/settings.json.
Gemini CLI configuration
gemini mcp add --transport http awesomevideo-mcp https://api.awesomevideoeditor.com/mcp

Claude Desktop

Merge this into claude_desktop_config.json (macOS: ~/Library/Application Support/Claude/, Windows: %APPDATA%\Claude\), then restart Claude Desktop.
Claude Desktop configuration
{
  "mcpServers": {
    "awesomevideo-mcp": {
      "url": "https://api.awesomevideoeditor.com/mcp"
    }
  }
}

Windsurf

Merge this into ~/.codeium/windsurf/mcp_config.json, then refresh MCP in Cascade. Windsurf remote servers use serverUrl, not url.
Windsurf configuration
{
  "mcpServers": {
    "awesomevideo-mcp": {
      "serverUrl": "https://api.awesomevideoeditor.com/mcp"
    }
  }
}

Let your agent find its tools

Find servers like AwesomeVideo MCP from your agent. Add Koskamo once to search the index for endpoints, access requirements, and client setup. Public discovery needs no key.

Do you run AwesomeVideo MCP?

Prove ownership with a DNS record, a well-known file, or your Official MCP Registry entry, and your edits publish immediately. Proofs are re-checked weekly; admins can still hide or remove a listing.

Claim this listing