Bundles

Create Bundle - Provision Accounts & Videos

Create a new TokPortal bundle via API to provision accounts and video slots for TikTok or Instagram campaigns.

Create Bundle

Create a new bundle to provision an account, upload videos, or both.

POST /bundles

All fields are top-level in the request body. There is no options wrapper.

Request Body

Required

FieldTypeDescription
bundle_typestring"account_only", "account_and_videos", or "videos_only".

Conditional

FieldTypeRequired WhenDescription
countrystringaccount_only, account_and_videosTokPortal country code or supported alias. Use GET /countries to list countries currently available for new account creation. Disabled countries and countries restricted to existing-account videos_only work are excluded. Optional for videos_only (derived from the saved account).
account_idstring (UUID)videos_onlyThe saved account ID to upload videos to. Only valid with bundle_type: "videos_only" — passing it on account_and_videos or account_only returns ACCOUNT_ID_NOT_ALLOWED (this prevents accidentally being charged the account-creation credits while reusing an existing account).
videos_quantityintegeraccount_and_videos, videos_onlyNumber of video slots. Must be greater than 0.

Optional

FieldTypeDefaultDescription
platformstring"tiktok""tiktok" or "instagram".
titlestringBundle title. Max 200 characters.
edits_quantityinteger0Number of video edits. Cannot exceed videos_quantity.
wants_advanced_warmingbooleanfalseEnable Advanced Niche Warming (recommended) — niche-target based warming with recorded proof and a data report. 3 credits per target, TikTok and Instagram only. Requires advanced_warming_terms_count or advanced_warming_terms. See the Advanced Niche Warming guide.
advanced_warming_terms_countintegerNumber of niche targets to purchase: 3-30, multiples of 3. Recommended flow: buy the count now and write the actual targets later via PUT /bundles/{id}/account. Purchases never configured within 14 days are auto-cancelled and fully refunded.
advanced_warming_termsstring[]Alternative to advanced_warming_terms_count: provide the niche targets immediately (3-30 terms, count multiple of 3, each 2-50 characters).
wants_niche_warmingbooleanfalseEnable niche warming (review-based, will be deprecated in favor of Advanced Niche Warming). Mutually exclusive with wants_advanced_warming.
wants_deep_warmingbooleanfalse⚠️ Discontinued. Any request with wants_deep_warming: true is rejected with DEEP_WARMING_DEPRECATED. Use Advanced Niche Warming instead.
wants_moderationbooleanfalse⚠️ Deprecated — no longer applied. Was the per-bundle "community management" add-on (25 credits). Use the Comments API instead. Sending it has no effect.
niche_warming_instructionsstringInstructions for niche warming. Required when wants_niche_warming is true.
moderation_noticestring⚠️ Deprecated — no longer applied. Was the guidelines notice for community management. Use the Comments API instead.
auto_finalize_videosbooleantrueAutomatically finalize videos when they are ready.
external_refstringYour own reference ID. Max 200 characters.

WARNING: Community management is deprecated The per-bundle "community management" / content-moderation add-on (wants_moderation, 25 credits) has been replaced by the standalone Comments API, which lets you post comments and reply to specific comments from your managed accounts. wants_moderation / moderation_notice are still accepted for backward compatibility but are ignored (no credits charged, no moderation provisioned).

Validation Rules

  • wants_advanced_warming requires either advanced_warming_terms_count or advanced_warming_terms (3-30 targets, multiples of 3) — otherwise ADVANCED_WARMING_TERMS. TikTok and Instagram only (ADVANCED_WARMING_PLATFORM).
  • wants_advanced_warming and wants_niche_warming are mutually exclusive (WARMING_CONFLICT).
  • wants_deep_warming: true is always rejected with DEEP_WARMING_DEPRECATED — deep warming is discontinued.
  • edits_quantity cannot exceed videos_quantity.
  • niche_warming_instructions is required when wants_niche_warming is true.
  • country must be available for new account creation. Disabled countries and countries restricted to existing-account videos_only work are rejected. US and GB aliases are accepted and normalized by the API.

GET /countries keeps new-account countries in data and exposes countries available for existing-account video orders in videos_only_countries. For example, a country can be absent from data but present in videos_only_countries; in that case, new account creation is blocked while a videos_only order linked to an existing account remains supported.

Response

{
  "data": {
    "bundle_id": "...",
    "bundle_type": "account_and_videos",
    "platform": "tiktok",
    "country": "US",
    "status": "pending_setup",
    "videos_quantity": 5,
    "edits_quantity": 2,
    "external_ref": "my-campaign-001",
    "created_at": "2026-02-10T09:00:00Z"
  },
  "credits_charged": 41,
  "credits_remaining": 459,
  "cost_breakdown": {
    "account": 25,
    "videos": 10,
    "edits": 6,
    "niche_warming": 0,
    "deep_warming": 0,
    "moderation": 0
  }
}
FieldTypeDescription
data.bundle_idstringUnique identifier for the created bundle.
data.bundle_typestringThe bundle type as submitted.
data.platformstringTarget platform.
data.countrystringCountry code.
data.statusstringInitial bundle status.
data.videos_quantityintegerNumber of video slots (if applicable).
data.edits_quantityintegerNumber of edits (if applicable).
data.external_refstringYour external reference (if provided).
data.created_atstringISO 8601 timestamp.
credits_chargedintegerCredits deducted for this bundle.
credits_remainingintegerYour remaining credit balance.
cost_breakdownobjectItemized cost breakdown.

Examples

1. Account and Videos (with niche warming)

curl -X POST https://app.tokportal.com/api/ext/bundles \
  -H "X-API-Key: sk_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "bundle_type": "account_and_videos",
    "platform": "tiktok",
    "country": "US",
    "videos_quantity": 5,
    "edits_quantity": 2,
    "wants_niche_warming": true,
    "niche_warming_instructions": "Focus on fitness and gym content. Follow fitness influencers, like workout videos.",
    "auto_finalize_videos": true,
    "external_ref": "campaign-42"
  }'

Response:

{
  "data": {
    "bundle_id": "bnd_a1b2c3d4",
    "bundle_type": "account_and_videos",
    "platform": "tiktok",
    "country": "US",
    "status": "pending_setup",
    "videos_quantity": 5,
    "edits_quantity": 2,
    "external_ref": "campaign-42",
    "created_at": "2026-02-10T09:00:00Z"
  },
  "credits_charged": 48,
  "credits_remaining": 452,
  "cost_breakdown": {
    "account": 25,
    "videos": 10,
    "edits": 6,
    "niche_warming": 7,
    "deep_warming": 0,
    "moderation": 0
  }
}

2. Account Only (with Advanced Niche Warming, targets configured later)

curl -X POST https://app.tokportal.com/api/ext/bundles \
  -H "X-API-Key: sk_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "bundle_type": "account_only",
    "platform": "instagram",
    "country": "FR",
    "wants_advanced_warming": true,
    "advanced_warming_terms_count": 9,
    "title": "French lifestyle account"
  }'

Response:

{
  "data": {
    "bundle_id": "bnd_e5f6g7h8",
    "bundle_type": "account_only",
    "platform": "instagram",
    "country": "FR",
    "status": "pending_setup",
    "videos_quantity": 0,
    "edits_quantity": 0,
    "wants_advanced_warming": true,
    "advanced_warming_terms": [],
    "advanced_warming_terms_count": 9,
    "external_ref": null,
    "created_at": "2026-02-10T09:05:00Z"
  },
  "credits_charged": 52,
  "credits_remaining": 400,
  "cost_breakdown": {
    "account": 25,
    "videos": 0,
    "edits": 0,
    "niche_warming": 0,
    "deep_warming": 0,
    "advanced_warming": 27,
    "moderation": 0
  }
}

The 9 niche targets are written afterwards on the bundle: PUT /bundles/{id}/account with advanced_warming_terms. See the Advanced Niche Warming guide.

3. Videos Only (existing account)

Recommendation: Instead of creating a videos_only bundle, consider using the add-video-slots endpoint on an existing active bundle. This preserves the same account manager, which is better for continuity and turnaround time.

curl -X POST https://app.tokportal.com/api/ext/bundles \
  -H "X-API-Key: sk_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "bundle_type": "videos_only",
    "account_id": "9f3a7b2e-1c4d-4e8f-a5b6-7d9e0f1a2b3c",
    "videos_quantity": 3,
    "external_ref": "restock-wave-2"
  }'

Response:

{
  "data": {
    "bundle_id": "bnd_i9j0k1l2",
    "bundle_type": "videos_only",
    "platform": "tiktok",
    "country": "US",
    "status": "pending_setup",
    "videos_quantity": 3,
    "edits_quantity": 0,
    "external_ref": "restock-wave-2",
    "created_at": "2026-02-10T09:10:00Z"
  },
  "credits_charged": 6,
  "credits_remaining": 381,
  "cost_breakdown": {
    "account": 0,
    "videos": 6,
    "edits": 0,
    "niche_warming": 0,
    "deep_warming": 0,
    "moderation": 0
  }
}

Note: platform and country are derived from the saved account when using videos_only.

Error Responses

StatusCodeDescription
400VALIDATION_ERRORInvalid or missing fields (see details for specifics).
400WARMING_CONFLICTwants_advanced_warming and wants_niche_warming cannot both be enabled.
400ADVANCED_WARMING_TERMSProvide advanced_warming_terms (3-30 terms, multiple of 3, each 2-50 chars) or advanced_warming_terms_count (3-30, multiple of 3).
400ADVANCED_WARMING_PLATFORMAdvanced Niche Warming is only available for TikTok and Instagram.

| 400 | EDITS_EXCEED_VIDEOS | edits_quantity exceeds videos_quantity. | | 400 | COUNTRY_NOT_ENABLED | Country is not enabled for your organization. | | 400 | ACCOUNT_ID_NOT_ALLOWED | account_id was passed with a bundle_type other than videos_only. Set bundle_type to videos_only to add videos to an existing account, or omit account_id. | | 402 | INSUFFICIENT_CREDITS | Not enough credits to create this bundle. | | 404 | ACCOUNT_NOT_FOUND | account_id does not exist or does not belong to your organization. |

FAQ

Can I comment or reply to comments?

Yes — but not through bundle creation. Commenting is its own product, the Comments API, separate from bundles.

From any of your delivered (managed) accounts, you can:

  • Comment on a video — post a comment under any TikTok/Instagram video. Set target_type: "video" and pass target_video_url.
  • Reply to a specific comment — reply under a particular comment on a TikTok video (TikTok only). Set target_type: "comment" and pass target_comment_url (the link from the app's Share comment → Copy link).

The assigned account manager posts it, then TokPortal auto-verifies the comment/reply by scraping the target (matching your account handle + text). Each comment costs 1 credit, debited up-front and refunded if it can't be fulfilled.

curl -X POST https://app.tokportal.com/api/ext/comments \
  -H "X-API-Key: sk_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "saved_account_id": "9f3a7b2e-1c4d-4e8f-a5b6-7d9e0f1a2b3c",
    "target_type": "comment",
    "target_comment_url": "https://www.tiktok.com/t/ZT9j5AXVsyuRS/",
    "comment_text": "100% agree with this!"
  }'

See the full Comments API reference for lifecycle, verification, and batch usage.

The old per-bundle "community management" add-on (wants_moderation) is deprecated in favor of this Comments API.