> ## 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.

# Earnings Calendar → Content Timing

### Scenario

Earnings announcements create predictable attention spikes — analysts, investors, and media focus on specific companies and sectors on known dates. This job pulls the upcoming earnings calendar, identifies companies relevant to your audience, then generates a content plan timed to each earnings window: pre-earnings thought pieces, real-time commentary angles, and post-earnings analysis frameworks.

**Flow:** Alpha Vantage `GET ?function=EARNINGS_CALENDAR` → Filter relevant companies → Mavera `POST /mave/chat` + `POST /generations` → Earnings-timed content plan

### Code

<CodeGroup>
  ```python Python theme={"dark"}
  import os, requests, time, csv, io

  AV_KEY = os.environ["ALPHA_VANTAGE_KEY"]
  AV_BASE = "https://www.alphavantage.co/query"
  MV = os.environ["MAVERA_API_KEY"]
  MV_BASE = "https://app.mavera.io/api/v1"
  MV_H = {"Authorization": f"Bearer {MV}", "Content-Type": "application/json"}

  AUDIENCE_SECTORS = ["Technology", "Communication Services", "Consumer Discretionary"]
  BRAND = "B2B marketing platform. Audience: Marketing leaders at enterprise companies. Tone: analytical, forward-looking."

  # 1. Fetch earnings calendar (returns CSV)
  r = requests.get(AV_BASE, params={
      "function": "EARNINGS_CALENDAR", "horizon": "3month", "apikey": AV_KEY,
  })
  r.raise_for_status()
  reader = csv.DictReader(io.StringIO(r.text))
  all_earnings = [row for row in reader]
  print(f"Total earnings events: {len(all_earnings)}")

  # 2. Filter to relevant companies
  relevant = [e for e in all_earnings
      if any(s.lower() in (e.get("name","") + e.get("symbol","")).lower() for s in ["AAPL","MSFT","GOOGL","META","AMZN","SHOP","HBS","CRM","ADBE","TWLO"])
      or float(e.get("estimate","0") or "0") > 1.0]
  relevant.sort(key=lambda x: x.get("reportDate",""))
  print(f"Relevant earnings: {len(relevant)}")

  # 3. Build earnings timeline
  timeline = "\n".join(
      f"- {e.get('reportDate','')} | {e.get('symbol','')} ({e.get('name','')}) | "
      f"Est EPS: ${e.get('estimate','N/A')} | Fiscal: {e.get('fiscalDateEnding','')}"
      for e in relevant[:20]
  )

  # 4. Mave content planning
  plan = requests.post(f"{MV_BASE}/mave/chat", headers=MV_H, json={
      "message": f"Content strategist specializing in earnings-cycle timing.\n\n"
          f"BRAND: {BRAND}\n\n"
          f"UPCOMING EARNINGS:\n{timeline}\n\n"
          "For the top 8 most impactful earnings events, create a content timing plan:\n\n"
          "PRE-EARNINGS (3-5 days before):\n- Thought piece angle that positions us as analysts\n"
          "EARNINGS DAY:\n- Real-time commentary template (LinkedIn post format)\n"
          "POST-EARNINGS (1-2 days after):\n- Analysis framework content piece\n\n"
          "Include: publish date, format, headline, key hook, why our audience cares."
  }).json()
  print(f"\n{plan.get('content', '')[:2000]}")

  # 5. Generate first content piece
  if relevant:
      first = relevant[0]
      gen = requests.post(f"{MV_BASE}/generations", headers=MV_H, json={
          "prompt": f"Write a pre-earnings thought piece (600 words) for marketing leaders.\n\n"
              f"COMPANY: {first.get('name','')} ({first.get('symbol','')})\n"
              f"REPORT DATE: {first.get('reportDate','')}\n"
              f"EPS ESTIMATE: ${first.get('estimate','N/A')}\n"
              f"BRAND: {BRAND}\n\n"
              "Angle: What this company's earnings signal about marketing technology spend.\n"
              "Include: What to watch, implications for marketing budgets, our unique take.\n"
              "Tone: analytical, not financial advice. End with a question for engagement.",
      }).json()
      print(f"\n{'='*60}\nPRE-EARNINGS PIECE: {first.get('symbol','')}\n{'='*60}")
      print(gen.get("output", gen.get("content", ""))[:1000])
  ```

  ```javascript JavaScript theme={"dark"}
  const AV_KEY = process.env.ALPHA_VANTAGE_KEY;
  const AV_BASE = "https://www.alphavantage.co/query";
  const MV = process.env.MAVERA_API_KEY;
  const MV_BASE = "https://app.mavera.io/api/v1";
  const MV_H = { Authorization: `Bearer ${MV}`, "Content-Type": "application/json" };

  const BRAND = "B2B marketing platform. Audience: Marketing leaders. Tone: analytical, forward-looking.";

  // 1. Earnings calendar (CSV)
  const csvText = await (await fetch(
    `${AV_BASE}?function=EARNINGS_CALENDAR&horizon=3month&apikey=${AV_KEY}`)).text();
  const lines = csvText.trim().split("\n");
  const headers = lines[0].split(",");
  const allEarnings = lines.slice(1).map(line => {
    const vals = line.split(",");
    return Object.fromEntries(headers.map((h, i) => [h, vals[i] || ""]));
  });
  console.log(`Total earnings events: ${allEarnings.length}`);

  // 2. Filter relevant
  const watchlist = ["AAPL","MSFT","GOOGL","META","AMZN","SHOP","CRM","ADBE","TWLO"];
  const relevant = allEarnings
    .filter(e => watchlist.some(s => (e.symbol||"").includes(s)) || parseFloat(e.estimate||"0") > 1.0)
    .sort((a, b) => (a.reportDate||"").localeCompare(b.reportDate||""));
  console.log(`Relevant earnings: ${relevant.length}`);

  // 3. Timeline
  const timeline = relevant.slice(0, 20).map(e =>
    `- ${e.reportDate} | ${e.symbol} (${e.name}) | Est: $${e.estimate || "N/A"}`).join("\n");

  // 4. Content plan
  const plan = await fetch(`${MV_BASE}/mave/chat`, { method: "POST", headers: MV_H,
    body: JSON.stringify({ message: `Earnings-cycle content strategist.\n\nBRAND: ${BRAND}\n\nEARNINGS:\n${timeline}\n\nTop 8 events: PRE (thought piece), DAY (LinkedIn template), POST (analysis). Include date, format, headline, hook.` }),
  }).then(r => r.json());
  console.log((plan.content || "").slice(0, 2000));

  // 5. Generate first piece
  if (relevant.length) {
    const first = relevant[0];
    const gen = await fetch(`${MV_BASE}/generations`, { method: "POST", headers: MV_H,
      body: JSON.stringify({ prompt: `Pre-earnings thought piece (600 words) for marketing leaders.\n\nCOMPANY: ${first.name} (${first.symbol})\nDATE: ${first.reportDate}\nEST: $${first.estimate||"N/A"}\n\nAngle: What earnings signal about martech spend.\nTone: analytical, not financial advice.` }),
    }).then(r => r.json());
    console.log(`\n${"=".repeat(60)}\nPRE-EARNINGS: ${first.symbol}`);
    console.log((gen.output || gen.content || "").slice(0, 1000));
  }
  ```
</CodeGroup>

### Example Output

```text theme={"dark"}
Total earnings events: 2,847
Relevant earnings: 23

1. AAPL (2026-04-24) — PRE-EARNINGS PIECE:
   "What Apple's Q2 Tells Us About the Future of Marketing Spend"
   Format: Blog (1,500 words) | Publish: Apr 21
   Hook: Services revenue growth rate = proxy for digital ad spend health

2. META (2026-04-30) — EARNINGS DAY:
   "Meta Earnings Live: 3 Numbers Marketing Leaders Should Watch"
   Format: LinkedIn post | Publish: Apr 30 4pm ET
   Hook: ARPU trend, Reels monetization, AI ad targeting changes

PRE-EARNINGS PIECE: AAPL
============================================================
# What Apple's Q2 Earnings Tell Us About Marketing Technology Spend

Every quarter, Apple's earnings call contains a signal most marketers
miss: the Services revenue growth rate. At $23.1B last quarter (+11%
YoY), Services — which includes App Store, iCloud, Apple TV+, and
Search Ads — is now Apple's second-largest segment...
```

### Error Handling

<AccordionGroup>
  <Accordion title="CSV parsing">Earnings calendar returns CSV, not JSON. The code parses it with `csv.DictReader` (Python) or manual split (JS). Handle empty rows and missing fields.</Accordion>
  <Accordion title="Rate-limit notes">Alpha Vantage returns HTTP 200 with a `"Note"` field when rate-limited. Check for `"Note" in response` before parsing data.</Accordion>
  <Accordion title="Date accuracy">Earnings dates can shift. Re-fetch weekly. Some dates show as estimated — filter on `reportDate` presence.</Accordion>
</AccordionGroup>
