Pinnacle odds drop alerts in Slack
Answer: create a Slack incoming webhook for your channel, then run a small script that polls GET /v1/drops every minute and posts each new move to the webhook URL. Dedupe on event, market, outcome and movedAt so one move posts once. Works on Free (30-second delay) and in real time on Hobby; for sub-second alerts use the Builder WebSocket.
Node 18+#
// PINNFEED_KEY=ps_live_... SLACK_WEBHOOK=https://hooks.slack.com/services/... node slack-drops.js
const seen = new Set();
async function tick() {
const r = await fetch('https://pinnfeed.io/v1/drops?sport=soccer&minutes=5&min_pct=6', {
headers: { 'x-api-key': process.env.PINNFEED_KEY },
});
if (!r.ok) return console.error('pinnfeed', r.status, await r.text());
const { drops = [] } = await r.json();
for (const d of drops) {
const id = `${d.eventId}:${d.marketId}:${d.outcome}:${d.movedAt}`;
if (seen.has(id)) continue;
seen.add(id);
const text = `${d.home} v ${d.away} · ${d.market} ${d.outcome}: ${d.from} → ${d.to} (-${d.dropPct}%)`;
await fetch(process.env.SLACK_WEBHOOK, {
method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ text }),
});
}
}
tick();
setInterval(tick, 60_000);
seen grows forever in this sketch; clear it daily or keep only the last few thousand ids in a real bot.
Limits to respect#
- Free: 1 request/second and 1,000/day, so a 1-minute loop (1,440 calls/day) needs a 2-minute interval on Free. Details: rate limits.
- Slack incoming webhooks are rate-limited by Slack too; batch several moves into one message if a lot move at once.
Faster: WebSocket worker#
On Builder (€99/mo), keep a socket open and detect drops yourself (steam in Python), then post to the same webhook. Same idea for other channels: Telegram, Discord, n8n.
Paid plans: 3-day trial; a card is required and it is charged after day 3 unless you cancel. Hobby (€29/mo) gives real-time REST without the WebSocket.
Educational content for adults (18+). A drop alert is market data, not a tip.
Questions people ask#
Do I need a Slack app?#
Only an incoming webhook, which you create from a Slack app's settings in your workspace. Keep the webhook URL secret like an API key.
Can I filter to big games?#
Add league= ids to the query, or filter by league in the loop.
Live only?#
Add live=true to the /v1/drops query.