← All guides

News-Driven Start/Sit Alerts

Scan your roster every morning for breaking injury, role, and transaction news — the stuff that flips a start/sit call after projections are already set. If a player has no coverage yet, ask the API to go fetch it, then check back.

What you'll build: a script that pulls recent news for every player on your roster, flags the injury- and role-tagged headlines that matter for lineups, and auto-requests a fresh scrape for anyone the dataset hasn't covered yet.

Endpoints used

Each news item carries an impact tag — injury, transaction, role, or general — so you can surface only what changes a lineup decision. A player ID is "{Player Name}#{POS}", e.g. Malik Nabers#WR.

1. Get recent news for one player

curl -H "x-api-key: YOUR_KEY" \
  "https://api.gridirondata.com/api/v1/news/Malik%20Nabers%23WR?days=7"
{
  "player_id": "Malik Nabers#WR",
  "days": 7,
  "count": 1,
  "news": [
    {
      "headline": "Nabers (knee) full participant at Wednesday practice",
      "impact": "injury",
      "source": "espn-nfl",
      "url": "https://www.espn.com/nfl/story/_/id/00000000",
      "published_at": "2026-09-10T17:22:00Z"
    }
  ]
}

2. When there's no news, ask for a scrape

Track a deep-bench player or a just-promoted backup the dataset hasn't picked up yet? A count: 0 response hands you a ready-made link to request one. POST to it and the API scrapes that player on demand — and adds them to the automated scraper so they're covered from then on.

{
  "player_id": "Max Bredeson#RB",
  "count": 0,
  "news": [],
  "message": "No news found for Max Bredeson#RB in the last 14 days.",
  "request_scrape": {
    "method": "POST",
    "href": "https://api.gridirondata.com/api/v1/news/Max%20Bredeson%23RB/request"
  }
}
curl -X POST -H "x-api-key: YOUR_KEY" \
  "https://api.gridirondata.com/api/v1/news/Max%20Bredeson%23RB/request"
# 202 Accepted — poll GET /news/{player_id} again shortly after

3. The full roster monitor

import requests

API = "https://api.gridirondata.com/api/v1"
H = {"x-api-key": "YOUR_KEY"}

ROSTER = [
    "Josh Allen#QB", "Bijan Robinson#RB", "Malik Nabers#WR",
    "CeeDee Lamb#WR", "Trey McBride#TE", "Max Bredeson#RB",
]
# Impact tags that can actually change a start/sit call.
LINEUP_MOVING = {"injury", "role", "transaction"}

def player_news(pid, days=7):
    r = requests.get(f"{API}/news/{requests.utils.quote(pid, safe='')}",
                     headers=H, params={"days": days})
    return r.json()

alerts = []
for pid in ROSTER:
    data = player_news(pid)

    # No coverage yet? Fire off an on-demand scrape and move on.
    if data.get("count", 0) == 0:
        link = data.get("request_scrape")
        if link:
            requests.request(link["method"], link["href"], headers=H)
            print(f"· requested scrape for {pid}")
        continue

    # Keep only the headlines that matter for a lineup.
    for item in data["news"]:
        if item["impact"] in LINEUP_MOVING:
            alerts.append((pid, item))

print("\n=== LINEUP-MOVING NEWS ===")
for pid, item in sorted(alerts, key=lambda a: a[1]["published_at"], reverse=True):
    name = pid.rsplit("#", 1)[0]
    print(f"[{item['impact'].upper():11}] {name:22} {item['headline']}")
    print(f"              {item['url']}")
🔁 Build the dataset as you go: every player you request through POST /news/{player_id}/request is added to the automated scraper, so your first lookup seeds coverage and every run after that stays fresh — no extra work on your end.

Wire it to Slack or cron

Run it each morning with cron and post alerts to a Slack incoming webhook, or trigger it Sunday pre-kickoff. Because on-demand requests are asynchronous, a good pattern is: request scrapes on the first pass, then re-poll the request_scrape players a minute later to catch anything fresh.

Next steps