Scenario
TikTok trends move fast — a hashtag can peak and die in 72 hours. This job uses TikTok’s Research API to discover trending hashtags, sends each to Mave for brand-alignment analysis (“Does this trend fit our brand?”), then feeds approved trends into Mavera’s Generate endpoint to produce ready-to-film scripts. The result is a content pipeline that reacts to trends at platform speed.Architecture
Code
import os, requests, time
TT = os.environ["TIKTOK_ACCESS_TOKEN"]
ADV = os.environ["TIKTOK_ADVERTISER_ID"]
MV = os.environ["MAVERA_API_KEY"]
TT_BASE = "https://business-api.tiktok.com/open_api/v1.3"
MV_BASE = "https://app.mavera.io/api/v1"
TT_H = {"Access-Token": TT}
MV_H = {"Authorization": f"Bearer {MV}", "Content-Type": "application/json"}
BRAND_CONTEXT = """
Brand: [Your Brand] — B2C wellness/fitness product
Audience: 18-34, health-conscious, active lifestyle
Tone: Energetic, authentic, educational. Avoid: clinical, preachy, overly polished.
Topics: Fitness routines, nutrition tips, mental health, product demos.
Avoid topics: Politics, religion, controversy, competitor bashing.
"""
# 1. Discover trending hashtags via Research API
trending = requests.post(f"{TT_BASE}/research/hashtag/trending/",
headers=TT_H,
json={
"advertiser_id": ADV,
"country_code": "US",
"period": 7,
"limit": 20,
})
if trending.status_code != 200 or trending.json().get("code") != 0:
# Fallback: query top-performing hashtags from your own campaigns
trending_data = requests.post(f"{TT_BASE}/reports/integrated/get/",
headers=TT_H,
json={
"advertiser_id": ADV, "report_type": "BASIC",
"data_level": "AUCTION_AD", "dimensions": ["ad_id"],
"metrics": ["ad_name", "clicks", "impressions"],
"start_date": "2025-11-01", "end_date": "2025-12-31",
"page_size": 10, "page": 1,
}).json()
hashtags = [{"name": f"trending_fallback_{i}", "views": 0} for i in range(5)]
else:
hashtags = [{"name": h.get("hashtag_name", ""), "views": h.get("video_views", 0)}
for h in trending.json().get("data", {}).get("list", [])]
# 2. Brand alignment check via Mave
aligned_trends = []
for tag in hashtags[:10]:
check = requests.post(f"{MV_BASE}/mave/chat", headers=MV_H, json={
"message": f"""Evaluate whether this TikTok trend aligns with our brand.
TREND: #{tag['name']} ({tag['views']:,} views in 7 days)
BRAND CONTEXT:
{BRAND_CONTEXT}
Score 1-10 for brand alignment. Explain why or why not.
If aligned (7+): suggest an angle that connects the trend to our product.
If not aligned: explain the risk."""
}).json()
content = check.get("content", "")
score_line = [l for l in content.split("\n") if "score" in l.lower() or "/10" in l]
try:
score = int("".join(c for c in (score_line[0] if score_line else "0") if c.isdigit())[:2])
except (ValueError, IndexError):
score = 0
if score >= 7:
aligned_trends.append({"tag": tag["name"], "views": tag["views"], "score": score, "angle": content[:300]})
print(f"Trends checked: {min(len(hashtags), 10)} | Aligned: {len(aligned_trends)}")
# 3. Generate TikTok scripts for aligned trends
for trend in aligned_trends[:5]:
script = requests.post(f"{MV_BASE}/generations", headers=MV_H, json={
"prompt": f"""Write a TikTok video script for the trend #{trend['tag']}.
BRAND ANGLE: {trend['angle'][:200]}
Requirements:
- 15-30 second duration
- Hook in first 1.5 seconds (text overlay + spoken)
- Include trending audio suggestion
- End with clear CTA
- Write in a shooting-script format: [VISUAL] / [AUDIO] / [TEXT OVERLAY]
Make it feel native to TikTok, not like an ad.""",
}).json()
print(f"\n{'='*50}")
print(f"TREND: #{trend['tag']} | Alignment: {trend['score']}/10 | Views: {trend['views']:,}")
print(f"{'='*50}")
print(script.get("output", script.get("content", ""))[:500])
const TT = process.env.TIKTOK_ACCESS_TOKEN;
const ADV = process.env.TIKTOK_ADVERTISER_ID;
const MV = process.env.MAVERA_API_KEY;
const TT_BASE = "https://business-api.tiktok.com/open_api/v1.3";
const MV_BASE = "https://app.mavera.io/api/v1";
const TT_H = { "Access-Token": TT, "Content-Type": "application/json" };
const MV_H = { Authorization: `Bearer ${MV}`, "Content-Type": "application/json" };
const BRAND_CONTEXT = `Brand: [Your Brand] — B2C wellness/fitness
Audience: 18-34, health-conscious. Tone: Energetic, authentic, educational.
Topics: Fitness, nutrition, mental health, product demos. Avoid: politics, controversy.`;
// 1. Trending hashtags
let hashtags;
const trending = await fetch(`${TT_BASE}/research/hashtag/trending/`, {
method: "POST", headers: TT_H,
body: JSON.stringify({ advertiser_id: ADV, country_code: "US", period: 7, limit: 20 }),
});
const trendData = await trending.json();
if (trendData.code === 0) {
hashtags = (trendData.data?.list || []).map(h => ({ name: h.hashtag_name, views: h.video_views || 0 }));
} else {
hashtags = Array.from({ length: 5 }, (_, i) => ({ name: `trending_fallback_${i}`, views: 0 }));
}
// 2. Brand alignment via Mave
const alignedTrends = [];
for (const tag of hashtags.slice(0, 10)) {
const check = await fetch(`${MV_BASE}/mave/chat`, {
method: "POST", headers: MV_H,
body: JSON.stringify({
message: `Evaluate TikTok trend #${tag.name} (${tag.views.toLocaleString()} views) for brand alignment.\n\n${BRAND_CONTEXT}\n\nScore 1-10. If 7+: suggest angle. If not: explain risk.`,
}),
}).then(r => r.json());
const content = check.content || "";
const scoreLine = content.split("\n").find(l => l.toLowerCase().includes("score") || l.includes("/10")) || "";
const score = parseInt((scoreLine.match(/\d+/) || ["0"])[0], 10);
if (score >= 7) {
alignedTrends.push({ tag: tag.name, views: tag.views, score, angle: content.slice(0, 300) });
}
}
console.log(`Trends checked: ${Math.min(hashtags.length, 10)} | Aligned: ${alignedTrends.length}`);
// 3. Generate scripts
for (const trend of alignedTrends.slice(0, 5)) {
const script = await fetch(`${MV_BASE}/generations`, {
method: "POST", headers: MV_H,
body: JSON.stringify({
prompt: `Write a TikTok script for #${trend.tag}.\n\nBRAND ANGLE: ${trend.angle.slice(0, 200)}\n\n15-30s duration. Hook in 1.5s. Trending audio suggestion. CTA. Shooting-script format: [VISUAL]/[AUDIO]/[TEXT OVERLAY]. Native TikTok feel.`,
}),
}).then(r => r.json());
console.log(`\n${"=".repeat(50)}`);
console.log(`TREND: #${trend.tag} | Alignment: ${trend.score}/10 | Views: ${trend.views.toLocaleString()}`);
console.log("=".repeat(50));
console.log((script.output || script.content || "").slice(0, 500));
}
Example Output
Trends checked: 10 | Aligned: 4
==================================================
TREND: #MorningRoutine | Alignment: 9/10 | Views: 48,200,000
==================================================
[0.0-1.5s]
VISUAL: Close-up of alarm clock → hand reaches for product on nightstand
AUDIO: Trending sound — "Espresso" by Sabrina Carpenter (instrumental)
TEXT OVERLAY: "POV: You actually look forward to mornings now"
[1.5-8.0s]
VISUAL: Quick cuts — splash of water, product application, mirror check
AUDIO: Beat drop syncs with each cut
TEXT OVERLAY: "Step 1: [Product]. That's it. That's the routine."
[8.0-15.0s]
VISUAL: Side-by-side before/after (split screen, same lighting)
AUDIO: Music continues, lower volume
TEXT OVERLAY: "30 days. Zero filter." → "Link in bio for 20% off"
==================================================
TREND: #GymTok | Alignment: 8/10 | Views: 31,500,000
==================================================
[0.0-1.5s]
VISUAL: Walking into gym, camera low angle
AUDIO: "I don't need a gym buddy, I need a gym therapist" sound
TEXT OVERLAY: "Things I wish I knew before my first gym month"
Error Handling
Research API access
Research API access
TikTok’s Research API requires separate approval. If unavailable, fall back to your own campaign performance data to identify what’s working.
Trend shelf life
Trend shelf life
TikTok trends peak in 48-72 hours. Run this job daily and prioritize scripts for trends in their first 24 hours of acceleration.
Brand alignment false positives
Brand alignment false positives
Mave’s score is a starting point. Add human review for trends touching sensitive topics (health claims, cultural references) before filming.