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

Pull subscriptions with status=past_due or status=canceled along with payment failure history. Extract traits — plan type, tenure, failed attempts — and feed into Mavera for personalized retention messaging.

Architecture

Code

import os, time, stripe, requests

stripe.api_key = os.environ["STRIPE_API_KEY"]
MAVERA_API_KEY = os.environ["MAVERA_API_KEY"]
MAVERA_BASE = "https://app.mavera.io/api/v1"

def get_at_risk_subscriptions():
    at_risk = []
    for status in ["past_due", "canceled"]:
        subs = stripe.Subscription.list(limit=50, status=status, expand=["data.customer"])
        for sub in subs.auto_paging_iter():
            invoices = stripe.Invoice.list(subscription=sub.id, limit=10)
            at_risk.append({
                "customer_email": sub.customer.email,
                "plan": sub["items"].data[0].price.nickname or sub["items"].data[0].price.id,
                "status": status,
                "tenure_days": (int(time.time()) - sub.start_date) // 86400,
                "payment_failures": sum(1 for inv in invoices.data if inv.status == "uncollectible"),
            })
    return at_risk

def generate_retention_content(profiles):
    summary = "\n".join(
        f"- {p['customer_email']}: {p['plan']}, {p['tenure_days']}d, {p['payment_failures']} failures"
        for p in profiles[:20])
    resp = requests.post(f"{MAVERA_BASE}/generations", json={
        "prompt": f"Generate retention emails for at-risk customers:\n{summary}\n\nProduce subject line + 2-sentence body per profile.",
        "max_tokens": 2000,
    }, headers={"Authorization": f"Bearer {MAVERA_API_KEY}"})
    resp.raise_for_status()
    return resp.json()

profiles = get_at_risk_subscriptions()
print(f"Found {len(profiles)} at-risk subscriptions")
print(generate_retention_content(profiles)["text"])

Example Output

Subject: "We miss you, Sarah — here's 30% off your next quarter"
Body: You've been with us for 14 months and we noticed your recent payment
didn't go through. Reply for a dedicated account review and 30% off.

Subject: "Your Pro plan is paused — let's fix that"
Body: After 8 months on Pro, we know switching tools is a pain. One-click
reactivation below with your settings intact, plus a free month.

Error Handling

Stripe limits expansion depth. For nested data like customer.default_payment_method, make a separate stripe.Customer.retrieve() call.
Prompts capped at 8,000 tokens. Batch profiles into groups of 20 or summarize into aggregate statistics.