Configure Videos
Use these endpoints to set content and metadata for videos within a bundle. You can configure a single video by position or update multiple videos in one request.
Configure a Single Video
PUT /bundles/:id/videos/:position
Sets or updates the content and metadata for the video at the given position (1-indexed).
Configure Multiple Videos (Batch)
PUT /bundles/:id/videos/batch
Updates multiple videos in a single request. The request body is an array of video objects, each including a position field.
Field Reference
| Field | Type | Required | Description |
|---|---|---|---|
video_type | string | Yes | video or carousel |
description | string | Yes | Caption or description for the post |
target_publish_date | string | Yes | Desired publish date (YYYY-MM-DD). Min 3 days ahead for new accounts, 1 day for existing. |
video_url | string | Conditional | URL of the uploaded video file. Required when video_type is video. |
carousel_images | string[] | Conditional | Array of image URLs. Required when video_type is carousel. |
tiktok_sound_url | string | Conditional | TikTok sound URL. Required for TikTok carousels, optional for TikTok videos. |
editing_instructions | string | No | Free-text instructions for the creator (e.g., "Add logo at end"). |
external_ref | string | No | Your own reference ID for this video (e.g., campaign or CMS identifier). |
instagram_content_type | string | Conditional | reel or post. Required for Instagram bundles. |
instagram_location | string | No | Location tag for the Instagram post. |
instagram_collaborators | string[] | No | Array of Instagram usernames to tag as collaborators. |
instagram_audio_name | string | No | Name of the audio track for Instagram Reels. |
instagram_add_to_story | boolean | No | If true, the creator also shares the post to their Instagram Story. |
youtube_title | string | Conditional | Video title. Required for YouTube bundles. |
youtube_tags | string[] | No | Array of tags for the YouTube video. |
youtube_category | string | No | YouTube video category (e.g., Entertainment, Gaming). |
youtube_visibility | string | No | public, unlisted, or private. Defaults to public. |
Examples
TikTok Video
curl -X PUT https://app.tokportal.com/api/ext/bundles/bundle_abc123/videos/1 \
-H "X-API-Key: tok_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"video_type": "video",
"description": "Check out this new product! #ad #sponsored",
"target_publish_date": "2026-03-15",
"video_url": "https://pub-xxx.r2.dev/videos/tiktok-promo.mp4",
"tiktok_sound_url": "https://www.tiktok.com/music/trending-sound-789",
"editing_instructions": "Add brand watermark in bottom-right corner",
"external_ref": "campaign-42-v1"
}'
Response:
{
"data": {
"position": 1,
"video_type": "video",
"status": "configured",
"description": "Check out this new product! #ad #sponsored",
"target_publish_date": "2026-03-15",
"video_url": "https://pub-xxx.r2.dev/videos/tiktok-promo.mp4",
"tiktok_sound_url": "https://www.tiktok.com/music/trending-sound-789",
"editing_instructions": "Add brand watermark in bottom-right corner",
"external_ref": "campaign-42-v1"
}
}
TikTok Carousel
curl -X PUT https://app.tokportal.com/api/ext/bundles/bundle_abc123/videos/2 \
-H "X-API-Key: tok_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"video_type": "carousel",
"description": "Swipe through our latest collection 🛍️",
"target_publish_date": "2026-03-17",
"carousel_images": [
"https://your-storage.supabase.co/storage/v1/object/public/images/slide1.jpg",
"https://your-storage.supabase.co/storage/v1/object/public/images/slide2.jpg",
"https://your-storage.supabase.co/storage/v1/object/public/images/slide3.jpg"
],
"tiktok_sound_url": "https://www.tiktok.com/music/chill-vibes-456",
"external_ref": "campaign-42-v2"
}'
Response:
{
"data": {
"position": 2,
"video_type": "carousel",
"status": "configured",
"description": "Swipe through our latest collection 🛍️",
"target_publish_date": "2026-03-17",
"carousel_images": [
"https://your-storage.supabase.co/storage/v1/object/public/images/slide1.jpg",
"https://your-storage.supabase.co/storage/v1/object/public/images/slide2.jpg",
"https://your-storage.supabase.co/storage/v1/object/public/images/slide3.jpg"
],
"tiktok_sound_url": "https://www.tiktok.com/music/chill-vibes-456",
"external_ref": "campaign-42-v2"
}
}
Instagram Reel
curl -X PUT https://app.tokportal.com/api/ext/bundles/bundle_def456/videos/1 \
-H "X-API-Key: tok_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"video_type": "video",
"instagram_content_type": "reel",
"description": "Morning routine with our skincare line ✨",
"target_publish_date": "2026-03-20",
"video_url": "https://pub-xxx.r2.dev/videos/reel-skincare.mp4",
"instagram_location": "Los Angeles, California",
"instagram_collaborators": ["brandofficial"],
"instagram_audio_name": "Original Audio",
"instagram_add_to_story": true,
"external_ref": "ig-reel-001"
}'
Response:
{
"data": {
"position": 1,
"video_type": "video",
"instagram_content_type": "reel",
"status": "configured",
"description": "Morning routine with our skincare line ✨",
"target_publish_date": "2026-03-20",
"video_url": "https://pub-xxx.r2.dev/videos/reel-skincare.mp4",
"instagram_location": "Los Angeles, California",
"instagram_collaborators": ["brandofficial"],
"instagram_audio_name": "Original Audio",
"instagram_add_to_story": true,
"external_ref": "ig-reel-001"
}
}
Instagram Post Carousel
curl -X PUT https://app.tokportal.com/api/ext/bundles/bundle_def456/videos/2 \
-H "X-API-Key: tok_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"video_type": "carousel",
"instagram_content_type": "post",
"description": "Our new summer drop is here. Which piece is your favorite?",
"target_publish_date": "2026-03-22",
"carousel_images": [
"https://your-storage.supabase.co/storage/v1/object/public/images/summer1.jpg",
"https://your-storage.supabase.co/storage/v1/object/public/images/summer2.jpg",
"https://your-storage.supabase.co/storage/v1/object/public/images/summer3.jpg",
"https://your-storage.supabase.co/storage/v1/object/public/images/summer4.jpg"
],
"instagram_location": "Miami, Florida",
"instagram_add_to_story": false,
"external_ref": "ig-post-002"
}'
Response:
{
"data": {
"position": 2,
"video_type": "carousel",
"instagram_content_type": "post",
"status": "configured",
"description": "Our new summer drop is here. Which piece is your favorite?",
"target_publish_date": "2026-03-22",
"carousel_images": [
"https://your-storage.supabase.co/storage/v1/object/public/images/summer1.jpg",
"https://your-storage.supabase.co/storage/v1/object/public/images/summer2.jpg",
"https://your-storage.supabase.co/storage/v1/object/public/images/summer3.jpg",
"https://your-storage.supabase.co/storage/v1/object/public/images/summer4.jpg"
],
"instagram_location": "Miami, Florida",
"instagram_add_to_story": false,
"external_ref": "ig-post-002"
}
}
Batch Configuration
Configure multiple videos in a single request by sending an array of video objects, each with a position field.
curl -X PUT https://app.tokportal.com/api/ext/bundles/bundle_abc123/videos/batch \
-H "X-API-Key: tok_live_xxx" \
-H "Content-Type: application/json" \
-d '[
{
"position": 1,
"video_type": "video",
"description": "Day 1 of the challenge #ad",
"target_publish_date": "2026-03-15",
"video_url": "https://pub-xxx.r2.dev/videos/day1.mp4"
},
{
"position": 2,
"video_type": "video",
"description": "Day 2 — things are getting interesting #ad",
"target_publish_date": "2026-03-18",
"video_url": "https://pub-xxx.r2.dev/videos/day2.mp4",
"tiktok_sound_url": "https://www.tiktok.com/music/hype-beat-101"
},
{
"position": 3,
"video_type": "carousel",
"description": "Final results — swipe to see the transformation",
"target_publish_date": "2026-03-21",
"carousel_images": [
"https://your-storage.supabase.co/storage/v1/object/public/images/before.jpg",
"https://your-storage.supabase.co/storage/v1/object/public/images/after.jpg"
],
"tiktok_sound_url": "https://www.tiktok.com/music/reveal-sound-202"
}
]'
Response:
{
"data": [
{
"position": 1,
"video_type": "video",
"status": "configured",
"description": "Day 1 of the challenge #ad",
"target_publish_date": "2026-03-15"
},
{
"position": 2,
"video_type": "video",
"status": "configured",
"description": "Day 2 — things are getting interesting #ad",
"target_publish_date": "2026-03-18"
},
{
"position": 3,
"video_type": "carousel",
"status": "configured",
"description": "Final results — swipe to see the transformation",
"target_publish_date": "2026-03-21"
}
]
}
Date Validation
The target_publish_date must meet the following minimum lead times:
| Account Status | Minimum Lead Time |
|---|---|
| New (not yet delivered) | 3 days from today |
| Existing (already delivered) | 1 day from today |
If the date is too soon, the API returns a VALIDATION_ERROR:
{
"error": {
"code": "VALIDATION_ERROR",
"message": "target_publish_date must be at least 3 days from today for new accounts.",
"details": {
"field": "target_publish_date",
"minimum_date": "2026-02-14"
}
}
}