Only show guides for your app
Two honest ways to hear about a deploy — a schedule that fires a webhook on the "git deployment completed" event, or a post-deploy command that posts to Discord yourself. Includes the exact success and failure responses a Discord webhook returns.
A deploy that lands silently is a deploy you have to go check. Better to be told: a ping in Discord that says "shipped" — or, more usefully, "that ship failed." Falix gives you two clean ways to wire this up. This guide covers both and when to reach for each.
| At a glance | |
|---|---|
| You need | a server deploying from Git, and a Discord channel you can post to |
| Plan | any |
| Time | fifteen minutes |
| Approach | How it fires | Best for |
|---|---|---|
| Schedule webhook | A schedule with a webhook attached, triggered by the deploy | Alerts about the deploy event itself — started, completed, or failed |
| Post-deploy command | A curl that your deploy runs and posts to Discord |
A custom message with details you control (commit, version, what changed) |
They're not mutually exclusive — plenty of people run both.
Schedules can fire a webhook when they run, and a schedule can be tied to your deploy. Two ways to link them:
Either way, once the schedule is tied to your deploy, attach a webhook to it. On the schedule you add a webhook URL — a Discord webhook, or any plain HTTPS endpoint — and pick which events notify you:
| Notify on | Tells you |
|---|---|
| Schedule started | the deploy hook began |
| Schedule completed | it finished cleanly |
| Task completed | a specific task in the schedule finished |
| Task failed | something in the schedule broke |
💡 Tip: Task failed is the alert most people actually want. Success is quiet by nature; it's the failed backup or the broken restart you need to hear about without watching the logs yourself. The webhook URL must be HTTPS, and there's a Test button to confirm it lands in the right channel before you rely on it.
This approach is the low-code one: no scripting, and it reports on the deploy machinery itself. See Automate your server with Schedules for the full builder.
For a message you compose — "Deployed commit abc123 ✅", a version bump, a changelog line — post to a Discord webhook yourself as a post-deploy command. A Discord webhook is just a URL you send an HTTP POST to; no bot, no token.
First, create the webhook in Discord: Edit Channel → Integrations → Webhooks → New Webhook → Copy Webhook URL. Keep that URL in your server's .env — treat it like a password. Then add a post-deploy command:
curl -X POST "$WEBHOOK_URL" \
-H "Content-Type: application/json" \
-d '{"content": "Deploy finished ✅", "username": "Falix Deploy"}'
Knowing the exact responses turns "it didn't work" into a two-second diagnosis:
| Response | Meaning |
|---|---|
204 No Content |
Success — the message posted. There's no body; that's the whole signal. |
404 {"message": "Unknown Webhook", "code": 10015} |
The URL is wrong or the webhook was deleted — fix the URL, not the code |
401 Unauthorized |
Right webhook ID, wrong token — re-copy the full URL |
400 Bad Request |
Malformed body — content must be a string and you must send Content-Type: application/json |
That 404 is worth understanding: it means Discord received and parsed your request and rejected only the missing webhook identity — so your curl is correct and the URL is the problem. The full treatment, including the Cloudflare User-Agent gotcha for raw Python requests, is in Post to a Discord webhook from any code.
⚠️ Heads up: For the post-deploy command to fire the alert, the deploy's post-deploy action and command order have to actually reach it. Put the notify command last so "deploy finished" only sends once the real work has run.
curl — you control the payload, including embeds for a titled, colored card.curl for the nice "what shipped" message. They don't conflict.http:// URL won't be accepted.404 Unknown Webhook from the curl — the URL is wrong or the webhook was deleted; copy it again from the channel's Integrations page.curl only runs if the deploy reaches it. To hear about failures, use the schedule's task failed event, which fires on the failure itself.