Run a faceless TikTok channel with Mastra
Run a faceless TikTok channel from Mastra: AI-generated clips → upload_video → 3 dated posts a day via batch_configure_bundle_videos, AI label on, human…
A faceless channel from Mastra is a pipeline: your generator (Sora, Veo, Runway, ElevenLabs + stock footage — whatever you use) produces clips, the agent uploads them with upload_video, fills dated slots with batch_configure_bundle_videos (up to 3 per day per bundle, ai_content_disclaimer: true where it applies) and publish_bundle; a TokPortal manager posts them from a real, geo-targeted account and get_account_analytics tells you what worked. No OAuth per channel, no app audit, and the account is warmed and held by a human, which is what faceless projects usually lack.
Connect TokPortal to Mastra
Mastra is an agent framework (code): TypeScript agent framework; MCPClient from @mastra/mcp connects HTTP or stdio MCP servers and hands their tools to an Agent.
npm i @mastra/core @mastra/mcp
import { Agent } from '@mastra/core/agent';
import { MCPClient } from '@mastra/mcp';
const mcp = new MCPClient({
servers: {
tokportal: {
url: new URL('https://app.tokportal.com/api/ext/mcp'),
requestInit: {
headers: { 'X-API-Key': process.env.TOKPORTAL_API_KEY! },
},
},
},
timeout: 30000,
});
export const socialOps = new Agent({
id: 'social-ops',
name: 'Social ops',
instructions: 'You operate TikTok and Instagram accounts through TokPortal tools. Quote credit costs before creating bundles.',
model: 'anthropic/claude-sonnet-4-5',
tools: await mcp.listTools(),
});
Tools are namespaced tokportal_tokportal_* (server name + tool name). Use mcp.listToolsets() to pass tools per request instead of at construction, and mcp.disconnect() on shutdown.
Snippet status: verified against Mastra's documentation (source).
Once connected, sanity-check the setup with a read-only call — "What is my TokPortal credit balance?" should trigger tokportal_get_credit_balance. Every tool runs as your TokPortal account and spends your credits; read-only tools (get_*, list_*, export_*) never do.
How it works
The economics of faceless channels are volume and consistency, so the design starts with the 3-videos-per-day-per-bundle cap: one channel is one account, one account posts at most 3 times a day, and a 30-day content plan is 90 slots (videos_quantity: 90). If you run five channels, run five bundles; create_bundles_bulk creates them in one call, each becoming its own account in the chosen country.
Per clip the agent needs a file URL, a caption and a date. upload_video gives a presigned PUT target and a public_url — from a script the agent uploads directly; from a chat host it can pass any public URL (your storage bucket, a Drive/R2 link) straight into video_url. batch_configure_bundle_videos takes the whole month at once; each item carries position, video_type: "video", description (caption + hashtags, ≤2200 chars), target_publish_date, video_url, and optionally tiktok_sound_url for a trending sound, ai_content_disclaimer: true (free — the manager toggles TikTok's AI-generated label) and editing_instructions if you want light edits (edit slots cost 3 credits). disclose_as_ads covers sponsored clips.
After publish_bundle, videos progress to finalized (auto after 72 h in review unless you disable auto_finalize_videos), and the agent closes the loop with list_account_video_analytics (per-video views/likes/comments) and get_analytics_series (daily followers/views), then adjusts the next batch. A weekly cron in Mastra — "pull last week's analytics, rank hooks, generate 21 new clips, fill next week's slots" — is the whole operating model.
Run it from Mastra
With Mastra the sequence is driven by your code: give the agent the tools from the TokPortal MCP server and the prompt below as the user message (or split it into tasks). Log every tokportal_* call and its arguments in development — the tool list is large (91 tools), so consider filtering to the ones this job needs.
Tool sequence
tokportal_create_bundle—account_and_videos,platform: tiktok,country,videos_quantity: 90for a month; optional warming terms in the channel's niche.tokportal_configure_bundle_account— Channel handle, display name, bio and aprofile_picture_url(upload withupload_image_from_url).tokportal_upload_video— Presigned upload per generated clip →public_url.tokportal_batch_configure_bundle_videos— Whole month in one call;ai_content_disclaimer: true; 3 per day.tokportal_publish_bundle— Manager creates the account, warms if ordered, then posts by date.tokportal_list_account_video_analytics— Per-video performance to rank hooks and formats.tokportal_get_analytics_series—metric=followers|views,granularity=dayfor the channel curve.tokportal_add_video_slots— Extend the same account withquantitymore slots next month.
Prompt to paste
Use the TokPortal MCP tools. I run a faceless "history shorts" channel; clips are at
https://cdn.example.com/history/clip-001.mp4 … clip-021.mp4 with captions in captions.csv.
Create a TikTok bundle in the US (account_and_videos, 21 videos), configure @rome.in.45s,
fill positions 1–21 with batch_configure_bundle_videos (3 per day from 2026-09-01, ai_content_disclaimer true),
run get_bundle_publish_readiness and wait for my GO before publish_bundle.
Run with mastra dev and test in the playground, or call agent.generate() from your server code.
REST equivalent (same operations, X-API-Key header, base URL https://app.tokportal.com/api/ext)
# Channel account + 90 slots
curl -X POST https://app.tokportal.com/api/ext/bundles \
-H "X-API-Key: sk_..." -H "Content-Type: application/json" -H "Idempotency-Key: $(uuidgen)" \
-d '{"bundle_type":"account_and_videos","platform":"tiktok","country":"US","videos_quantity":90,"title":"History shorts"}'
# Presigned upload for one clip
curl -X POST https://app.tokportal.com/api/ext/upload/video \
-H "X-API-Key: sk_..." -H "Content-Type: application/json" \
-d '{"filename":"clip-001.mp4","content_type":"video/mp4","bundle_id":"BUNDLE_ID"}'
# → PUT the file to data.upload_url, then use data.public_url as video_url
# Batch three per day, AI label on
curl -X PUT https://app.tokportal.com/api/ext/bundles/BUNDLE_ID/videos/batch \
-H "X-API-Key: sk_..." -H "Content-Type: application/json" \
-d '{"videos":[{"position":1,"video_type":"video","description":"Why Rome fell in 45 seconds #history","target_publish_date":"2026-09-01","video_url":"https://.../clip-001.mp4","ai_content_disclaimer":true}]}'
Key parameters
| Parameter | Values | Notes |
|---|---|---|
videos_quantity | 0–500 | 90 = one month at 3/day. |
ai_content_disclaimer | boolean (free) | Manager enables TikTok's AI-generated content label. |
description | ≤2200 chars | Caption + hashtags; required for video/carousel. |
tiktok_sound_url | URI | Trending sound; volume_added_sound 0–200 (1 credit). |
editing_instructions | ≤5000 chars | Light edits by the manager; needs edit slots (3 credits each). |
auto_finalize_videos | boolean (default true) | Keep true for hands-off channels. |
Full schemas: OpenAPI reference · openapi.json.
Example configurations
Channel with niche warming
{"bundle_type":"account_and_videos","platform":"tiktok","country":"US","videos_quantity":90,
"wants_advanced_warming":true,"advanced_warming_terms":["history facts","ancient rome","ww2 documentary"]}
Batch item for an AI clip
{"position":12,"video_type":"video","description":"The pirate who stole a whole navy 🏴☠️ #history #storytime",
"target_publish_date":"2026-09-04","video_url":"https://pub-xxx.r2.dev/videos/b/012.mp4","ai_content_disclaimer":true}
Extend next month
{"quantity":90}
Credits
One channel month ≈ 32 (account) + 90 × 2 (slots) = 212 credits at standard rates, plus 5 per warming target and 3 per edit slot if used. Subsequent months are slots only (add_video_slots, 2 credits each). Live rates via get_credit_costs — see Credits & Pricing.
Why not the official API
Faceless operators hit every wall of the official route at once: each channel needs its own OAuth grant, posts stay private until the app is audited, the per-token 6 requests/minute limit and the undocumented daily cap (spam_risk_too_many_posts) throttle multi-channel schedules, and the account still has to be created and warmed by hand. TokPortal collapses that into one API key, human-operated accounts and dated slots.
As of August 2026 the first-party routes look like this. TikTok's Content Posting API (Direct Post) requires each account owner to authorize your app with the video.publish scope, limits every user access token to 6 requests per minute, keeps all posts from unaudited apps in private viewing mode until TikTok audits the app, and enforces an unpublished daily post cap per user (spam_risk_too_many_posts) that integrators commonly report at roughly 15–25 posts per account per day. Meta's Instagram Content Publishing API allows 100 API-published posts per professional account in a 24-hour moving window and only for accounts you own and connect via OAuth. Neither creates accounts, warms them, or reports third-party bans. TokPortal is human-operated infrastructure: accounts created and run by managers in the target country, one X-API-Key for all of them, dated slots (max 3 per day per bundle) instead of per-account tokens.
Sources: TikTok Content Posting API – Direct Post, TikTok Content Posting API – Get started, Instagram Platform – Content Publishing.
FAQ
Can the agent upload straight from a generation API?
Yes — most generators return a temporary URL; the agent fetches it and PUTs to the presigned upload_video URL (or, in hosts without file access, passes the public URL directly as video_url if it stays valid until posting).
Should I always set ai_content_disclaimer?
If the clip is AI-generated, yes: it is free, it is TikTok's rule, and it protects the account. Set disclose_as_ads too when the clip is sponsored.
How do I run several channels in different niches?
One bundle per channel; use external_ref (e.g. history-us-01) so your agent can list_bundles by reference, and different warming terms per bundle.
What if a clip fails TikTok's rules?
The manager flags it (video.pending_corrections with a comment); the agent replaces video_url/caption with configure_bundle_video and it re-enters the queue.
Related
Also works with
- Run a faceless TikTok channel with Microsoft Copilot Studio
- Run a faceless TikTok channel with Factory Droid
- Run a faceless TikTok channel with n8n
- Run a faceless TikTok channel with Make
- Run a faceless TikTok channel with Zapier
- Run a faceless TikTok channel with Pipedream
All 25 agents for "Run a faceless TikTok channel"
Other jobs with Mastra
- Create TikTok accounts with Mastra
- Post 100 TikTok videos a day with Mastra
- Run US TikTok accounts from abroad with Mastra
- Warm TikTok & Instagram accounts with Mastra
- Seed UGC across many accounts with Mastra
- Seed a music sound on TikTok with Mastra
- Launch an app with persona accounts with Mastra
- Run multi-client agency operations with Mastra
- Get ban alerts via webhooks with Mastra
- Pull analytics across all accounts with Mastra
- Create Instagram accounts with Mastra