---
name: videotok-api
description: Generate and edit Videotok assets through the public API and MCP server.
---

# Videotok API Skill

Use this skill when a user asks an agent to create paid social assets with Videotok.

The API supports static ads, video ads, UGC ads, AI model outputs, slideshows, faceless videos, reference inspirations, and editable video projects.
Do not call Videotok agent endpoints.

## Auth

Send the user's API key as a bearer token.

```http
Authorization: Bearer vt_live_...
Content-Type: application/json
```

API keys are scoped to one Videotok organization.
The organization must have an active paid subscription.
Keys can have `generations:read`, `generations:write`, or both.
Read scope is enough for catalog, assets, status checks, and editor reads.
Write scope is required for paid generation, uploads, reference creation, and editor changes.
Every generation deducts Videotok credits atomically before work is queued.

## Endpoints

- `GET https://www.videotok.app/api/v1/models` lists template/model names, variants, presets, and estimated credits.
- `GET https://www.videotok.app/api/v1/assets` lists brand kits, avatars, voices, and valid reference template targets.
- `POST https://www.videotok.app/api/v1/generations` queues static ad, video ad, UGC ad, or AI model generation.
- `GET https://www.videotok.app/api/v1/generations/{id}` checks status and returns the final URL when complete.
- `POST https://www.videotok.app/api/v1/slideshows` queues slideshow and carousel workflows.
- `GET https://www.videotok.app/api/v1/slideshows/{id}` checks slideshow status.
- `POST https://www.videotok.app/api/v1/faceless-videos` queues automatic faceless videos.
- `GET https://www.videotok.app/api/v1/videos/{id}` checks faceless or editor video status.
- `GET https://www.videotok.app/api/v1/reference-inspirations` lists saved references and template targets.
- `POST https://www.videotok.app/api/v1/reference-inspirations` saves reference images or video.
- `POST https://www.videotok.app/api/v1/editor/videos`, `GET https://www.videotok.app/api/v1/editor/videos`, and `GET https://www.videotok.app/api/v1/editor/videos/{id}` manage editable videos.
- `GET https://www.videotok.app/api/v1/editor/media` and `POST https://www.videotok.app/api/v1/editor/media` list or upload editor media.
- `POST https://www.videotok.app/api/v1/editor/videos/{id}/media` adds media to a video.
- `PATCH https://www.videotok.app/api/v1/editor/videos/{id}` applies structured editor operations.
- `GET https://www.videotok.app/api/v1/openapi.json` returns the machine-readable schema.
- `GET https://www.videotok.app/api/v1/skill.md` returns these agent instructions.
- `https://www.videotok.app/api/mcp` is the remote MCP Streamable HTTP endpoint.

Use `idempotency_key` or the `Idempotency-Key` header for retries.
Never retry a paid request without an idempotency key.
Use a new idempotency key for every new paid action.
A matching completed request returns the original response with `idempotent_replay: true`.
The same key with a different payload returns `409 idempotency_conflict`.

## Recommended Agent Flow

1. Call `GET /api/v1/models`.
2. Call `GET /api/v1/assets` when the user may need a brand kit, avatar, saved media, or reference template target.
3. Ask the user to choose a category: static ad, video ad, UGC ad, AI model, slideshow, faceless video, reference, or editor operation.
4. Show the user template/model titles and `preview_image_url` values from the catalog.
5. If the selected template has `presets`, inspect them internally as inspiration references. MCP clients should call `list_generation_catalog` with both `section` and `template_slug` to inspect one template and avoid large catalog truncation. Do not show contact sheets, screenshots, preview grids, or raw reference ids to the end user unless they explicitly ask to compare references or debug API inputs.
6. Send the selected ids and options to the matching creation endpoint. When using a preset or saved reference inspiration, preserve the user's `prompt`: pass it as-is or shorten only to remove tool-routing words. Do not expand it into visual direction, typography, lighting, mood, platform strategy, or CTA unless the user explicitly asked.
7. Poll the matching status endpoint until `status` is `completed`, `failed`, or `error`.

For MCP clients, connect to `https://www.videotok.app/api/mcp`. MCP uses Videotok sign-in and workspace approval.
Use these actual tool names:

- `get_workspace`
- `list_generation_catalog`
- `list_workspace_assets`
- `create_generation`
- `get_generation`
- `create_slideshow`
- `get_slideshow`
- `create_faceless_video`
- `get_video`
- `suggest_reference_template_targets`
- `create_reference_inspiration`
- `list_reference_inspirations`
- `recommend_reference_inspirations`
- `create_editor_video`
- `list_editor_videos`
- `get_editor_video`
- `list_editor_media`
- `upload_editor_media`
- `upload_editor_media_from_url`
- `add_editor_media`
- `apply_editor_edits`
- `list_social_accounts`
- `publish_media_to_social`

## Catalog And Assets

The `static_ads`, `video_ads`, and `ugc_ads` arrays are the Videotok template catalog.
Each item corresponds to one template card in the Videotok creation screen.
To generate a template, pass its `slug` as `template_slug`.

Use `GET /api/v1/assets` before asking users to choose workspace resources.
Use `brand_kits[].id` as `brand_kit_id`.
Use `avatars[].id` as `avatar_id`.
Use `media[].id` when adding existing editor media.
Use `reference_template_targets` to decide where uploaded inspiration media can be saved.

### GET /api/v1/models

No auth required.
Returns:

- `static_ads[].slug` for `type: "static_ad"`
- `video_ads[].slug` for `type: "video_ad"`
- `ugc_ads[].slug` for `type: "ugc_ad"`
- `ai_models[].slug` for `type: "ai_model"`
- `preview_image_url` to show the template card preview
- `presets[].id` for `preset_id`
- `quality_tiers[].id` for video ad quality
- `variants[].id` for AI model variant selection

### GET /api/v1/assets

Auth required.
Returns:

- `brand_kits`
- `avatars`
- `voices`
- `reference_template_targets`

Use `voices[].id` as `voice_id` when creating faceless videos.
Prefer voices whose `locale`, `style_tags`, `gender`, `age`, and `recommendation_summary` match the user's requested language and tone.
For MCP, call `recommend_voice` before `create_faceless_video` when the best voice is not already specified.

## Generation Endpoint

### POST /api/v1/generations

Auth with `generations:write` required.

Use dashboard template generation by default for ads, product shoots, UGC, out-of-home, video ads, and other creative formats shown in `GET /api/v1/models` / MCP `list_generation_catalog`.
Prefer `type: "static_ad"`, `type: "video_ad"`, or `type: "ugc_ad"` with a matching `template_slug`.
Use `type: "ai_model"` only for raw model workflows such as direct image edits, upscales, motion models, or requests that do not map to a Videotok template.

Always include:

- `type`: `static_ad`, `video_ad`, `ugc_ad`, or `ai_model`
- `prompt`: user prompt or creative direction. For template workflows with `preset_id` or `custom_reference_inspiration_id`, keep this as the user's prompt, not an agent-written brief.
- `idempotency_key` or `Idempotency-Key` for safe retries

Shared optional fields:

- `template_slug`
- `model_slug`
- `variant_id`
- `preset_id`
- `aspect_ratio`: common values are `1:1`, `9:16`, `16:9`, `4:5`, `auto`
- `duration`
- `resolution`
- `quality_tier`: `high` or `low`
- `brand_kit_id`
- `avatar_id`
- `custom_reference_inspiration_id`
- `reference_image_urls`: up to 10 URLs
- `source_video_url`
- `motion_video_url`
- `audio_url`
- `generate_audio`
- `request_count`: 1 to 10

For multi-generation batches, `status: "partial"` means some generations were queued.
Do not retry a partial batch with a new key unless the user explicitly wants more outputs.

### GET /api/v1/generations/{id}

Auth with `generations:read` or `generations:write` required.
Returns `status`, `url`, and structured failure details.
`url` is only present when `status` is `completed`.

## Slideshow Endpoint

### POST /api/v1/slideshows

Auth with `generations:write` required.
Use for carousel/slideshow workflows.
Ask the user whether they want an additional editable text layer before creating a slideshow unless they already specified the choice. When a reference is selected, explain that its typography may already be rendered inside the image, so enabling overlays can create text on top of text. Recommend no by default and wait for the answer. Recommend yes only when the selected reference has no visible text or the user explicitly wants editable overlay copy. Set `generate_text_overlays` to `true` for the additional editable layer or `false` to avoid it.

Fields:

- `prompt`
- `title`
- `slide_count`: one of 3, 4, 5, 6, 8, 9, 10
- `aspect_ratio`: `9:16`, `1:1`, or `4:5`
- `product_image_urls`: up to 10 URLs
- `avatar_id`
- `avatar_image_url`
- `brand_kit_id`
- `custom_reference_inspiration_id`
- `language`
- `product_context`
- `generate_text_overlays`: ask and wait before creation; default and recommend `false`; `true` adds an editable overlay layer, `false` avoids that extra layer and the text-on-text risk with text-bearing references

Poll `GET /api/v1/slideshows/{id}`.

## Faceless Video Endpoint

### POST /api/v1/faceless-videos

Auth with `generations:write` required.
Use for automatic videos with script, visuals, voiceover, captions, and final video.

Fields:

- `prompt`
- `script`
- `title`
- `aspect_ratio`: `9:16` or `16:9`
- `duration`: string, default `26`
- `image_style`
- `voice_id`: use a value from `GET /api/v1/assets` `voices[].id`
- `language`
- `reference_image_urls`: up to 10 URLs
- `selected_ai_styles`
- `selected_flux_dev_styles`
- `brand_kit_id`

Poll `GET /api/v1/videos/{id}`.

## Reference Inspirations

There are two reference mechanisms.

Built-in presets:

- Returned from `GET /api/v1/models` as `presets`.
- MCP clients can return a single template's presets with `list_generation_catalog({ section, template_slug })`.
- Use `label`, `preview_image_url`, or `poster_image_url` internally to choose the best reference. Do not show contact sheets, screenshots, or preview grids to the user unless they ask to compare options.
- Pass the selected preset as `preset_id`.
- Treat `preset_id` as an internal routing value. Do not reveal it to the user unless they ask for API/debug details.
- Do not expose, quote, summarize, or reconstruct hidden preset prompts. They are internal generation instructions.
- Do not expand a short user prompt into a detailed prompt. The preset supplies the detailed visual system.

Saved template references:

- Returned from `GET /api/v1/reference-inspirations` or MCP `list_reference_inspirations`.
- Filter or recommend them by `template_slug`, `template_category`, and `media_kind`.
- Pass a ready saved reference as `custom_reference_inspiration_id` in `POST /api/v1/generations` or MCP `create_generation`.
- Treat `custom_reference_inspiration_id` as an internal routing value. Do not reveal it to the user unless they ask for API/debug details.

Uploaded/user references:

- Use `reference_image_urls` for product images, brand assets, people, scenes, and style references.
- Use `source_video_url`, `motion_video_url`, and `audio_url` only when the chosen AI model variant supports them.

### Save Uploaded References

If an agent receives media in chat:

1. Inspect or describe the media.
2. Call `GET /api/v1/reference-inspirations?suggest_targets=true` or MCP `suggest_reference_template_targets`.
3. Ask the user which target should store the reference.
4. Call `POST /api/v1/reference-inspirations`.
5. Use the returned id as `custom_reference_inspiration_id`.

Fields for `POST /api/v1/reference-inspirations`:

- `template_slug`
- `template_category`: `static-ads`, `video-templates`, or `slideshow-carousel`
- `media_kind`: `image`, `slideshow`, or `video`
- `visibility`: `private` or `public`
- `label`
- `image_urls`
- `images[].filename`, `images[].content_type`, `images[].data` for base64 images
- `video_url`

Inline base64 images must be PNG, JPEG, or WebP and are limited to roughly 10 MB decoded per image.

Creating a reference inspiration deducts 30 credits per media item before analysis is queued.

Use `GET /api/v1/reference-inspirations?recommend=true&template_slug=...&template_category=...&media_kind=...` to recommend saved references.

## Editor Operations

Use the editor API when the user wants to assemble or modify a video project.

Editor project `ready` means the project exists and can be opened in the Videotok editor. It does not require exporting or downloading an MP4.

Flow:

1. Create or choose a video with `create_editor_video` or `list_editor_videos`. Newly created editor projects are ready to open immediately.
2. Upload media with `upload_editor_media`, `upload_editor_media_from_url`, or list existing media with `list_editor_media`.
3. Add media with `add_editor_media`.
4. Inspect item ids with `get_editor_video`.
5. Apply structured edits with `apply_editor_edits`.

Timing rules:

- `from_seconds` places an item on the timeline.
- `duration_seconds` controls how long the item is visible/audible on the timeline.
- `source_start_seconds` trims into the original video/audio/captions source.
- `playback_rate` changes media speed; `1` is normal speed.

Supported edit operation types:

- `set_title`: `title`
- `remove_item`: `item_id`
- `set_item_timing`: `item_id`, `from_seconds`, `duration_seconds`
- `set_item_source`: `item_id`, `source_start_seconds`, `playback_rate`
- `set_item_audio`: `item_id`, `volume_db`, `audio_fade_in_seconds`, `audio_fade_out_seconds`
- `set_audio_levels`: `item_ids`, `exclude_item_ids`, `item_types`, `audio_roles`, `volume_db`, `audio_fade_in_seconds`, `audio_fade_out_seconds`
- `set_item_animation`: `item_id`, `enter`, `exit`
- `apply_item_transition`: `from_item_id`, `to_item_id`, `overlap_seconds`, `enter`, `exit`
- `split_item`: `item_id`, `at_seconds`
- `set_item_transform`: `item_id`, `left`, `top`, `width`, `height`, `opacity`
- `move_item_to_track`: `item_id`, `track_id`
- `set_item_layer_order`: `item_id`, `position`
- `add_text`: `text`, `from_seconds`, `duration_seconds`, `style`
- `update_text`: `item_id`, `text`, `style`
- `add_captions`: `captions`, `from_seconds`, `duration_seconds`, `style`
- `add_sound_effect`: `sound_effect_id`, `url`, `media_id`, `from_seconds`, `duration_seconds`, `volume_db`
- `add_voiceover`: `text`, `voice_id`, `from_seconds`, `volume_db`, `voice_settings`
- `update_captions`: `item_id`, `captions`, `style`
- `generate_captions_from_items`: `source_item_ids`, `captions_item_id`, `language`, `style`

Caption entries use Remotion-style JSON timing: `text`, `startMs`, `endMs`, optional `timestampMs`, optional `confidence`, and optional word-level `words`.

When `track_id` is omitted, added media is packed onto compatible existing tracks when timelines do not overlap. Only force a new or explicit track when layer order or overlap requires it.

Music, voiceovers, voice assets, and SFX are audio timeline items. Use `list_editor_media` with `media_type=audio` for audio plus voices, `media_type=voice` for voice-only, and MCP `list_editor_sound_effects` before `add_sound_effect` when choosing built-in SFX. Use `set_item_audio` for one item, or `set_audio_levels` to lower/duck groups by `audio_roles` (`sound_effect`, `music`, `voiceover`, `voice`, `source_video`, `audio`) or by `item_types`. Older audio items without `audioRole` are inferred from asset metadata and normalized when matched. Do not remove SFX just to lower their volume.

Use `add_voiceover` to generate fresh TTS audio from text and place it on the editor timeline. Use `recommend_voice` or `list_workspace_assets` first when the user did not specify a voice. To replace speech in only part of a video, split the source clip around that section, lower or mute the split segment with `set_item_audio` or `set_audio_levels`, then add the generated voiceover at the same `from_seconds`.

Use `add_editor_media` for background music from My Media or an HTTPS URL with `audio_role: "music"`. Then use `set_item_audio` or `set_audio_levels` on the music item to keep it behind speech, usually around `-18` to `-28` dB with short fades.

Use `set_item_layer_order` with `position=front` when captions or text must appear above videos. New `add_text`, `add_captions`, and `generate_captions_from_items` overlays are placed on a front layer by default. When `top` is omitted, new text overlays choose a safe vertical slot to avoid overlapping existing timed text/captions.

Use `generate_captions_from_items` when the user asks for captions that match the actual narration. It transcribes selected video or audio items, respects timeline placement, source trims, playback rate, and duration, then creates a front-layer captions item or replaces `captions_item_id`. It needs source items with remote media URLs and an available transcription provider.

Use `set_item_animation` for native editor visual transitions on videos, images, GIFs, text, and captions. Supported transition types are `fade`, `slide`, `scale`, `bounce`, `flip`, `zoom`, `glitch`, `swipe`, `float`, and `snap`. Set `enter` for how an item appears and `exit` for how it leaves. Pass `null` for `enter` or `exit` to clear an existing transition.

Use `apply_item_transition` for crossfade-style visual transitions. It moves the incoming item earlier so it overlaps the outgoing item, optionally preserves the incoming item's original end time, and applies exit/enter animations in one operation. Keep overlaps short when source clips include speech, because video item audio can overlap too. Use `set_item_audio` fades or `add_sound_effect` for audio transitions.

## Social Publishing

Use MCP `list_social_accounts` to list connected Instagram, TikTok, X, LinkedIn, Threads, YouTube, Pinterest, and Facebook accounts.

Use MCP `publish_media_to_social` to queue publishing for completed My Media images, GIFs, or videos.
Find the media id with `list_editor_media` when the user refers to the latest generated image or video.
Duplicate social account ids are ignored before publishing.

For large rendered media, first create a completed My Media item. Use MCP `upload_editor_media_from_url` when the file is reachable over HTTPS, or REST `POST /api/v1/editor/media` with multipart `file` when the file is local. Do not pass `file://` URIs or absolute local paths in `media.data`; that field is only for base64 bytes or data URLs.

Social account reads require `social:read` or `social:write`.
Publishing requires `social:write`.

### GET /api/v1/openapi.json

No auth required.
Use it to create typed clients or tool schemas.

### GET /api/v1/skill.md

No auth required.
Use it to teach agents the Videotok API contract.

### /api/mcp

Use Streamable HTTP MCP with Videotok sign-in through the connector OAuth flow.

The MCP server exposes organization-scoped behavior after the user approves a workspace.
HTTP 401/403 responses include OAuth protected-resource metadata for `generations:read generations:write social:read social:write`.

## Create A Static Ad

```json
{
  "type": "static_ad",
  "template_slug": "product-shoot",
  "preset_id": "cosmos-1779191129",
  "prompt": "Create a premium skincare ad for a vitamin C serum.",
  "aspect_ratio": "1:1",
  "resolution": "1K",
  "request_count": 1,
  "idempotency_key": "order-123-static"
}
```

## Create A Video Ad

```json
{
  "type": "video_ad",
  "template_slug": "viral-video-ads",
  "prompt": "Make a fast hook-driven ad for a new productivity app.",
  "aspect_ratio": "9:16",
  "duration": 8,
  "quality_tier": "high",
  "reference_image_urls": ["https://example.com/product.png"],
  "idempotency_key": "order-123-video"
}
```

## Create A UGC Ad

```json
{
  "type": "ugc_ad",
  "template_slug": "ugc-product-video",
  "prompt": "Natural creator-style testimonial for a collagen drink.",
  "aspect_ratio": "9:16",
  "duration": 8,
  "reference_image_urls": ["https://example.com/product.png"],
  "idempotency_key": "order-123-ugc"
}
```

## Create With An AI Model

```json
{
  "type": "ai_model",
  "model_slug": "nano-banana-2",
  "variant_id": "image",
  "prompt": "Minimal e-commerce hero image for white sneakers on concrete.",
  "aspect_ratio": "1:1",
  "resolution": "1K",
  "idempotency_key": "order-123-model"
}
```

## Errors

Errors are structured:

```json
{
  "error": {
    "code": "insufficient_credits",
    "message": "Insufficient credits for this request.",
    "retryable": false,
    "context": {
      "credits_required": 1200,
      "credits_available": 500
    }
  }
}
```

Common error codes:

- `unauthorized`: missing bearer token
- `invalid_api_key`: malformed, revoked, expired, or unknown key
- `forbidden`: key is valid but missing a required scope
- `payment_required`: organization is not on an active paid plan
- `insufficient_credits`: request cannot be queued with current credits
- `bad_request`: invalid body, params, or unsupported option
- `idempotency_conflict`: idempotency key is still processing or was used with a different payload
- `rate_limited`: too many generation requests
- `not_found`: resource does not exist or belongs to another organization
- `server_error`: unexpected server failure

Retry only when `error.retryable` is `true`.
For `rate_limited`, back off before retrying and keep the same idempotency key for paid requests.
For `server_error`, retry with exponential backoff and the same idempotency key.
Do not retry `bad_request`, `forbidden`, `payment_required`, `insufficient_credits`, or `idempotency_conflict` without changing the request or asking the user.
