DEV Community

Michalis Solomou
Michalis Solomou

Posted on

Build a Slack Bot That Pings You the Moment a Prospect Raises Funding

The first thing most SDRs do with a funding alert is... nothing, because it
lands in an email digest three weeks after the fact and 40 other companies
in that digest already got pitched by five other vendors.

This is a ~40 line Python script that checks for new funding signals every
morning and posts the ones that match your ICP straight into a Slack
channel — so the "just raised money" alert actually arrives while it's
still useful.

What you need

  • A free Funding Signals API key (self-serve, no card).
  • A Slack Incoming Webhook URL for the channel you want alerts in (Slack → your workspace → Apps → search "Incoming Webhooks" → Add to Slack → pick a channel → copy the webhook URL).
  • requests installed (pip install requests).

The script

import requests
import os

FS_API_KEY = os.environ["FUNDING_SIGNALS_KEY"]
SLACK_WEBHOOK = os.environ["SLACK_WEBHOOK_URL"]

# tune this to your ICP
PARAMS = {
    "min_score": 80,
    "min_raise": 3_000_000,
    "industry": "technology",
    "has_contact": "true",
    "limit": 10,
}

def fetch_signals():
    resp = requests.get(
        "https://funding-signals-api.onrender.com/v1/signals",
        headers={"X-API-Key": FS_API_KEY},
        params=PARAMS,
    )
    resp.raise_for_status()
    return resp.json()

def post_to_slack(signal):
    text = (
        f"*{signal['company_name']}* just raised "
        f"${signal['amount_usd']:,} ({signal['industry']}) — score "
        f"{signal['score']}/100\n"
        f"<https://funding-signals-api.onrender.com/v1/signals/{signal['id']}/lead"
        f"?utm_source=slackbot|View enriched lead>"
    )
    requests.post(SLACK_WEBHOOK, json={"text": text})

def main():
    for signal in fetch_signals():
        post_to_slack(signal)

if __name__ == "__main__":
    main()
Enter fullscreen mode Exit fullscreen mode

Set the two environment variables and run it once to sanity-check the
output, then point it at a scheduler.

Making it run daily

Simplest option: a GitHub Actions workflow in the same repo as the script
(no server to babysit).

# .github/workflows/funding-alerts.yml
name: funding-alerts
on:
  schedule:
    - cron: "0 13 * * 1-5"  # 9am ET, weekdays
  workflow_dispatch: {}

jobs:
  alert:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4      - uses: actions/setup-python@v5        with:
          python-version: "3.12"
      - run: pip install requests
      - run: python alert.py
        env:
          FUNDING_SIGNALS_KEY: ${{ secrets.FUNDING_SIGNALS_KEY }}
          SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
Enter fullscreen mode Exit fullscreen mode

Add the two secrets in the repo's Settings → Secrets → Actions, and that's
the whole pipeline: SEC filing → scored signal → Slack message, with no
server and no cron box to maintain.

Avoiding duplicate alerts

The API doesn't track what you've already seen, so on a fresh run every
signal in the current window will post again. Cheapest fix: keep a small
JSON file of seen IDs, commit it back after each run.

import json
from pathlib import Path

SEEN_FILE = Path("seen_ids.json")

def load_seen():
    if SEEN_FILE.exists():
        return set(json.loads(SEEN_FILE.read_text()))
    return set()

def save_seen(ids):
    SEEN_FILE.write_text(json.dumps(sorted(ids)))

def main():
    seen = load_seen()
    signals = fetch_signals()
    new = [s for s in signals if s["id"] not in seen]
    for signal in new:
        post_to_slack(signal)
    save_seen(seen | {s["id"] for s in new})
Enter fullscreen mode Exit fullscreen mode

If you're running this in GitHub Actions, add a commit-and-push step at the
end of the job so seen_ids.json persists between runs.

Where to take it from here

Same pattern works for a Discord webhook, a CRM sync (dump straight into
HubSpot/Airtable instead of Slack), or per-rep channels filtered by
industry. The API call is the same either way — only post_to_slack
changes.

Docs: funding-signals-api.onrender.com/docs

Prefer no code at all? Grab the free lead tracker template instead.

Top comments (0)