Bundles
A bundle groups an account configuration and optional video configuration for a specific country and platform. Bundles are the core unit of work in the TokPortal API.
Authentication
All endpoints require an API key passed via the X-API-Key header.
X-API-Key: tok_live_xxx
Base URL
https://app.tokportal.com/api/ext
Bundle Types
| Type | Description |
|---|---|
account_only | Account creation and setup only. No videos. |
account_and_videos | Account creation with video uploads. |
videos_only | Video uploads on an existing account. |
Lifecycle
Bundles follow a strict lifecycle:
pending_setup → published → accepted → completed
For bundles that include videos, the video phase adds intermediate states:
accepted → in_review → finalized → completed
| Status | Description |
|---|---|
pending_setup | Bundle created, awaiting configuration. |
published | Configuration complete, submitted for processing. |
accepted | Account work has been accepted by an operator. |
in_review | Videos are being reviewed. |
finalized | Videos have been finalized. |
completed | All work is done. |
Platforms
| Platform | Value |
|---|---|
| TikTok | tiktok |
instagram | |
| YouTube | youtube |
Options
| Option | Description | Restrictions |
|---|---|---|
niche_warming | Warm the account by engaging with niche-relevant content before publishing. | Cannot combine with deep_warming. |
deep_warming | Extended warming with deeper engagement signals. | Instagram only. Cannot combine with niche_warming. |
moderation | Enable content moderation on the account. | — |
editing | Include video editing services. | — |
auto_finalize_videos | Automatically finalize videos once ready. | — |
Endpoints
| Method | Path | Description |
|---|---|---|
POST | /bundles | Create a bundle |
GET | /bundles | List all bundles |
GET | /bundles/:id | Get a single bundle |
PATCH | /bundles/:id | Update bundle settings |
GET | /bundles/:id/publish-readiness | Check publish-readiness |
POST | /bundles/:id/publish | Publish a bundle |
POST | /bundles/:id/unpublish | Unpublish a bundle |
Computed State Fields
Both GET /bundles and GET /bundles/:id return a set of read-only computed fields to make integration logic simpler. These derive from the underlying bundle / account / video state — you do not need to recompute them client-side.
| Field | Type | Description |
|---|---|---|
is_published | boolean | true once the bundle has been published (status is published, published_priority, accepted, or completed). |
account_configured | boolean | true when the bundle's account is in configured or finalized status (i.e., publish-eligible). |
videos_total | integer | Number of video slots on the bundle. |
videos_configured_count | integer | Number of video slots whose status indicates they have been configured (any of configured, in_review, pending_corrections, accepted, published, finalized). |
next_action | string | null | Suggested next step in the configure → publish flow. One of configure_account, configure_videos, publish_bundle, or null if no action is required. |
next_action is the recommended primary signal for an integration:
configure_account— callPUT /bundles/:id/accountto set the account fields.configure_videos— callPUT /bundles/:id/videos/batch(or per-position) to fill the video slots.publish_bundle— callPOST /bundles/:id/publish(or passauto_publish: trueon the next video configuration call).null— the bundle is already past setup; nothing to do.
List Bundles
Retrieve all bundles for your organization.
GET /bundles
Query Parameters
| Param | Type | Description |
|---|---|---|
status | string | Filter by bundle status: pending_setup, published, accepted, completed, etc. |
bundle_type | string | Filter by type: account_only, account_and_videos, videos_only. |
account_status | string | Filter by account listing status: pending, configured, in_review, finalized. Useful for finding bundles with accounts ready to finalize. |
platform | string | Filter by platform: tiktok, instagram, youtube. |
external_ref | string | Filter by your external reference. |
page | integer | Page number (default: 1). |
per_page | integer | Results per page (default: 25, max: 100). |
Example
# List all bundles with accounts awaiting finalization
curl -X GET "https://app.tokportal.com/api/ext/bundles?account_status=in_review" \
-H "X-API-Key: tok_live_xxx"
Response
{
"data": [
{
"id": "bnd_abc123",
"bundle_type": "account_and_videos",
"platform": "tiktok",
"country": "US",
"status": "accepted",
"account_status": "in_review",
"videos_quantity": 5,
"edits_quantity": 0,
"used_edits": 0,
"credit_cost": 60,
"external_ref": "campaign-42",
"existing_account_id": null,
"auto_finalize_videos": true,
"wants_niche_warming": true,
"wants_deep_warming": false,
"wants_moderation": false,
"is_published": true,
"account_configured": true,
"videos_total": 5,
"videos_configured_count": 5,
"next_action": null,
"created_at": "2026-01-15T10:30:00Z",
"updated_at": "2026-01-15T12:00:00Z"
}
]
}
Get Bundle
Retrieve a single bundle by ID.
GET /bundles/:id
Example
curl -X GET https://app.tokportal.com/api/ext/bundles/bnd_abc123 \
-H "X-API-Key: tok_live_xxx"
Response
{
"data": {
"id": "bnd_abc123",
"bundle_type": "account_and_videos",
"platform": "tiktok",
"country": "US",
"status": "published",
"videos_quantity": 3,
"edits_quantity": 0,
"used_edits": 0,
"credit_cost": 40,
"external_ref": "campaign-42",
"existing_account_id": null,
"auto_finalize_videos": false,
"wants_niche_warming": true,
"wants_deep_warming": false,
"wants_moderation": false,
"is_published": true,
"account_configured": true,
"videos_total": 3,
"videos_configured_count": 3,
"next_action": null,
"account": {
"username": "cooluser123",
"visible_name": "Cool User",
"biography": "Just vibes.",
"profile_picture_url": "https://example.com/pic.jpg"
},
"videos": [
{
"id": "vid_xyz",
"position": 1,
"status": "pending",
"name": "Video 1"
}
],
"created_at": "2026-01-15T10:30:00Z",
"updated_at": "2026-01-15T12:00:00Z"
}
}
Update Bundle
Update settings on an existing bundle. You can modify auto_finalize_videos, external_ref, and title at any time, regardless of bundle status.
PATCH /bundles/:id
Request Body
All fields are optional. At least one must be provided.
| Field | Type | Description |
|---|---|---|
auto_finalize_videos | boolean | Toggle auto-approval of videos. |
external_ref | string | null | Your own reference ID. Max 200 characters. Must be unique per user. Set to null to clear. |
title | string | null | Bundle title. Max 200 characters. Set to null to clear. |
Example
curl -X PATCH https://app.tokportal.com/api/ext/bundles/bnd_abc123 \
-H "X-API-Key: tok_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"auto_finalize_videos": false,
"external_ref": "campaign-42-updated"
}'
Response
{
"data": {
"id": "bnd_abc123",
"title": "My Campaign",
"auto_finalize_videos": false,
"external_ref": "campaign-42-updated",
"updated_at": "2026-02-10T14:30:00Z"
}
}
Error Responses
| Status | Code | Description |
|---|---|---|
400 | VALIDATION_ERROR | No fields provided, or invalid values. |
404 | BUNDLE_NOT_FOUND | Bundle does not exist. |
403 | BUNDLE_NOT_OWNED | Bundle belongs to another user. |
409 | DUPLICATE_EXTERNAL_REF | Another bundle already uses this external_ref. |
Check Publish-Readiness
Returns whether a bundle is currently ready for POST /bundles/:id/publish, and if not, the list of blockers that publish would raise. Read-only — no side effects, no credit charge. Useful to surface "what's missing" in your UI before attempting publish.
GET /bundles/:id/publish-readiness
Example
curl -X GET https://app.tokportal.com/api/ext/bundles/bnd_abc123/publish-readiness \
-H "X-API-Key: tok_live_xxx"
Response — ready
{
"data": {
"bundle_id": "bnd_abc123",
"ready": true,
"blockers": []
}
}
Response — blockers present
{
"data": {
"bundle_id": "bnd_abc123",
"ready": false,
"blockers": [
{
"code": "ACCOUNT_MISSING_FIELDS",
"message": "Account is missing required fields.",
"details": { "missing_fields": ["profile_picture_url"] }
}
]
}
}
Blocker Codes
| Code | Meaning |
|---|---|
BUNDLE_ALREADY_PUBLISHED | The bundle is already published or accepted. |
BUNDLE_NOT_IN_SETUP | The bundle's status is not pending_setup (e.g., draft, cancelled). |
ACCOUNT_MISSING | No account configuration exists yet for the bundle. |
ACCOUNT_NOT_CONFIGURED | The account exists but its status is not yet configured or finalized. |
ACCOUNT_MISSING_FIELDS | The account is missing one or more required fields (username, visible_name, profile_picture_url). |