Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.mavera.io/llms.txt

Use this file to discover all available pages before exploring further.

Scenario

Perigon’s /stories/all endpoint groups related articles into story clusters — each cluster represents a single narrative arc across multiple sources. This job pulls top story clusters for your industry, asks Mave to evaluate each cluster for content potential and timing, then generates a week’s worth of content calendar entries with formats, angles, and publish dates. Flow: Perigon GET /stories/all → Mavera POST /mave/chat (evaluate clusters) → POST /generations (calendar entries) → Content calendar

Code

import os, requests, time

PG_KEY = os.environ["PERIGON_API_KEY"]
PG_BASE = "https://api.goperigon.com/v1"
MV = os.environ["MAVERA_API_KEY"]
MV_BASE = "https://app.mavera.io/api/v1"
MV_H = {"Authorization": f"Bearer {MV}", "Content-Type": "application/json"}

TOPIC = "artificial intelligence"
BRAND = "Enterprise SaaS platform for marketing teams. Audience: VP Marketing, CMO. Tone: strategic, data-backed, forward-looking."

# 1. Fetch story clusters
r = requests.get(f"{PG_BASE}/stories/all", params={
    "apiKey": PG_KEY, "q": TOPIC, "sortBy": "createdAt",
    "size": 15, "sourceGroup": "top100",
})
r.raise_for_status()
stories = r.json().get("results", [])
print(f"Fetched {len(stories)} story clusters for '{TOPIC}'")

# 2. Build cluster summaries
cluster_text = []
for s in stories:
    articles = s.get("articles", [])
    sources = [a.get("source", {}).get("name", "") for a in articles[:5]]
    cluster_text.append(
        f"CLUSTER: {s.get('name', s.get('title', 'Unnamed'))}\n"
        f"Articles: {s.get('articleCount', len(articles))}\n"
        f"Sources: {', '.join(set(sources))}\n"
        f"Summary: {s.get('summary', '')[:300]}\n"
        f"Created: {s.get('createdAt', '')[:10]}"
    )

# 3. Mave evaluates clusters for content potential
evaluation = requests.post(f"{MV_BASE}/mave/chat", headers=MV_H, json={
    "message": f"Content strategist. Evaluate these {len(stories)} news story clusters for content calendar potential.\n\n"
        f"BRAND: {BRAND}\n\n"
        + "\n\n".join(cluster_text)
        + "\n\nFor each cluster score content potential (1-10). For clusters 7+:\n"
        "- Suggested content format (blog, LinkedIn, webinar, infographic, podcast)\n"
        "- Angle that ties to our brand\n"
        "- Optimal publish timing (ride the wave vs. contrarian delay)\n"
        "- Target persona\n\n"
        "Return a ranked list."
}).json()
print(f"\nCluster Evaluation:\n{evaluation.get('content', '')[:1500]}")

# 4. Generate calendar
calendar = requests.post(f"{MV_BASE}/generations", headers=MV_H, json={
    "prompt": f"Build a 7-day content calendar from these evaluated story clusters.\n\n"
        f"EVALUATION:\n{evaluation.get('content', '')[:3000]}\n\n"
        f"BRAND: {BRAND}\n\n"
        "For each day (Mon-Sun):\n"
        "- Content piece title\n"
        "- Format (blog/LinkedIn/tweet thread/webinar/email)\n"
        "- Story cluster it references\n"
        "- Key message (1 sentence)\n"
        "- CTA\n"
        "- Estimated production time\n\n"
        "Ensure variety in formats. Front-load time-sensitive topics.",
}).json()
print(f"\n{'='*60}\nCONTENT CALENDAR\n{'='*60}")
print(calendar.get("output", calendar.get("content", ""))[:2000])

Example Output

Fetched 15 story clusters for 'artificial intelligence'

Cluster Evaluation:
1. "OpenAI Enterprise Pricing Restructure" (9/10)
   Format: Blog + LinkedIn | Angle: Cost analysis for marketing leaders
   Timing: Publish within 48 hours (news cycle peak)

2. "Google Gemini Marketing Tools Launch" (8/10)
   Format: Webinar + Tweet thread | Angle: Competitive comparison
   Timing: Day 3 — let early takes publish first, then add depth

CONTENT CALENDAR
============================================================
Monday: "What OpenAI's New Pricing Means for Your Marketing Stack"
  Format: Blog (1,500 words) | CTA: ROI calculator
  Production: 4 hours

Tuesday: "Thread: 5 Things Marketers Missed About Gemini's Launch"
  Format: Tweet thread (8 tweets) | CTA: Newsletter signup
  Production: 1 hour

Error Handling

Some queries return clusters with zero articles in the response. Check articleCount before processing. Fall back to /all for raw articles.
Starter plans: 100 req/day. This job uses 1 Perigon call + 2 Mavera calls. Safe for daily runs on any plan.
Clusters with updatedAt older than 72 hours may have peaked. Use sortBy=createdAt to prioritize fresh narratives.