This is the no-code version of the Slack bot tutorial. If your team lives in Notion and not Slack, or if you're a PM/analyst who'd rather not maintain a Node.js codebase, this is the same outcome with zero JavaScript: a Notion database that auto-fills with structured earnings summaries the moment your watchlist companies report.

The workflow is built in n8n (self-hosted or cloud), takes ~25 minutes to set up, and runs forever on a schedule trigger.

Total monthly cost: ~$30 if self-hosting n8n on a $5 VPS, $25 for the API tier, plus pennies for Claude calls. n8n cloud is $20/month if you want zero maintenance.

What You'll Build

[Schedule Trigger: every 30 min, 8 AM - 8 PM ET, Mon-Fri]
       ↓
[Loop over watchlist tickers (Code node)]
       ↓
[HTTP: GET /transcripts/recent?ticker=X&limit=1]
       ↓
[Filter: is this earnings_id new? (compare against Notion DB)]
       ↓ (only when NEW)
[HTTP: GET /transcripts/:earnings_id]
       ↓
[Anthropic: summarize transcript into 4 bullets + 3 metrics]
       ↓
[Notion: create page in "Earnings Watch" database]
       ↓
[Slack (optional): notify channel]

Every node is a drag-and-drop block in n8n's editor. No code beyond two small JS snippets in Code nodes (provided below).

Prerequisites

  1. n8n instance — self-hosted via Docker or n8n cloud (free tier handles low volume)
  2. earningscalls.dev API key — Pro tier or higher
  3. Anthropic API key for Claude summarization
  4. Notion integration token + a database with the right columns (see below)

Step 1: Notion Database Schema

Create a new Notion database called "Earnings Watch" with these properties:

Property Type Why
Ticker Title Primary identifier
Company Text Human-readable name
Call Date Date When the call happened
Earnings ID Text Used as dedupe key
Summary Text 4 AI bullets
Metrics Text 3 key extracted figures
Transcript Link URL Deep link to full transcript
Sector Select For filtering views

Share the database with your n8n Notion integration (Notion → Connections → add your integration → grant access).

Step 2: n8n Workflow — Schedule Trigger

Add a Schedule Trigger node:

Step 3: Iterate Your Watchlist

Add a Code (JavaScript) node right after the trigger:

// Watchlist as array
const tickers = [
  "NVDA", "MSFT", "AAPL", "META", "GOOG", "AMZN",
  "TSLA", "CRM", "NFLX", "ORCL", "AMD", "AVGO"
];

return tickers.map(ticker => ({ json: { ticker } }));

This emits one execution per ticker downstream. n8n's "execute once per item" mode handles the fan-out automatically.

Step 4: Fetch Latest Call

Add an HTTP Request node:

Response will be { results: [{...call object...}] }.

Step 5: Check If New

Add a Notion node to query your database for this earnings_id:

Then an IF node:

Only the "TRUE" branch continues — that means we haven't seen this call before.

Step 6: Fetch Full Transcript

Another HTTP Request node on the TRUE branch:

Step 7: Summarize With Claude

Add an HTTP Request node (we use direct API rather than the n8n Anthropic node for finer control over the prompt):

{
  "model": "claude-haiku-4-5",
  "max_tokens": 600,
  "messages": [{
    "role": "user",
    "content": "You are an equity analyst. Read this earnings call transcript and produce a summary in this exact format:\n\nBULLETS:\n- [bullet 1: headline result vs consensus]\n- [bullet 2: guidance change]\n- [bullet 3: most important strategic update]\n- [bullet 4: most concerning risk in Q&A]\n\nMETRICS:\n- [metric 1: figure with value]\n- [metric 2: figure with value]\n- [metric 3: figure with value]\n\nBe terse. Use the ticker, not 'the company'.\n\nTRANSCRIPT:\n{{ $node['HTTP Request3'].json.transcript }}"
  }]
}

(HTTP Request3 is the name of your transcript-fetch node — rename to taste.)

Step 8: Parse Summary

The Claude response has the format we asked for, but it's all in one content.text string. A small Code node parses it:

const raw = $input.first().json.content.text;

// Split on the "METRICS:" header
const [bulletsBlock, metricsBlock] = raw.split(/METRICS:/i);

const bullets = bulletsBlock
  .replace(/BULLETS:/i, "")
  .trim();

const metrics = (metricsBlock || "")
  .trim();

return [{ json: { bullets, metrics } }];

Step 9: Create Notion Page

Final node — Notion:

The Full Workflow JSON

Export-ready n8n workflow that you can paste into your instance — gives you the full chain wired up. (Trim sensitive data before sharing externally.)

{
  "name": "Earnings Watch → Notion",
  "nodes": [
    { "id": "trigger", "type": "n8n-nodes-base.scheduleTrigger",
      "parameters": { "rule": { "interval": [{ "field": "minutes", "minutesInterval": 30 }]}}},
    { "id": "tickers", "type": "n8n-nodes-base.code",
      "parameters": { "jsCode": "const tickers=['NVDA','MSFT','AAPL','META','GOOG','AMZN','TSLA','CRM'];return tickers.map(t=>({json:{ticker:t}}));"}},
    { "id": "fetchLatest", "type": "n8n-nodes-base.httpRequest",
      "parameters": {
        "url": "https://earningscalls.dev/api/v1/transcripts/recent",
        "qs": { "ticker": "={{ $json.ticker }}", "limit": 1 },
        "headers": { "X-API-Key": "={{ $env.EARNINGSCALLS_API_KEY }}" }}}
    // ... continued with notionQuery, ifNew, fetchTranscript, claudeCall,
    //     parseSummary, createNotion — full file ~120 lines
  ]
}

(Full JSON gets long; load the workflow template from earningscalls.dev's example repo, link at the end.)

The Cost Receipts

For a 12-ticker watchlist during a typical earnings week:

Step Per execution Per week
/transcripts/recent poll 12 requests × 60 ticks/week 720
/transcripts/:id (only when new) ~12 calls report per week × 1 12
earningscalls API total 732/week ≈ 2,928/month
Claude Haiku summary ~12/week × $0.0015 each ~$0.07/month
Notion API Free up to 3 req/sec
n8n (cloud Starter) $20/month flat
Grand total ~$45/month

That's 58.6% of the Pro plan's monthly budget on the API side. To trim:

If you reduce polling to once per hour AND use the calendar short-circuit, your earningscalls usage drops to about 250-400 requests/month — under 8% of Pro plan budget.

Why n8n Beats Custom Code Here

I'm partial to writing a Node bot when the workflow has complex branching logic. But for this shape — schedule, fetch, filter, transform, store — n8n wins on three axes:

  1. Visual debugging. You can re-run any node in isolation with the actual data from the last execution. When something breaks, you see exactly which step failed and with what input. Cuts debugging time by 80%.
  2. Non-engineers can edit it. Your analyst can swap "Notion" for "Airtable" by replacing one node, no PR required.
  3. Built-in retry + error handling. Each node has configurable retry, exponential backoff, and error-branch routing. Reproducing this in code takes ~50 lines of try/catch boilerplate.

The tradeoff: when your workflow has loops with state, or recursive logic, n8n gets awkward. For anything in the "watch X, transform Y, write to Z" shape — n8n is unbeatable.

Variations

The same backbone supports many downstream destinations. Swap Step 9's Notion node for:

The earningscalls → Claude → format pipeline stays identical. The destination is a 1-node swap.

Get an API key and have the workflow running before this week's reports drop.