SMM multi-account runner A–Z
Bind caller-owned brand, agency, UGC and theme-page accounts to sticky 1:1 mobile device + city contexts, run realistic multi-day organic warming and foreground lifecycle loops, brand profiles, precheck & publish media, and convert comment/DM leads.
1. Sticky 1:1 device contexts, lifecycle hygiene & multi-day warming
Most SMM automation fails because operators fire raw upload calls from cold sessions or shared datacenter footprints without mobile foreground telemetry. Every Connected Workspace account on Tikultra is pinned 1:1 to a dedicated FullPool Android or iOS context in one city (miami, london, los_angeles). Before publishing on a newly imported session, run 2–3 daily foreground sessions (session/warm-reopen → warm/niche + warm/seed-accounts + warm/watch-item → session/tick → session/background) so TikTok’s interest graph and trust signals match a real niche user.
| Action | Endpoint | Cost |
|---|---|---|
| Import session | POST /v1/account/import | 25 cr |
| Email sign-in: send code | POST /v1/account/login/otp/send | 25 cr |
| Session health | GET /v1/account/health | 15 cr |
| Warm reopen lifecycle | POST /v1/account/session/warm-reopen | 15 cr |
| Warm session for niche | POST /v1/account/warm/niche | 25 cr |
| Warm from seed creators | POST /v1/account/warm/seed-accounts | 25 cr |
| Watch item telemetry | POST /v1/account/warm/watch-item | 15 cr |
| Update profile | POST /v1/account/profile/update | 25 cr |
| Upload precheck | GET /v1/account/upload/precheck | 15 cr |
| Publish video | POST /v1/account/upload/video | 100 cr |
| Inbox | GET /v1/account/dm/inbox | 20 cr |
| Send message | POST /v1/account/dm/send | 35 cr |
2. Runnable daily SMM fleet loop (warm → brand → precheck → publish → DM)
1import { TikUltra } from 'tikultra'
2
3const client = new TikUltra({ apiKey: process.env.TIKULTRA_KEY, os: 'ios', appFlavour: 'tiktok', region: 'US', city: 'miami' })
4
5export async function runDailySmmCycle(accountId: string, videoUrl?: string) {
6 // 1. Verify session health & sticky device context before mutating
7 const health = await client.account.health(accountId)
8 if (health.data.restricted || health.data.status === 'expired') {
9 throw new Error(`Session ${accountId} requires attention: ${JSON.stringify(health.data)}`)
10 }
11
12 // 2. Foreground resume + organic niche, seed-creator & watch-dwell telemetry
13 await client.account.warmReopen(accountId)
14 await client.account.warmNiche({ account_id: accountId, niche: 'b2b saas', duration_sec: 45, like_items: true })
15 await client.account.warmSeedAccounts({ account_id: accountId, usernames: ['linear', 'vercel', 'raycast'], watch_per_profile: 2 })
16
17 // 3. Optional one-call prechecked video publish + bio CTA sync
18 let publishedAwemeId: string | undefined
19 if (videoUrl) {
20 const pre = await client.account.uploadPrecheck(accountId)
21 if (pre.data.can_publish !== false) {
22 const pub = await client.account.uploadVideo({
23 account_id: accountId,
24 video_url: videoUrl,
25 caption: 'How 3-person SaaS teams automate inbound pipeline #saas #founders #gtm',
26 visibility: 'public',
27 })
28 publishedAwemeId = pub.data.aweme_id
29 }
30 }
31
32 // 4. Pull inbound DM threads + close foreground session cleanly
33 const inbox = await client.account.dmInbox({ account_id: accountId, count: 20 })
34 await client.account.tick(accountId)
35 await client.account.background(accountId)
36 return { accountId, publishedAwemeId, unreadThreads: (inbox.data.items ?? []).length }
37}
warm/niche and warm/seed-accounts without uploading on Days 1–2, always check upload/precheck before upload/video, and operate strictly on accounts you own or manage under client authorization.