API Keys
Richfolio uses up to 5 external services, all with generous free tiers. Only Resend and a recipient email are required — everything else is optional.
Add each key as a repository Secret: Settings → Secrets and variables → Actions → Secrets tab. Add RECIPIENT_EMAIL as a Variable instead (easier to view/edit).

Resend (Email) — Required
Resend delivers the HTML email reports.
- Go to resend.com and sign up
- Navigate to API Keys in the dashboard
- Click Create API Key, give it a name, and copy the key
- Add as a GitHub Secret — name:
RESEND_API_KEY, value: the key you just copied
Free tier: 3,000 emails/month. Sends from onboarding@resend.dev by default. Can only send to your account owner email unless you verify a custom domain (Dashboard → Domains → Add Domain → add DNS records).
Recipient Email — Required
Add as a GitHub Variable (not Secret): name: RECIPIENT_EMAIL, value: your email address.
Must match your Resend account email unless you’ve verified a custom domain.
NewsAPI (Headlines) — Optional
Provides top headlines per ticker for the daily brief.
- Go to newsapi.org and sign up
- Your API key is shown on the dashboard immediately
- Add as a GitHub Secret — name:
NEWS_API_KEY, value: the key from the dashboard
Free tier: 100 requests/day. Richfolio uses ~4 requests per run via batching. Headlines from the last 24 hours only. If not set, the brief runs without news.
AI Providers — at least one required for AI recommendations
Richfolio supports two AI providers: Google Gemini and Anthropic Claude. Set at least one for AI-powered recommendations. Set both to run them in parallel — scores are then averaged and a per-AI breakdown is shown next to every recommendation. If neither is set, Richfolio falls back to gap-based recommendations (no AI).
| Mode | Setup | Output |
|---|---|---|
| No AI | Neither key set | Gap-based recommendations only |
| Single AI | One key set | Identical to today — one set of action + confidence per ticker |
| Multi-AI | Both keys set | Per-ticker consensus action + averaged confidence; per-AI breakdown shown beneath each rec; STRONG BUY requires unanimous agreement |
Google Gemini — Optional
Powers the AI buy recommendations with Gemini 2.5 Flash.
- Go to aistudio.google.com/apikey
- Click Create API Key, select a Google Cloud project (or create one)
- Copy the key and add as a GitHub Secret — name:
GEMINI_API_KEY, value: the key you just copied
Free tier: 250 requests/day, 10 requests/minute. Richfolio uses 2 requests per run (Stage 1 Observe + Stage 2 Decide) plus 1 per STRONG BUY ticker for detailed analysis. New keys may take a few minutes for quota to activate (you might see 429 errors initially).
A note on Gemini model tiers
Google’s pricing page states that Gemini 2.5 Pro is “Free of charge” for both input and output tokens. In practice, however, free-tier Pro requests frequently hit 429 RESOURCE_EXHAUSTED errors — even with minimal usage. Google does not publish the actual RPD (requests per day) limits for the free tier; third-party sources suggest Pro may be capped at ~100 RPD, but the real number appears to vary by account and is not guaranteed.
Richfolio uses Gemini 2.5 Flash by default because Flash has a more generous and reliable free-tier quota. The quality difference for financial analysis text is negligible.
Anthropic Claude — Optional
Powers the AI buy recommendations with Claude (Sonnet 4.6 by default).
- Go to console.anthropic.com and sign up
- Navigate to API Keys → Create Key, give it a name, copy the key
- Add as a GitHub Secret — name:
ANTHROPIC_API_KEY, value: the key you just copied
Pricing: Anthropic does not have a permanent free tier like Gemini, but new accounts receive a small starter credit and Sonnet usage for Richfolio’s workload is typically cents per day. To minimise cost, set CLAUDE_MODEL=claude-haiku-4-5-20251001 (the Haiku tier is significantly cheaper while still handling this workload well).
Combining with Gemini (multi-AI mode)
If both GEMINI_API_KEY and ANTHROPIC_API_KEY are set, Richfolio runs both providers concurrently on every analysis and aggregates the results:
- Consensus action per ticker via majority vote (with confidence-sum tiebreaker)
- Averaged confidence displayed prominently; per-AI scores shown beneath
- STRONG BUY requires unanimous agreement — if any provider dissents, the consensus caps at BUY
- Agreement label (unanimous / majority / split) shown as a badge next to the action
If a provider fails mid-run (rate-limited, quota exhausted, network error), the surviving provider continues alone and the email/Telegram for that run falls back to single-AI display.
Choosing which provider generates the detailed STRONG BUY analysis page
When both providers are active, the per-STRONG-BUY analysis page (the “More Details” link) is generated by a single provider — by default the first available one in registry order (Gemini, then Claude). Override with:
| Env var | Value | Effect |
|---|---|---|
AI_DETAILED_PROVIDER | gemini | Force Gemini for detailed analysis (must have GEMINI_API_KEY set) |
AI_DETAILED_PROVIDER | claude | Force Claude for detailed analysis (must have ANTHROPIC_API_KEY set) |
CLAUDE_MODEL | e.g. claude-haiku-4-5-20251001 | Override Claude model (default: claude-sonnet-4-6) |
Telegram Bot — Optional
Delivers condensed summaries to your Telegram account.
Create the bot
- Open Telegram and search for @BotFather
- Send
/newbot - Choose a name (e.g., “Richfolio Brief”) and username (must end in
bot, e.g.,richfolio_brief_bot) - BotFather replies with your bot token — copy it
Get your chat ID
- Search for @userinfobot on Telegram and start it
- It replies with your numeric user ID — this is your chat ID
Important: Send any message to your new bot (e.g., “hi”) before running Richfolio — this is required before the bot can message you.
Add both as GitHub Secrets:
- Name:
TELEGRAM_BOT_TOKEN, value: the token from BotFather - Name:
TELEGRAM_CHAT_ID, value: your numeric user ID
Notes: If not set, the brief skips Telegram. Messages are condensed summaries (not full HTML). 4,096 character limit per message — news is truncated if needed.
Social Posting — Optional
Richfolio can publish generic buy signals to public accounts on X, Facebook, Threads, and LinkedIn. Every platform is optional and stays off until configured. Required secrets per platform:
- Facebook:
FACEBOOK_PAGE_ID,FACEBOOK_PAGE_TOKEN - Threads:
THREADS_USER_ID,THREADS_ACCESS_TOKEN(+ optionalTHREADS_TOKEN_PATto auto-refresh the ~60-day token) - LinkedIn:
LINKEDIN_ACCESS_TOKEN,LINKEDIN_ORG_URN - X/Twitter:
X_API_KEY,X_API_SECRET,X_ACCESS_TOKEN,X_ACCESS_TOKEN_SECRET
Notes: Posts are generic — no holdings or allocations are disclosed. If unset, social posting is skipped. See Social Posting for step-by-step setup of each platform.
Summary
| Key | Required | Service |
|---|---|---|
RESEND_API_KEY | Yes | Email delivery |
RECIPIENT_EMAIL | Yes | Your email address |
NEWS_API_KEY | No | News headlines |
GEMINI_API_KEY | No | AI provider (Google Gemini) |
ANTHROPIC_API_KEY | No | AI provider (Anthropic Claude) |
TELEGRAM_BOT_TOKEN | No | Telegram delivery |
TELEGRAM_CHAT_ID | No | Telegram delivery |
FACEBOOK_PAGE_ID / FACEBOOK_PAGE_TOKEN | No | Facebook Page posting |
THREADS_USER_ID / THREADS_ACCESS_TOKEN | No | Threads posting |
THREADS_TOKEN_PAT | No | Auto-refresh the Threads token (PAT with Secrets write) |
LINKEDIN_ACCESS_TOKEN / LINKEDIN_ORG_URN | No | LinkedIn Page posting |
X_API_KEY / X_API_SECRET / X_ACCESS_TOKEN / X_ACCESS_TOKEN_SECRET | No | X/Twitter posting |
CLAUDE_MODEL | No | Override Claude model (default: claude-sonnet-4-6) |
AI_DETAILED_PROVIDER | No | Force gemini or claude for the STRONG BUY analysis page |