Skip to content

Substack to Slack or Discord: Announce New Posts

By the newsletterapi team · Published · Updated · 6 min read

The problem: “Substack has no webhooks, so nothing tells my team's Slack or my Discord community when a new post goes out.”

Cover image: Substack to Slack or Discord: Announce New Posts

Short answer

Substack has no Slack or Discord app and no webhooks as of October 2026, but every publication has a public RSS feed at /feed. The quickest route is Slack's own RSS app with /feed subscribe. For Discord, or for custom messages, point an n8n RSS trigger or a small script at the feed and send each new post to an incoming webhook.

Announcing each new post in Slack or Discord is one of the easiest Substack automations to get right, because it needs nothing but your public RSS feed. This guide covers three ways to do it, from a two-minute no-code setup to a tested Node.js script, and is honest about what you can't pipe into Slack (new subscribers in real time). Facts are as of October 2026. For everything else Substack exposes to developers, see our Substack API guide.

newsletterapi is an independent project, not affiliated with Substack. Nothing below depends on newsletterapi.

The problem

Teams and communities live in Slack and Discord, and Substack doesn't talk to either. As one person put it: "without APIs and webhooks, what happens on Substack stays on Substack." (@denk_tweets). Another, more bluntly: "substack doesn't use webhooks." (@Ace_theSage). Writers who cross-post everywhere end up handing the job to an assistant or an agent: "Every time I post an X article, claude takes it and posts it in beehiiv, substack, medium, linkedin and my personal blog" (@AunySillyMe).

You don't need webhooks from Substack for this job. You need the feed.

Which Substack to Slack method should I use?

Method Slack Discord Setup Custom message Runs where
Slack RSS app Yes No Minutes, no code No Slack
n8n RSS Feed Trigger Yes Yes A few nodes, no code Yes n8n Cloud or self-hosted
Node.js script + incoming webhooks Yes Yes One script and a cron job Full control Any server or cron
newsletterapi post.published webhook Yes Yes Point it at your endpoint Yes Our service

All four start from the same input. Every publication has a feed at https://your.substack.com/feed, per Substack's help centre; with a custom domain it's https://yourdomain.com/feed. Paid posts appear in the feed cut at the paywall, so messages carry the title, link and preview. Our RSS feed guide explains what else the feed contains.

How do I add a Substack feed to Slack with no code?

Slack's RSS app does it inside Slack. The steps from Slack's help centre:

  1. Open the RSS app page in the Slack Marketplace, click Add to Slack, then Add RSS integration.
  2. Paste your Substack feed URL next to Feed URL, choose the channel, and click Subscribe to this feed.
  3. To add more feeds later, type /feed subscribe https://yourname.substack.com/feed in the channel.

Use /feed list to see a channel's feeds with their IDs and /feed remove [ID] to stop one. Slack says the app is available on all plans and, by default, all members except guests can use it. It "polls for new items" and doesn't state an interval, so expect a delay rather than an instant post. If Slack rejects the URL, Slack's help suggests validating the feed with the W3C feed validator.

The trade-off: you can't change the message format, and there is no Discord equivalent. For either, use one of the next two methods.

How do I create the incoming webhooks?

Both n8n and the script below post to an incoming webhook URL.

Slack: create a Slack app, turn on Incoming Webhooks, click Add New Webhook to Workspace, pick the channel and click Authorize (Slack docs). The URL looks like https://hooks.slack.com/services/T000/B000/XXXX and posts to that one channel only. Slack warns: "Your webhook URL contains a secret", and it "actively searches out and revokes leaked secrets".

Discord: open Server Settings, then Integrations, click Create Webhook, choose the text channel, then Copy Webhook URL (Discord Support). Discord's Execute Webhook endpoint takes JSON with a content field of up to 2000 characters, or up to 10 embeds.

How do I send Substack posts to Slack or Discord with n8n?

  1. Add an RSS Feed Trigger with your feed URL and Poll Times set to Every Hour (n8n docs).
  2. Add a Slack node (Message, Send) using an n8n Slack credential, or an HTTP Request node that POSTs {"text": "New post: {{ $json.title }} {{ $json.link }}"} to your Slack webhook URL.
  3. For Discord, add a Discord node, or an HTTP Request that POSTs {"content": "New post: **{{ $json.title }}**\n{{ $json.link }}"} to the Discord webhook URL.
  4. Activate the workflow.

The trigger won't replay your archive. In n8n's source it only emits items newer than the last one it saw, starting from the time you activate it. More Substack workflows are in automating Substack with n8n.

How do I post Substack updates to Slack and Discord with code?

This Node.js script reads the feed with rss-parser, remembers which posts it has already announced in a small JSON file, and posts new ones (oldest first) to Slack, Discord or both. On the first run it records the current feed without posting, so your channel isn't flooded. Slack text is escaped as Slack's formatting docs require (&, < and >). We tested it on Node 24 on 2026-10-24 against a live Substack feed, with local servers standing in for the two webhooks.

Install with npm install rss-parser and save as notify.mjs:

import { readFile, writeFile } from "node:fs/promises";
import Parser from "rss-parser";

const FEED_URL = process.env.FEED_URL ?? "https://yourname.substack.com/feed";
const SLACK_WEBHOOK_URL = process.env.SLACK_WEBHOOK_URL;     // https://hooks.slack.com/services/...
const DISCORD_WEBHOOK_URL = process.env.DISCORD_WEBHOOK_URL; // https://discord.com/api/webhooks/...
const STATE_FILE = process.env.STATE_FILE ?? "seen.json";

const parser = new Parser({ timeout: 15000 });
const slackEscape = (s) => s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");

async function loadSeen() {
  try { return new Set(JSON.parse(await readFile(STATE_FILE, "utf8"))); }
  catch { return null; } // first run: no state file yet
}

async function send(url, body) {
  const res = await fetch(url, {
    method: "POST",
    headers: { "content-type": "application/json" },
    body: JSON.stringify(body),
  });
  if (!res.ok) throw new Error(`Webhook returned ${res.status}: ${await res.text()}`);
}

const feed = await parser.parseURL(FEED_URL);
const seen = await loadSeen();
const items = feed.items.map((i) => ({
  id: i.guid ?? i.link,
  title: i.title ?? "",
  url: i.link ?? "",
  summary: (i.contentSnippet ?? "").slice(0, 280),
}));

// First run: remember what's already in the feed instead of posting the backlog.
const fresh = seen ? items.filter((i) => !seen.has(i.id)).reverse() : []; // oldest first

for (const item of fresh) {
  if (SLACK_WEBHOOK_URL) {
    await send(SLACK_WEBHOOK_URL, {
      text: `New post: ${slackEscape(item.title)} ${item.url}`, // used in notifications
      blocks: [{
        type: "section",
        text: { type: "mrkdwn", text: `*<${item.url}|${slackEscape(item.title)}>*\n${slackEscape(item.summary)}` },
      }],
    });
  }
  if (DISCORD_WEBHOOK_URL) {
    await send(DISCORD_WEBHOOK_URL, { content: `New post: **${item.title}**\n${item.url}`.slice(0, 2000) });
  }
  console.log("Announced:", item.title);
}

const ids = new Set([...items.map((i) => i.id), ...(seen ?? [])]);
await writeFile(STATE_FILE, JSON.stringify([...ids].slice(0, 500)));

Run it hourly from cron on any small server, keeping the webhook URLs in environment variables:

0 * * * * cd /opt/substack-notify && SLACK_WEBHOOK_URL=... DISCORD_WEBHOOK_URL=... node notify.mjs >> notify.log 2>&1

If a webhook call fails, the script exits before saving state, so it retries on the next run; a post that had already gone to the other channel may be sent there again. Keep the state file on persistent disk, because a deleted file just means one silent first run.

Can I send new Substack subscribers to Slack?

Not as live events. Substack has no subscriber webhooks; our Substack webhooks guide lists the closest signals, and the new-subscriber notification guide explains why the notification email no longer names the subscriber. If Substack has enabled the read-only Publisher API for your publication, a daily job can read /subscribers/counts and post yesterday's total and paid figures to Slack. The path and field names come from the open-source substack-publisher-mcp wrapper (self-reported). That gives you a daily team update, not per-person alerts.

Is there an easier way to trigger on new posts?

The newsletterapi embeds and content webhooks send a signed post.published event to your URL when a new post appears in your feed, so your n8n workflow, Slack bot or Discord bot reacts to a push instead of running its own poller and state file. Pair it with the Posts API when you want the full post as Markdown, for example to post a summary thread. To get access, see pricing or email hello@newsletterapi.io.

Questions people ask

Is there a Substack app for Slack or Discord?
Not from Substack, as of October 2026. Use your publication's RSS feed with Slack's RSS app, with n8n, or with a script that posts to an incoming webhook.
How fast does a new post reach Slack?
It depends on how often the feed is polled. Slack's RSS app doesn't publish an interval; with n8n or a cron script you choose it, and hourly is plenty for a newsletter.
Will paid posts show their full text in Slack?
No. Substack's RSS feed cuts paid posts at the paywall, so the message carries the title, link and preview. Readers click through to Substack to read the rest.
Can I get new Substack subscribers in Slack?
Not as live events. Substack has no subscriber webhooks. If the Publisher API is enabled for you, you can post a daily count; otherwise check your dashboard or export.
Is a Slack webhook URL safe to share?
No. Slack says the webhook URL contains a secret. Store it in an environment variable or your automation tool's credentials, never in a public repo.

Sources

  1. Substack help: Is there an RSS feed for my publication? (accessed 2026-10-24)
  2. Slack Help: Add RSS feeds to Slack (accessed 2026-10-24)
  3. Slack Marketplace: RSS app (accessed 2026-10-24)
  4. Slack developer docs: Sending messages using incoming webhooks (accessed 2026-10-24)
  5. Slack developer docs: Formatting message text (escaping) (accessed 2026-10-24)
  6. Discord Support: Intro to Webhooks (accessed 2026-10-24)
  7. Discord developer docs: Execute Webhook (accessed 2026-10-24)
  8. n8n docs: RSS Feed Trigger node (accessed 2026-10-24)
  9. n8n source: RssFeedReadTrigger.node.ts (polling logic) (accessed 2026-10-24)
  10. rss-parser on GitHub (accessed 2026-10-24)
  11. dkships/substack-publisher-mcp (wrapper around the Publisher API) (accessed 2026-10-24)
  12. @denk_tweets on X: what happens on Substack stays on Substack (accessed 2026-10-21)
  13. @Ace_theSage on X: substack doesn't use webhooks (accessed 2026-10-21)
  14. @AunySillyMe on X: cross-posting every article (accessed 2026-10-21)