feedhook · recipes

Get a Discord, Slack, or no-code alert when a YouTube channel posts

You want something to happen the moment a channel uploads — a Discord ping, a Slack message, a row in a database, a Zap. YouTube can push that event in ~8 seconds, but the plumbing (WebSub handshakes, ~5-day lease renewals, signature checks) is a pain. Feedhook does that once and POSTs you clean JSON; these recipes turn that POST into the thing you actually want. Free for 1 channel — every recipe starts the same way:

# 1. Sign up (free, 1 feed) — the API key is shown once
curl -X POST https://feedhook.walls.sh/accounts -d '{"email":"you@example.com"}'

# 2. Point the channel's webhook at your receiver (or no-code URL below)
curl -X POST https://feedhook.walls.sh/subscriptions \
  -H 'authorization: Bearer fh_your_key' \
  -d '{"channel":"@mkbhd","callbackUrl":"https://your.app/hook"}'
# → save the returned "secret": it signs every delivery (shown once)

# 3. Fire a real signed test through the live pipeline — no need to wait for a video
curl -X POST https://feedhook.walls.sh/subscriptions/SUB_ID/test -H 'authorization: Bearer fh_your_key'

Prefer to just watch it work first? npx -y feedhook-quickstart @mkbhd runs this whole flow (account → subscribe → real signed delivery → signature verified) against the live API in ~5 seconds, no endpoint of your own required.

Every delivery is a JSON POST with x-feedhook-signature: sha256=<hmac>; the body carries title, author, url, videoId, publishedAt. Full contract in the docs.

YouTube → Discord

Drop a message in a channel via a Discord incoming webhook (Server Settings → Integrations → Webhooks → New Webhook → Copy URL). No server? Deploy the one-click Cloudflare Worker instead — same thing, hosted free on the edge, no code to run.

// node + express — verifies the signature, then posts to Discord
import express from "express";
import { createHmac, timingSafeEqual } from "node:crypto";

const SECRET  = process.env.FEEDHOOK_SECRET;       // from step 2
const DISCORD = process.env.DISCORD_WEBHOOK_URL;   // your Discord webhook

const app = express();
app.post("/hook", express.raw({ type: "*/*" }), async (req, res) => {
  const want = "sha256=" + createHmac("sha256", SECRET).update(req.body).digest("hex");
  const got  = req.headers["x-feedhook-signature"] || "";
  if (want.length !== got.length || !timingSafeEqual(Buffer.from(want), Buffer.from(got)))
    return res.sendStatus(401);                    // not from Feedhook — drop it

  const v = JSON.parse(req.body);
  await fetch(DISCORD, {
    method: "POST",
    headers: { "content-type": "application/json" },
    body: JSON.stringify({ content: `📺 **${v.author}** posted: **${v.title}**\n${v.url}` }),
  });
  res.sendStatus(200);                             // 2xx within 15s or Feedhook retries
});
app.listen(3000);

YouTube → Slack

Same receiver, Slack incoming webhook body. No server? Deploy the one-click Cloudflare Worker instead — same thing, hosted free on the edge, no code to run.

  const v = JSON.parse(req.body);                  // (signature check identical to above)
  await fetch(process.env.SLACK_WEBHOOK_URL, {
    method: "POST",
    headers: { "content-type": "application/json" },
    body: JSON.stringify({ text: `*${v.author}* posted <${v.url}|${v.title}>` }),
  });

YouTube → Zapier / Make / n8n (no code)

No server needed — the platforms give you a catch-all webhook URL; paste it as the callbackUrl in step 2:

• Zapier  — trigger "Webhooks by Zapier → Catch Hook", copy its URL
• Make    — module "Webhooks → Custom webhook", copy the address
• n8n     — "Webhook" node, POST, copy the Production URL

Each delivers the JSON body straight into your scenario; map title / url / author onto the next step (a tweet, a row, an email). Run step 3 once and the test.ping shows up as live sample data to map against.

YouTube → database / queue

Persist or enqueue every new video — the verified handler body is just:

  const v = JSON.parse(req.body);
  await db.videos.insertOne({
    videoId: v.videoId, channelId: v.channelId,
    title: v.title, url: v.url, publishedAt: v.publishedAt,
  });

Why not just poll the Data API? See the honest comparison. Want an agent to wire this up itself? npx -y feedhook-mcp. Live delivery numbers: /metrics.

← a wall on walls.sh