Migrate to RunxBuild and earn up to $50 in hosting credit on your first deposit.

Calculate your savings
unxBuild
Back to Blog Troubleshooting

Discord Webhook Not Working With GitHub: The Missing /github Suffix

Sean

Platform Writer

Aug 14, 2026
6 min read

Append /github to the end of your Discord webhook URL and paste that into GitHub. The reason nothing arrives is that GitHub sends its own payload format and Discord expects a different one, so Discord rejects the request with a 400. The /github suffix tells Discord to translate rather than reject.

Discord Webhook Not Working With GitHub: The Missing /github Suffix

This is the fix in nine out of ten cases, and it is not documented anywhere obvious in either product. The rest of this covers why it works and the other causes worth checking when it does not.

Table of contents

The fix

Take the webhook URL Discord gives you and add /github to the end.

Discord gives you:
https://discord.com/api/webhooks/123456789/AbCdEf...

Paste this into GitHub:
https://discord.com/api/webhooks/123456789/AbCdEf.../github

Then in GitHub, under Settings, Webhooks, Add webhook, set the content type to application/json. Leaving it as the default form-encoded type is the second most common cause of silence.

  1. In Discord, open Server Settings, Integrations, Webhooks, and create one for the target channel.
  2. Copy the webhook URL and append /github to it.
  3. In the GitHub repository, go to Settings, Webhooks, Add webhook.
  4. Paste the modified URL as the payload URL.
  5. Set Content type to application/json.
  6. Choose which events to send, then save.

GitHub sends a ping event immediately on save. If a message appears in the channel, it is working. If not, the delivery log will now tell you why.

Why the suffix is needed

A Discord webhook expects a JSON body with a specific shape: a content string, or an embeds array with title, description, colour, and fields. Nothing else is accepted.

GitHub sends its own event payload, which looks nothing like that. It has a repository object, a sender, a ref, an array of commits, and dozens of other fields depending on the event. Posted to a plain Discord webhook, none of the expected keys are present, so Discord responds 400 Bad Request and discards it.

The /github suffix routes the request to a compatibility endpoint that knows how to read GitHub’s format and render it as a Discord message. Discord provides a similar /slack endpoint for the same reason.

This also explains why the failure is silent from GitHub’s side unless you look. GitHub delivered the request successfully and got a response, so from its point of view nothing went wrong. The rejection is in the response body, which you only see in the delivery log.

When the suffix is already there and it still fails

Check GitHub’s delivery log first. It is under Settings, Webhooks, click the webhook, then Recent Deliveries, and it shows the exact request and response for each attempt. This turns guessing into reading.

  • 401 Unauthorized: the webhook was deleted or regenerated in Discord. The URL contains a token, and it changes when the webhook is recreated. Create a new one and update GitHub.
  • 404 Not Found: the URL is wrong, or the channel or webhook no longer exists. Deleting a channel deletes its webhooks.
  • 400 Bad Request with the suffix present: usually the content type is not application/json.
  • 429 Too Many Requests: rate limited. A busy repository with all events enabled will hit this.
  • 204 No Content but nothing visible: the delivery succeeded, so the problem is in Discord, most often channel permissions.

That last case is the confusing one, because everything reports success. If Discord’s compatibility endpoint has no rendering for the event type you sent, it accepts and silently drops it. Not every GitHub event maps to a message.

Supported events include pushes, pull requests, issues, releases, and a handful of others. Selecting send me everything mostly generates rate limiting and dropped events rather than more messages.

Rate limits and the noise problem

Discord rate limits webhooks per channel, and the practical effect is that a push of many commits, or a busy monorepo, produces some messages and quietly loses others.

Two mitigations. Send fewer events: select individual events rather than everything, and in most cases pushes, pull requests, and releases are the ones anyone reads. And separate high-traffic repositories into their own channels so one noisy project does not consume the budget for the rest.

The broader point is that a channel receiving every event from every repository stops being read within about a week. The value of the integration is inversely proportional to its volume, and the configuration that works is deliberately sparse.

If you need richer formatting than the compatibility endpoint provides, the alternative is a small relay: GitHub posts to your own endpoint, which builds a Discord embed with exactly the fields you want and posts that to the plain webhook URL. That also gives you a place to filter, batch, and deduplicate.

Keeping the URL out of your repository

The webhook URL is a credential. Anyone holding it can post to your channel as the webhook, and there is no additional authentication.

For the repository integration this is handled for you, since the URL lives in GitHub’s webhook settings rather than in your code. The mistake happens when someone moves the notification into a GitHub Actions workflow and pastes the URL into the YAML.

# Wrong: the URL is in the repository, and in its history forever.
- run: curl -X POST https://discord.com/api/webhooks/123/AbCdEf... -d '...'

# Right: store it as a repository secret.
- run: curl -X POST "$DISCORD_WEBHOOK" -H 'Content-Type: application/json' -d '{"content":"Deploy finished"}'
  env:
    DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}

If a URL has been committed, rotating it means deleting the webhook in Discord and creating a new one. Removing the commit does not help, since the history and any fork retain it.

How this fits the rest of the stack

Notifications like these are usually the visible edge of a deploy pipeline, and they are most useful when they say something specific: which commit, which environment, whether it succeeded. That information has to come from somewhere that knows, which means a deploy process that records each build against its commit rather than a script that posts a fixed message. The RunxBuild hosting calculator shows the service, database, and storage as separate line items, and each deploy carries its own build log and a rollback to the previous version.

Useful related references:

FAQ

Why does my GitHub webhook not post to Discord?

GitHub sends its own payload format, which a plain Discord webhook rejects with a 400. Append /github to the Discord webhook URL so it routes to the compatibility endpoint that translates the payload.

What content type should I use for a GitHub to Discord webhook?

application/json. The default form-encoded type is the second most common reason deliveries fail after the missing /github suffix.

Why does GitHub report success but nothing appears in Discord?

Either the event type has no rendering at the compatibility endpoint and was accepted then dropped, or the webhook lacks permission to post in that channel. Check the response code in Recent Deliveries.

Why do some GitHub notifications go missing in Discord?

Rate limiting. Discord limits webhook posts per channel, so a burst of events loses some. Send fewer event types and split busy repositories across separate channels.

Is a Discord webhook URL a secret?

Yes. Anyone with it can post to the channel as that webhook, with no further authentication. Store it as a repository secret rather than in workflow files, and rotate it by recreating the webhook if it leaks.

#Discord Webhook#GitHub Webhooks#CI/CD#Integrations#Troubleshooting