Agents × jobs · Mastra

Seed UGC across many accounts with Mastra

Seed UGC from Mastra: the same creative on N geo-targeted TikTok/Instagram accounts via create_bundles_bulk, disclose_as_ads, per-account analytics.

UGC seeding from Mastra means taking a batch of creator-style videos and getting them posted from many ordinary-looking accounts in the target market, so the campaign reads as organic rather than as one brand handle. TokPortal does the account side: create_bundles_bulk opens N accounts in one country, configure_bundle_video places each creative on its slot with disclose_as_ads when required, publish_bundle hands each account to a human manager, and export_analytics_videos gives you a per-account, per-video report. Each account is human-created and human-operated, which is what keeps a seeding wave from being flagged as coordinated automation.

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

A seeding plan is a matrix: creatives × accounts × dates. The agent starts with the accounts. create_bundles_bulk with platforms: ["tiktok"] (or ["tiktok","instagram"] to seed both), country, accounts_count (≤100 per call) and videos_per_account returns one bundle id per account. Each account gets its own configure_bundle_account — vary handles, bios and profile pictures (upload with upload_image_from_url) so the accounts look like different people, and consider advanced_warming_terms in the product's niche so the accounts have a history when the seeding starts.

Then the creatives. Upload each once (upload_videopublic_url) and reuse the URL across bundles; TokPortal's duplicate-post guard is per account, so the same file on ten different accounts is fine. Fill slots with configure_bundle_video or batch_configure_bundle_videos, staggering target_publish_date across days and accounts (max 3 per day per bundle) so the wave looks natural. Set disclose_as_ads: true where the content is paid promotion — the manager enables branded-content disclosure or adds #ad — and add tiktok_sound_url if the campaign runs on a sound. publish_bundle per bundle (or loop). If a client asks for the Spark/Partner code to boost a post, create_video_ad_code_request returns it after finalization (7 credits).

Reporting is where Mastra shines: export_analytics_videos (CSV, filter by country, platform, from/to) plus get_comment_pulse for what people say, aggregated by the agent into a campaign summary.

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

  1. tokportal_get_credit_costs — N accounts × (32 + 2 × videos) — quote before creating.
  2. tokportal_create_bundles_bulkplatforms, country, accounts_count, videos_per_account, optional advanced_warming_terms_count.
  3. tokportal_configure_bundle_account — Different persona per bundle: handle, name, bio, profile_picture_url.
  4. tokportal_upload_video — Upload each creative once; reuse public_url across bundles.
  5. tokportal_configure_bundle_video — Place creative on slot: description, target_publish_date, video_url, disclose_as_ads, tiktok_sound_url.
  6. tokportal_publish_bundle — One call per bundle.
  7. tokportal_create_video_ad_code_request — Spark Code / Partner Code for paid boosting after finalization (7 credits).
  8. tokportal_export_analytics_videos — Per-video CSV across all accounts for the campaign report.
  9. tokportal_get_comment_pulse — Sentiment / themes across the seeded posts.

Prompt to paste

Use the TokPortal MCP tools. Campaign: 12 UGC creatives, seed in Mexico on TikTok across 12 accounts,
one creative per account, dates spread over 2026-09-08 → 2026-09-12, all disclosed as ads.
Quote with get_credit_costs, call create_bundles_bulk (12 accounts, 1 video each, external_ref "mx-wave1"),
then show me the per-bundle configure_bundle_account and configure_bundle_video payloads before running them.

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)

# 15 seeding accounts in Brazil, 4 videos each, both platforms
curl -X POST https://app.tokportal.com/api/ext/bundles/bulk \
  -H "X-API-Key: sk_..." -H "Content-Type: application/json" -H "Idempotency-Key: $(uuidgen)" \
  -d '{"platforms":["tiktok","instagram"],"country":"BR","accounts_count":15,"videos_per_account":4,"external_ref":"seed-sept-br"}'

# Same creative on bundle A and bundle B, disclosed as ad
for B in BUNDLE_A BUNDLE_B; do
curl -X PUT https://app.tokportal.com/api/ext/bundles/$B/videos/1 \
  -H "X-API-Key: sk_..." -H "Content-Type: application/json" \
  -d '{"video_type":"video","description":"testei por 7 dias 👀 #publi","target_publish_date":"2026-09-05","video_url":"https://.../creative-1.mp4","disclose_as_ads":true}'
done

# Campaign export
curl "https://app.tokportal.com/api/ext/analytics/export/videos?country=BR&from=2026-09-01&to=2026-09-30" -H "X-API-Key: sk_..."

Key parameters

ParameterValuesNotes
accounts_count1–100 per bulk callOne bundle/account each; repeat calls for more.
platforms["tiktok"] · ["instagram"] · bothBulk creates accounts on each listed platform.
disclose_as_adsboolean (free)Branded-content disclosure or
target_publish_dateYYYY-MM-DDStagger across accounts; 3/day/bundle max.
external_ref≤200 charsCampaign tag copied to every bundle of the bulk call.
instagram_content_typereel · postFor Instagram slots; carousels via carousel_images.

Full schemas: OpenAPI reference · openapi.json.

Example configurations

Bulk seeding fleet

{"platforms":["tiktok"],"country":"MX","accounts_count":25,"videos_per_account":3,
 "wants_advanced_warming":true,"advanced_warming_terms_count":3,"external_ref":"launch-mx-wave1"}

Slot with disclosure and sound

{"video_type":"video","description":"lo probé y… #ad #skincare","target_publish_date":"2026-09-06",
 "video_url":"https://pub-xxx.r2.dev/videos/creative-2.mp4","disclose_as_ads":true,
 "tiktok_sound_url":"https://www.tiktok.com/music/original-sound-7300000000000000000"}

Ad code request (POST /videos/{id}/ad-code-request)

{"note":"Boost for MX wave 1"}

Credits

25 accounts × (32 + 3 × 2) = 950 credits for a 25-account, 3-post wave at standard rates, plus warming targets (5 each) and 7 credits per ad code. Quote live with get_credit_costs; see Credits & Pricing.

Why not the official API

The official APIs are built for a brand posting on its own audited app to accounts users authorized one by one; seeding across dozens of fresh accounts would need dozens of OAuth grants, an audit, and would still be capped per token (6 requests/minute) and per user per day. TokPortal's model — distinct human-operated accounts, dated slots, disclosure flags — is the shape seeding actually needs.

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

Only if you make them: use distinct handles, bios and pictures per configure_bundle_account, different warming terms, and staggered dates. Each account has its own manager, device and network.

Can I reuse the accounts for the next campaign?

Yes — list_accounts then videos_only bundles with account_id. Accounts remain managed and warm between waves.

How do I handle

Set disclose_as_ads: true on paid content; the manager enables the platform's branded-content toggle or adds #ad. Combine with create_video_ad_code_request if you plan to boost.

How do I report per creative rather than per account?

Put the creative id in each slot's external_ref (or name), then join export_analytics_videos on it in the agent.

Also works with

All 25 agents for "Seed UGC across many accounts"

Other jobs with Mastra