Skip to main content

Configure Videos

Set content and metadata for videos within a bundle. You can configure a single video by position or update multiple videos in one batch 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 must be wrapped in a videos object — it is not a raw array.

{
"videos": [
{ "position": 1, "video_type": "video", "..." : "..." },
{ "position": 2, "video_type": "carousel", "..." : "..." }
]
}

Field Reference

Common Fields

FieldTypeRequiredDescription
positionintegerBatch only1-indexed video position. Required in batch requests.
video_typestringYes"video" or "carousel". For Instagram: carousel with instagram_content_type: "reel" = Fixed Photos (creates a video from images), carousel with instagram_content_type: "post" = swipeable Carousel.
descriptionstringYesCaption or description for the post.
target_publish_datestringYesDesired publish date (YYYY-MM-DD). Min 3 days ahead for new accounts, 1 day for existing.
video_urlstringConditionalVideo file URL. Required when video_type is "video". You can pass a public_url from the upload endpoint or any external URL (Google Drive, Dropbox, direct link…) — the API will automatically download and re-upload the file to our storage.
carousel_imagesstring[]ConditionalArray of image storage paths. Required when video_type is "carousel". Use the storage_path from the image upload response.
tiktok_sound_urlstringConditionalTikTok sound URL. Required for TikTok carousels, optional for TikTok videos.
editing_instructionsstringNoFree-text instructions for the editor (e.g., "Add logo at end").
external_refstringNoYour own reference ID for this video (e.g., campaign or CMS identifier).
profile_picture_urlstringNoStorage path for the account profile picture. Use the storage_path from the image upload response.

Instagram-Specific Fields

FieldTypeRequiredDescription
instagram_content_typestringYes (Instagram)"reel" or "post". Required for Instagram bundles.
instagram_locationstringNoLocation tag for the Instagram post.
instagram_collaboratorsstring[]NoArray of Instagram usernames to tag as collaborators.
instagram_audio_namestringNoName of the audio track for Instagram Reels.
instagram_add_to_storybooleanNoIf true, the creator also shares the post to their Instagram Story.

Instagram Content Type Combinations

instagram_content_typevideo_typeResult
reelvideoReel Video
reelcarouselReel Fixed Photos — creates a video from images (not swipeable)
postvideoPost Video
postcarouselPost Carousel — swipeable photo carousel

YouTube Fields (Coming Soon)

YouTube support is not yet available. The following fields are reserved for future use:

FieldTypeDescription
youtube_titlestringVideo title.
youtube_tagsstring[]Array of tags.
youtube_categorystringVideo category.
youtube_visibilitystring"public", "unlisted", or "private".

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/bundle-id/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/bundle-id/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"
}
}
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": [
"carousel-images/org_xxx/bundle_abc123/slide1.jpg",
"carousel-images/org_xxx/bundle_abc123/slide2.jpg",
"carousel-images/org_xxx/bundle_abc123/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": [
"carousel-images/org_xxx/bundle_abc123/slide1.jpg",
"carousel-images/org_xxx/bundle_abc123/slide2.jpg",
"carousel-images/org_xxx/bundle_abc123/slide3.jpg"
],
"tiktok_sound_url": "https://www.tiktok.com/music/chill-vibes-456",
"external_ref": "campaign-42-v2"
}
}

Instagram Reel (Video)

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/bundle-id/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 Reel Fixed Photos (creates a video from images, not swipeable)

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": "reel",
"description": "Style inspiration for spring",
"target_publish_date": "2026-03-20",
"carousel_images": [
"carousel-images/org_xxx/bundle_def456/slide1.jpg",
"carousel-images/org_xxx/bundle_def456/slide2.jpg"
],
"instagram_location": "Paris, France",
"instagram_collaborators": ["partner"],
"instagram_add_to_story": true
}'

Instagram Post Carousel (swipeable photo carousel)

curl -X PUT https://app.tokportal.com/api/ext/bundles/bundle_def456/videos/3 \
-H "X-API-Key: tok_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"video_type": "carousel",
"instagram_content_type": "post",
"description": "Our latest collection",
"target_publish_date": "2026-03-20",
"carousel_images": [
"carousel-images/org_xxx/bundle_def456/photo1.jpg",
"carousel-images/org_xxx/bundle_def456/photo2.jpg"
],
"instagram_location": "Paris, France"
}'
Instagram Carousel Behavior

For Instagram, video_type: "carousel" behaves differently depending on instagram_content_type:

  • With "reel": creates a video from your images (Fixed Photos — not swipeable)
  • With "post": creates a swipeable photo carousel

Automatic Video Download

You don't need to upload your video first. If you pass any external URL (Google Drive, Dropbox, any direct link) as video_url, the API will automatically download the file and store it on our servers. The returned video_url in the response will be the final hosted URL. This also works in batch configuration and CSV import.

URLs already hosted on our storage (pub-0d3f...r2.dev) are kept as-is (no redundant re-upload).


Batch Configuration

Configure multiple videos in a single request. The body must be wrapped in { "videos": [...] }.

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 '{
"videos": [
{
"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/bundle-id/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/bundle-id/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": [
"carousel-images/org_xxx/bundle_abc123/before.jpg",
"carousel-images/org_xxx/bundle_abc123/after.jpg"
],
"tiktok_sound_url": "https://www.tiktok.com/music/reveal-sound-202"
}
]
}'

Response:

{
"data": {
"bundle_id": "bundle_abc123",
"configured": 3,
"errors": [],
"results": [
{
"position": 1,
"video_type": "video",
"status": "configured"
},
{
"position": 2,
"video_type": "video",
"status": "configured"
},
{
"position": 3,
"video_type": "carousel",
"status": "configured"
}
]
}
}

If some videos fail validation, the response includes partial results:

{
"data": {
"bundle_id": "bundle_abc123",
"configured": 2,
"errors": [
{
"position": 3,
"error": "carousel_images is required when video_type is carousel"
}
],
"results": [
{
"position": 1,
"video_type": "video",
"status": "configured"
},
{
"position": 2,
"video_type": "video",
"status": "configured"
}
]
}
}

Date Validation

The target_publish_date must meet the following minimum lead times:

Account StatusMinimum 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"
}
}
}

Important: Media URL Types

When referencing uploaded files in video configuration:

  • video_url — Use the public_url from the video upload response.
  • carousel_images — Use the storage_path from the image upload response (not public_url).
  • profile_picture_url — Use the storage_path from the image upload response (not public_url).

See Media Upload for details on uploading files and obtaining URLs.