Integracje · przewodnik
Webhooki Discord — kompletny przewodnik (2026)
Webhook Discord: POST JSON na URL i wiadomość pojawia się na kanale. Bez bota, bez połączenia websocket. Pola embeda, rate limit 30/min, curl/JS/GitHub Actions, pułapki.
10 min czytania · ostatnia aktualizacja: 2026-06-18
Krótka odpowiedź: czym są webhooki Discord
Webhook Discord to URL na który wysyłasz żądanie HTTP POST z JSON-em, a Discord wyświetla wiadomość na wskazanym kanale. Nie potrzeba bota, nie ma trwałego połączenia websocket, jest jednokierunkowy (z systemu zewnętrznego do kanału). Tworzysz go w: ustawienia kanału → Integrations → Webhooks → New Webhook. Limit: 30 wiadomości / minutę per webhook.
Webhook vs bot account — czym się różnią
| Cecha | Webhook | Bot account |
|---|---|---|
| Typ połączenia | Brak (jednorazowy HTTP POST) | Websocket gateway (trwałe) |
| Kierunek | Jednokierunkowy (HTTP → kanał) | Dwukierunkowy |
| Reaguje na komendy | Nie | Tak (/komendy, klika przyciski) |
| Status online | Brak | „Online" w liście członków |
| Wymaga hostingu | Nie | Tak (VPS lub platforma jak FlowCord) |
| Auth | URL = secret | Token bota (OAuth2) |
| Rate limit | 30/min per webhook | 50/10s per kanał (globalnie 50/s) |
| Embed z przyciskami | Nie (tylko embed) | Tak |
| Reaguje na zdarzenia (member_join etc.) | Nie | Tak |
Kiedy używać webhooków
Webhooki błyszczą tam gdzie potrzebujesz prostego dwu-way push z zewnętrznego systemu do kanału Discord, bez pisania bota:
- CI/CD notifications: GitHub Actions, GitLab CI push webhook na
#deployspo każdym build/start. - Monitoring: UptimeRobot / BetterStack ping na
#alertsgdy endpoint down. Sentry/Rollbar push krytycznych błędów. - Formularze: Typeform/Tally wysyła zgłoszenie na
#leads. - Stripe payments: webhook na
#paymentspo każdym charge. - Custom integrations: skrypt Python / N8n / Make.com push danych z dowolnego systemu.
Jeśli potrzebujesz reagowania na wiadomości Discorda (komendy, klika przycisków), webhook nie wystarczy — potrzebujesz bota. Webhooki też nie pozwala na custom logiki (warunki, pętle) — jeśli if status == 'error' then ping @oncall, potrzebujesz bota albo middleware jak N8n.
Jak stworzyć webhook Discord
- Na Discordsie: ustawienia kanału (⚙ przy kanale) → Integrations → Webhooks.
- Kliknij „New Webhook". Domyślna nazwa „Captain Hook", avatar losowy.
- Edytuj nazwę (będzie się podpisywać wiadomościami) i avatar.
- Kliknij „Copy Webhook URL". Trzymaj jak hasło.
- Test: wyślij curl (przykład poniżej).
Anatomia webhook POST — pola JSON
{
"content": "Tekst wiadomości (max 2000 znaków)",
"username": "Nazwa nadpisująca nazwę webhooka",
"avatar_url": "https://example.com/avatar.png",
"tts": false,
"embeds": [
{
"title": "Tytuł embeda",
"description": "Główny tekst embeda (max 4096)",
"url": "https://link-w-tytule",
"color": 5736417,
"timestamp": "2026-06-18T12:00:00.000Z",
"footer": { "text": "Stopka", "icon_url": "..." },
"thumbnail": { "url": "https://..." },
"image": { "url": "https://..." },
"author": { "name": "Autor", "url": "..." },
"fields": [
{ "name": "Pole 1", "value": "Wartość", "inline": true },
{ "name": "Pole 2", "value": "Wartość", "inline": false }
]
}
],
"allowed_mentions": {
"parse": ["users", "roles", "everyone"]
}
}Wymagane minimum: {"content":"..."} albo jeden embed. Reszta opcjonalna. color jako integer (nie hex) — wartość RGB złączona w jeden int.
Przykłady kodu
cURL
curl -X POST "https://discord.com/api/webhooks/123/abc..." \
-H "Content-Type: application/json" \
-d '{"content":"Deploy zakończony ✅","username":"CI"}'JavaScript (fetch)
await fetch(process.env.DISCORD_WEBHOOK_URL, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
content: 'Build #' + process.env.BUILD_NUMBER + ' gotowy',
embeds: [{
title: 'Szczegóły',
url: process.env.BUILD_URL,
color: 0x22C55E, // zielony (parseInt auto)
fields: [
{ name: 'Branch', value: process.env.BRANCH, inline: true },
{ name: 'Czas', value: process.env.BUILD_TIME + 's', inline: true }
]
}]
})
});GitHub Actions YAML
name: Deploy notify
on:
workflow_dispatch:
jobs:
notify:
runs-on: ubuntu-latest
steps:
- name: Discord webhook
env:
WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK }}
run: |
curl -X POST "$WEBHOOK_URL" \
-H "Content-Type: application/json" \
-d "{"content":"Deploy zatwierdzony przez ${{ github.actor }}"}"Rate limits
Discord rate limituje webhooks: 30 wiadomości / minutę per webhook, z burst dozwolonym do 5 wiadomości w pierwszej sekundzie. Powyżej limitu → HTTP 429 z nagłówkiem Retry-After (w sekundach). Implementacja: retry z exponential backoff albo kolejka z opóźnieniem.
Dla CI/CD to nie problem — deploy event raz na jakiś czas. Dla wysokotonażowych powiadomień (1M użytkowników → 1M webhook posts) — użyj bota zamiast webhooka, bot ma wyższe limity (50 msg/10s per kanał globalnie).
Bot + webhook — razem
Webhooki i boty to nie albo-albo. Złożone integracje używają obu:
- Bot tworzy webhook dynamicznie per kanał (akcja
create webhook), zapisuje URL w zmiennej. Każdy kanał ma własny URL. - Zewnętrzny system wysyła webhook z powiadomieniem (np. „new order #1234").
- Bot nasłuchuje na kanale (intent
MESSAGE_CREATE), widzi powiadomienie i reaguje — np. tworzy ticket, ping mod, aktualizuje statystyki.
To decouples — system zewnętrzny nie musi znać tokenu bota, pushuje webhook. Bot dostaje dane przez zdarzenie, niesie całą logikę.
Najczęstsze pułapki
- Webhook URL = secret. Traktuj jak hasło. Nie commit do repo. W GitHub Actions użyj
secrets.DISCORD_WEBHOOK. W .env. Jeśli wyciekł: usuń webhook w ustawieniach kanału i stwórz nowy (stary URL jest natychmiast martwy). - Embed color jako integer nie jako hex. Discord API wymaga liczby (np.
5736417) a nie stringa ("#5765F2"). W JS:parseInt("5765F2", 16)albo0x5765f2. W Python:int("5765F2", 16). - Rate limit intervals. Po 429 czekaj
Retry-Afterz headera (w sekundach), nie domyślnej wartości. Inaczej ponowny 429. - Max 10 embedów / wiadomość. Więcej? Podziel na 2 POST-y z opóźnieniem albo użyj bota z akcją „bulk send".
- Max 6000 znaków łącznie w embedach + content. Discord tnie po 6000, reszta ląduje w osobnej wiadomości z suffixem „(continued)".
- Webhook nie „online". Webhook nie pokazuje się w liście członków, nie ma statusu. To po prostu anonimowy sender. Nie nadużywaj do symulacji „bot pisze" — użyj wtedy bota.
allowed_mentionsdomyślnie off. Bez tego pola Discord nie pozwala na wzmianki @everyone / @role przez webhook. Większość kont nie potrzebuje, ale jeśli chcesz pingować rolę — dodaj{"allowed_mentions":{"parse":["roles"]}}.
Webhooki świetnie łączą się z botem FlowCord — bot może zarządzać webhookami dynamiecznie i nasłuchiwać na ich kanałach. Zobacz też artykuł o moderacji automatycznej (bot nasłuchuje na #alerts z webhooka Sentry → auto-reakcja) oraz system ticketów (webhook formularza → nowy ticket). Skoro pytasz o webhooki — sprawdź też porównanie FlowCord vs Discord.js (gdzie webhook możesz obsługiwać z kodu, w FlowCord wizualnie).
Najczęstsze pytania
Czy webhook Discord jest bezpieczny?
Webhook URL działa jak hasło — każdy kto zna URL może wysłać wiadomość. Trzymaj URL w secrets (env vars), nie w repo. Jeśli URL wycieknie: wejdź na ustawienia kanału → Integrations → Webhooks → usuń i stwórz nowy. Discord nie oferuje autoryzacji na webhook URL.Ile wiadomości mogę wysłać przez jeden webhook?
30 wiadomości na minutę per webhook (burst do 5 w pierwszej sekundzie). Powyżej → HTTP 429 z nagłówkiem Retry-After. W GitHub Actions / CI-CD narzędziach używaj retry z exponential backoff.Czy mogę wysłać embed przez webhook?
Tak. W JSON body dodaj tablicę embeds (max 10 embedów per wiadomość). Każdy embed ma title, description, fields[], color (jako integer!), thumbnail, image, footer, timestamp. Discord renderuje embed tak samo jak bot-embed.Jaka jest różnica między webhookiem a botem Discord?
Webhook: jednokierunkowy (POST dari zewnętrznego systemu do kanału), bez połączenia, bez komend, bez „online" statusu. Bot: dwukierunkowy (websocket), reaguje na /komendy, klika przyciski, widzi wiadomości. Webhook jest prosty do powiadomień one-shot. Bot jest pełnoprawną aplikacją.Dlaczego kolor embeda w webhooku jest liczbą a nie hex?
Discord API definiuje color jako integer (wartość RGB złączona w jeden 24-bit int). W JSON wysyłasz np. 5736417, nie "#5765F2". W FlowCord konwersja jest automatyczna, ale w curl/JS musisz sam: parseInt("5765F2", 16). Częsty bug.Czy mogę połączyć webhook i bota?
Tak i warto. Bot może dynamicznie tworzyć webhooki (akcja „create webhook" per kanał) i zarządzać nimi. Pattern: zewnętrzny system (CI/CD) wysyła webhook → bot nasłuchuje na webhook channel (intent MESSAGE_CREATE) i reaguje (np. „deploy done" → bot auto-check statystyk na produkcji).