Videos
Video management in the TokPortal API. Video types, statuses, supported formats for TikTok and Instagram content.
Videos
Videos are the content units within a bundle. Each video occupies a specific position (1-indexed) in the bundle and represents a single piece of content to be published on a creator's social media account.
Video Types
Every video has a video_type that determines what content it contains:
| Type | Description |
|---|---|
video | A single video file |
carousel | Multiple images displayed as a slideshow |
story | A TikTok/Instagram Story — one video or one image, no description. Counts as one video slot and is verified by an account-manager screenshot (evidence_screenshot). See Configure Videos → Story Fields. |
Platform-Specific Behavior
Each platform supports different combinations of video types and has its own requirements.
TikTok
| Type | Requirements |
|---|---|
video | Video file required. Sound URL optional. |
carousel | Carousel images required. Sound URL required. |
story | Exactly one media: video_url or story_image_url. No description. Optional same-platform story_repost_url (+1 credit). |
Instagram requires the instagram_content_type field to distinguish between reels and feed posts:
| Content Type | Video Type | Result |
|---|---|---|
reel | video | Reel Video |
reel | carousel | Reel Fixed Photos — creates a video from images (not swipeable) |
post | video | Post Video |
post | carousel | Post Carousel — swipeable photo carousel |
INFO: Reel Fixed Photos vs Post Carousel On Instagram,
video_type: "carousel"behaves differently depending oninstagram_content_type:
- With
"reel": Instagram creates a video from your images (Fixed Photos — not swipeable). This is a Reel, not a carousel.- With
"post": Instagram creates a swipeable photo carousel in the feed.
Instagram also supports video_type: "story" (one video or one image, no instagram_content_type). See Configure Videos → Story Fields.
YouTube
YouTube accounts cannot be ordered through the API. Public bundle creation supports TikTok and Instagram only, and a YouTube bundle is rejected with YOUTUBE_DELAYED — even though GET /credit-costs lists a YouTube price, the price is real but the order path is not open. YouTube accounts are delivered through a separate, non-API flow; talk to the team. You may still see reserved YouTube fields in templates and generated schemas.
Video Status Lifecycle
Each video progresses through the following statuses:
pending → configured → published → accepted → in_review → finalized
| Status | Description |
|---|---|
pending | Position exists but no content has been configured yet. |
configured | Content has been uploaded and metadata set. Ready for review. |
published | The video has been published to the platform by the creator. |
accepted | The brand has reviewed and accepted the published video. |
in_review | The video is awaiting user review. If the user takes no review action for about 72 hours, TokPortal automatically moves the video listing to finalized. |
finalized | The video lifecycle is complete, either after user approval or automatic finalization at the end of the 72-hour review window. No further changes are allowed. |
The 72-hour window starts when the video listing enters in_review. Finalize it to approve it immediately, or request corrections before the window expires. If neither action is taken, finalization is automatic — this applies regardless of auto_finalize_videos, which does not switch automatic finalization off.
Platform Signals
Once a video is live, TokPortal checks what the platform did with it: about 48 hours after posting and again after 7 days, plus whenever the post is scraped for analytics. The result is returned on every video as platform_signals, also on the order progress page and in Analytics. The object is always present; every field is null until the first check — null means not checked yet, never no.
"platform_signals": {
"checked_at": "2026-09-22T05:47:52Z",
"not_recommended": true,
"not_recommended_since": "2026-09-19T05:28:00Z",
"ai_label": null,
"sound": "non_commercial",
"sound_reason": "Can't promote due to audio copyright issue"
}
| Field | Type | Description |
|---|---|---|
checked_at | string | null | Last time the live post was observed. |
not_recommended | boolean | null | TikTok Not For Feed / Not Recommended. true = the post stays online but is excluded from the For You feed and typically sits at 0 views. Usually a sign that TikTok treats the content as reused across accounts or low-effort. Re-posting the same media does not help; new original content on the account does. |
not_recommended_since | string | null | First observation of the flag. |
ai_label | creator | platform | null | An "AI-generated" label is shown on the post: creator = declared at posting time, platform = applied by TikTok's moderation on its own. |
sound | ok | non_commercial | removed | muted | null | non_commercial: the sound is outside TikTok's commercial music library — the post cannot be boosted with Promote / Spark Ads. removed: TikTok pulled the sound for copyright, the video plays muted. muted: Instagram muted the audio. |
sound_reason | string | null | Platform wording when the sound is restricted. |
The same observations are pushed as webhooks the moment they are detected: video.not_recommended, video.ai_labeled and video.sound_restricted. Portfolio-wide, GET /analytics/signals lists every flagged post.
Publish Date Rules
The target_publish_date field controls when the video should be published.
- Account still being created (not yet delivered): minimum 3 days from today.
- Account already delivered, or a bundle running on an existing account: minimum 1 day from today.
A bundle can also carry at most 3 videos targeting the same day. Dates earlier than the allowed minimum are rejected with a VALIDATION_ERROR.
List All Videos in a Bundle
Retrieve every video configured for a bundle.
GET /bundles/:id/videos
curl -X GET https://app.tokportal.com/api/ext/bundles/bundle_abc123/videos \
-H "X-API-Key: sk_xxx"
Response:
{
"data": [
{
"position": 1,
"video_type": "video",
"status": "configured",
"description": "Unboxing the new product line",
"target_publish_date": "2026-03-15",
"video_url": "https://pub-xxx.r2.dev/videos/abc123.mp4",
"external_ref": "campaign-42-v1",
"download_issue": false,
"download_issue_comment": null
},
{
"position": 2,
"video_type": "carousel",
"status": "pending",
"description": null,
"target_publish_date": null,
"video_url": null,
"external_ref": null,
"download_issue": false,
"download_issue_comment": null
}
]
}
Get a Single Video
GET /bundles/:id/videos/:position
curl -X GET https://app.tokportal.com/api/ext/bundles/bundle_abc123/videos/1 \
-H "X-API-Key: sk_xxx"
Response:
{
"data": {
"position": 1,
"video_type": "video",
"status": "configured",
"description": "Unboxing the new product line",
"target_publish_date": "2026-03-15",
"video_url": "https://pub-xxx.r2.dev/videos/abc123.mp4",
"tiktok_sound_url": "https://www.tiktok.com/music/original-sound-123",
"editing_instructions": "Add brand logo at the end",
"external_ref": "campaign-42-v1",
"download_issue": false,
"download_issue_comment": null,
"platform_signals": {
"checked_at": null,
"not_recommended": null,
"not_recommended_since": null,
"ai_label": null,
"sound": null,
"sound_reason": null
}
}
}
What's Next
| Topic | Description |
|---|---|
| Configure Videos | Set content, metadata, and platform-specific fields |
| Patch Video Metadata | Update external_ref or name at any time without re-uploading content |
| CSV Import | Bulk-import videos from a CSV file |
| Video Actions | Finalize, request corrections, or unschedule videos |
| Fix Download Link | Detect and fix broken download links flagged by managers |