DEV Community

Cover image for I Built a Gumroad Telegram Sale Alert in 5 n8n Nodes. Zapier Charges $20/mo and Still Delays It 15 Minutes
tinycoder-studio
tinycoder-studio

Posted on AI-assisted

I Built a Gumroad Telegram Sale Alert in 5 n8n Nodes. Zapier Charges $20/mo and Still Delays It 15 Minutes

Your product sells at 2:47am. You find out at 9:15am, when you check email and the Gumroad notification is sitting three promotions down in your inbox.

That's the problem nobody sells a fix for, because the fix is boring: know the instant a sale happens. Not when you check the dashboard. Not when the weekly payout email lands. When it happens.

Someone put it better than I can. One comment on my last post: "silent sales you didn't even know about." That's the pain. Gumroad already emails you, but email waits for you, and you're not a notification, you're a person with a life. Sales fire at all hours, and you're not watching.

So I built the dumbest thing that solves it: a 5-node n8n workflow that pushes a Telegram alert to my phone the moment Gumroad pings. No polling. No monthly fee. Nothing else to babysit. And yeah, Zapier charges about $20/mo for a version that's still 15 minutes late on its free tier.

What I built: five nodes, one line

This is the workflow that survived my 7-setup n8n teardown, the one I called "the rare workflow that's exactly as simple as it looks." It's a straight line: webhook in, Telegram out, nothing in between that can rot.

Five nodes, exact names, nothing invented:

  1. Webhook: Gumroad Sale (n8n-nodes-base.webhook) — Gumroad POSTs to /webhook/gumroad-sale on every new sale. This is the trigger. No cron, no scheduler, no compute while idle.
  2. IF: Is a Sale? (n8n-nodes-base.if) — passes only payloads that carry a sale_id. This one node exists to kill Gumroad's test ping, which it fires the moment you save the webhook URL. Without it, you'd alert yourself on an imaginary sale.
  3. Format Telegram Message (n8n-nodes-base.function) — builds the alert text. Paid sales get a 💰 header and a price line; free downloads get a 🎁 header. Product name, buyer email, timestamp.
  4. Telegram: Send Alert (n8n-nodes-base.httpRequest) — a plain POST to the Telegram Bot API sendMessage endpoint. Token and chat ID come from env vars, never hardcoded.
  5. Respond (n8n-nodes-base.respondToWebhook) — returns HTTP 200 so Gumroad knows the ping landed and stops retrying.

That's the whole thing. Five nodes, one straight line, no community nodes, no n8n credentials to configure. The bot token lives in the request URL, pulled from $env.TELEGRAM_BOT_TOKEN, which works on both n8n Cloud and self-hosted.

The Zapier math: $20/mo and still 15 minutes late

Here's the comparison that made me build this instead of using the obvious tool.

Zapier's free tier polls your Gumroad account every 15 minutes. That means a sale at 2:47am is discovered somewhere between 2:47 and 3:02, so worst case you're a quarter hour late, on average 7.5 minutes. And the free tier ships with a 100 tasks/month ceiling. Cross it mid-month and your automation just stops running until the calendar flips. On a product that sells, that's not a tool, that's a lottery.

Want it faster? Zapier's paid tier runs about $20/mo (Professional, billed annually). What you buy is a shorter poll interval, not no interval. It's still polling. Every sale still waits for the next poll cycle to notice it. You're paying monthly, forever, for the privilege of being less late.

The n8n workflow doesn't poll at all by design. Gumroad's webhook is a push: the moment a sale lands, Gumroad fires a POST at my URL. No interval to miss, no recurring subscription. Self-hosted on your own box, the runtime cost is $0, and the workflow fires only when something actually happens.

Zapier Free Zapier Professional This n8n workflow
How it finds sales Polls every 15 min Polls (shorter interval) Webhook push, no polling
Worst-case delay ~15 min Interval-bound, still >0 Zero by design*
Task ceiling 100/month Higher, still capped None
Cost $0 ~$20/mo, forever $0 (self-hosted)

*Zero by design: the webhook fires when Gumroad pings. I'm not going to sell you latency numbers this thing hasn't earned in production; the architecture just has no poll cycle in it.

Inside the workflow: the JSON nobody screenshots

Everyone posts the canvas screenshot. Nobody shows the code. Here's the actual node config from the import file, so you can judge it like a developer instead of like a customer.

The filter lives in one condition on the IF node:

`json
{
  "name": "IF: Is a Sale?",
  "type": "n8n-nodes-base.if",
  "parameters": {
    "conditions": {
      "boolean": [
        { "value1": "={{ $json.sale_id != null }}", "operation": "true" }
      ]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

`

No sale_id, no alert. That's the entire spam filter.

The formatter is where the message takes shape, and where the Gumroad payload quirks get handled:

`js
const sale = $json;
const product = sale.product_name || 'Unknown product';
const email = sale.email || 'no email captured';
const when = sale.timestamp ? new Date(sale.timestamp * 1000).toISOString() : new Date().toISOString();
const isPaid = (sale.price || 0) > 0;
const currency = sale.currency || 'USD';

const lines = [
isPaid ? '💰 PAID SALE' : '🎁 FREE DOWNLOAD',
'',
Product: ${product},
Buyer: ${email},
Time: ${when}
];
if (isPaid) lines.splice(3, 0, Price: ${currency} ${(sale.price / 100).toFixed(2)});

return [{ json: { message: lines.join('\n'), is_paid: isPaid } }];
`

Gumroad sends price in cents, which is why the code divides by 100. timestamp arrives in unix seconds, hence the * 1000. Both are payload quirks that would've had me staring at a wall for an hour if I'd hit them blind, so they're handled in the node instead of in your head.

The send is a one-liner HTTP request reading two env vars, so your token never sits in the workflow JSON:

json
{
"name": "Telegram: Send Alert",
"type": "n8n-nodes-base.httpRequest",
"parameters": {
"url": "= {{ 'https://api.telegram.org/bot' + $env.TELEGRAM_BOT_TOKEN + '/sendMessage' }}",
"method": "POST",
"jsonParameters": true,
"bodyParametersJson": "={{ { chat_id: $env.TELEGRAM_CHAT_ID, text: $json.message, parse_mode: 'HTML' } }}"
}
}

One more thing you get for free: free downloads alert too. isPaid branches the header (💰 vs 🎁), and the price line only shows up on paid sales. Tracking free downloads in real time tells you when a launch post is actually landing, which is worth more than the paid alerts in the early days.

What you'll get on your phone looks like this, straight from the formatter above:

Honest limitations (read this before importing)

I'm not going to bury the caveats, because the caveats are the part that's actually true.

Structurally validated, not production-tested. This workflow parses clean, the wiring is verified node-to-node, and it's version-pinned to n8n 1.x. It has not been run against a live n8n instance or a real Gumroad sale in my environment. That's the entire honesty envelope: structurally valid and import-ready, not "battle-tested at scale." Test it before you rely on it, trigger Gumroad's test ping, or buy your own product for $0, and confirm the message lands. If that caveat bothers you, good. It should.

Self-hosted means public. Gumroad has to reach your webhook. If your n8n runs on localhost, Gumroad can't find it, and no amount of workflow cleverness fixes that. You need either n8n Cloud (the free tier works for a single workflow like this) or a self-hosted instance with a public URL.

The workflow ships inactive. The import file has active: false, because nobody should ship a workflow that starts firing at strangers the second it's imported. You flip the toggle, copy the /webhook/gumroad-sale URL, and paste it into Gumroad → Settings → Advanced → Webhooks.

It's fire-and-forget. No retry queue, no database, no dedupe beyond the sale_id filter. If Telegram is down, the alert is gone. For a "I want to know a sale happened" push, that's the right trade. For a financial system, it isn't, but then again, neither is Zapier.

Take it, it's free

This workflow is a free download: import-ready JSON, MIT licensed, no catch beyond an email address so I can send you the setup doc (5 minutes, BotFather → bot token, env vars, import, activate, paste webhook URL).

Download the Gumroad Sale → Telegram Alert workflow →

I'm also building a full pack around the workflows that survived the teardown, tested-by-inspection n8n workflows plus AI agent prompt skills, $29 on Gumroad. The free workflow is the on-ramp: if a 5-node sale alert is your kind of boring, the pack is the rest of it.

Your product is going to sell at 2:47am someday. The only question is whether you find out at 2:47am, or at brunch.

Top comments (0)