DEV Community

Michalis Solomou
Michalis Solomou

Posted on

Get a Slack Alert the Moment a Startup Files for Funding (Python)

Your sales team doesn't live in their inbox — they live in Slack. If a competitor's Series B lands in a shared channel five minutes after it's filed, someone on your team can be drafting an outreach email before the news even hits TechCrunch.

I already covered pulling SEC Form D filings with Python and emailing yourself a daily digest. This time we're skipping email entirely and pushing new funding events straight into a Slack channel the moment they're scored, using an Incoming Webhook.

Step 1: Create a Slack Incoming Webhook

In Slack, go to Apps → Incoming Webhooks → Add to Slack, pick the channel (e.g. #funding-alerts), and copy the webhook URL. It looks like:

https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX
Enter fullscreen mode Exit fullscreen mode

Keep it secret — anyone with that URL can post to your channel.

Step 2: Pull today's filings

Rather than parsing raw SEC EDGAR XML ourselves, I'm using the Funding Signals API, which already normalizes Form D filings into clean JSON (company, amount, industry, state, filing date) and scores each one for B2B sales relevance:

import requests
import os

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

resp = requests.get(
    "https://fundingsignals.net/api/v1/filings",
    params={"days": 1, "min_score": 70},
    headers={"Authorization": f"Bearer {FS_API_KEY}"},
)
filings = resp.json()["results"]
Enter fullscreen mode Exit fullscreen mode

min_score=70 filters out the noise (tiny angel rounds, real-estate LLCs) and keeps only filings that look like genuine B2B prospects.

Step 3: Format and post to Slack

Slack's Block Kit makes the message actually readable instead of a wall of text:

def post_to_slack(filing):
    blocks = [
        {
            "type": "section",
            "text": {
                "type": "mrkdwn",
                "text": (
                    f"*<https://fundingsignals.net/companies/{filing['id']}"
                    f"?utm_source=devto&utm_medium=tutorial5|{filing['company_name']}>*\n"
                    f"💰 ${filing['amount']:,.0f} · {filing['industry']} · {filing['state']}"
                ),
            },
        },
        {
            "type": "context",
            "elements": [
                {"type": "mrkdwn", "text": f"Filed {filing['filing_date']} · relevance score {filing['score']}/100"}
            ],
        },
    ]
    requests.post(SLACK_WEBHOOK_URL, json={"blocks": blocks})


for filing in filings:
    post_to_slack(filing)
Enter fullscreen mode Exit fullscreen mode

Each message links straight back to the full company profile on Funding Signals, so whoever sees the alert can click through for firmographics, contact leads, and the original SEC filing — no separate lookup step.

Step 4: Run it on a schedule

Same GitHub Actions cron pattern from the email digest tutorial works here — just point it at slack_alert.py instead:

name: Slack Funding Alerts
on:
  schedule:
    - cron: "0 14 * * 1-5"  # 9am ET, weekdays
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 slack_alert.py
        env:
          FS_API_KEY: ${{ secrets.FS_API_KEY }}
          SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
Enter fullscreen mode Exit fullscreen mode

Why Slack over email

Email digests are great for a once-a-day summary. But funding data is time-sensitive — the earlier you reach out after a round closes, the less crowded your inbox is next to every other vendor who saw the same TechCrunch article. A Slack channel your whole sales team already has open beats a digest sitting unread until lunch.

If you want to try this against real, freshly-filed data instead of stubbing it out, Funding Signals has a free tier that's enough to wire this up end to end.

Top comments (0)