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

Blog content decays — statistics go stale, links break, and SEO rankings drop. You pull every published post with its date and categories, flag anything older than 12 months as stale, send the list to Mavera for a prioritized refresh plan, then generate updated outlines for the top-priority posts.

Architecture

Code

import os, requests
from datetime import datetime, timedelta, timezone

WP, MV = os.environ["WORDPRESS_URL"], os.environ["MAVERA_API_KEY"]
MB = "https://app.mavera.io/api/v1"
MH = {"Authorization": f"Bearer {MV}", "Content-Type": "application/json"}
cutoff = (datetime.now(timezone.utc) - timedelta(days=365)).isoformat()

posts, page = [], 1
while True:
    resp = requests.get(f"{WP}/wp-json/wp/v2/posts", params={
        "status": "publish", "per_page": 100, "page": page,
        "_fields": "id,title,date,modified,categories,slug,link"})
    if resp.status_code == 400: break
    resp.raise_for_status()
    batch = resp.json()
    if not batch: break
    posts.extend(batch)
    if page >= int(resp.headers.get("X-WP-TotalPages", 1)): break
    page += 1
print(f"Total posts: {len(posts)}")

stale = sorted([p for p in posts if p["modified"] < cutoff], key=lambda p: p["modified"])
print(f"Stale posts (12+ months): {len(stale)}")

listing = "\n".join(f"- [{p['title']['rendered']}]({p['link']}) — modified: {p['modified'][:10]}" for p in stale[:40])
plan_resp = requests.post(f"{MB}/mave/chat", json={"input": [
    {"role": "system", "content": "Content strategist. Prioritize stale posts for refresh by SEO value, evergreen potential, update effort. Numbered list: priority, title, reason, action."},
    {"role": "user", "content": f"Posts not updated in 12+ months:\n\n{listing}\n\nPrioritize top 10."},
]}, headers=MH)
plan_resp.raise_for_status()
print(f"\n--- Refresh Plan ---\n{plan_resp.json()['choices'][0]['message']['content']}")

for p in stale[:3]:
    gen = requests.post(f"{MB}/generations", json={
        "prompt": f"Updated outline for:\nTitle: {p['title']['rendered']}\nURL: {p['link']}\nLast updated: {p['modified'][:10]}\n\nProvide: updated title, 5-7 headings, key points, stats to research."
    }, headers=MH)
    gen.raise_for_status()
    print(f"\n--- Outline: {p['title']['rendered']} ---\n{gen.json()['text']}")

Example Output

Total posts: 247 | Stale (12+ months): 83

--- Refresh Plan ---
1. HIGH — "Remote Work Statistics 2024" — modified 2024-11-15
   Action: Update all stats to 2026 sources, add hybrid work section.
2. HIGH — "Complete Guide to Email Marketing" — modified 2024-08-22
   Action: Add AI-assisted email section, update platform comparisons.
3. MEDIUM — "Best Project Management Tools" — modified 2024-06-10
   Action: Re-evaluate tool list, update screenshots and pricing.

Error Handling

WordPress returns HTTP 400 when you request a page beyond X-WP-TotalPages. The code breaks on status 400. Alternatively, read X-WP-TotalPages from the first response and stop before exceeding it.
If your site has hundreds of stale posts, the listing may exceed the context window. The code caps at 40 posts. For larger audits, split by category or date range and merge the top results.