Çoğu Discord botu, Discord'a sürekli açık bir WebSocket (gateway) bağlantısı kurar ve bu yüzden 7/24 çalışan bir sunucuya ihtiyaç duyar. Oysa botunuz yalnızca slash komutlarına, butonlara ve modallara yanıt veriyorsa başka bir yol var: Discord etkileşimleri doğrudan sizin HTTPS adresinize POST isteği olarak gönderebilir. Bu modelin adı HTTP interactions, ayarın adı ise "Interactions Endpoint URL"dir.
Bu yazıda HTTP interactions modelinin nasıl çalıştığını, zorunlu olan Ed25519 imza doğrulamasını, PING/PONG el sıkışmasını, bu modelde neleri kaybettiğinizi ve Discord'un resmî Cloudflare Workers eğitiminin ana adımlarını anlatıyoruz. Etkileşimlerin genel mantığı için slash komut rehberimize de bakabilirsiniz.
Gateway ile HTTP interactions arasındaki fark

Belgeye göre uygulamanız etkileşimleri birbirini dışlayan iki yoldan biriyle alır: WebSocket tabanlı gateway bağlantısı veya HTTP üzerinden giden webhook'lar. Varsayılan yol gateway'dir; Developer Portal'da bir Interactions Endpoint URL eklediğinizde etkileşimler HTTP ile gelmeye başlar.
| Gateway botu | HTTP interactions | |
|---|---|---|
| Bağlantı | Sürekli açık WebSocket | Her etkileşim için ayrı bir HTTPS POST isteği |
| Alabildiği olaylar | Mesaj, üye, ses, tepki gibi tüm gateway olayları | Yalnızca etkileşimler (komut, bileşen, modal, autocomplete) |
| Barındırma | Sürekli çalışan süreç (VDS/VPS) | Sunucusuz platformlar dahil herhangi bir HTTPS sunucusu |
| Ses ve müzik | Var | Yok |
| Güvenlik adımı | Token gizliliği | Token gizliliği ve her istekte imza doğrulaması |
Discord'un platform sayfası bu modeli şöyle özetler: yalnızca komutlara ve arayüz bileşenlerine yanıt vermesi gereken uygulamalar için uygundur, kalıcı bağlantı gerektirmez ve standart web altyapısıyla doğal olarak ölçeklenir.
Neleri kaybedersiniz?
- Gateway olayları gelmez. Mesaj içeriğini okuyan, üye katılımlarını karşılayan, tepki rolü veren veya AutoMod olaylarını dinleyen özellikler bu modelde çalışmaz.
- Ses yoktur. Müzik botu için gateway gerekir; bkz. müzik botu rehberi.
- Önbellek yoktur. Sunucu, kanal veya üye bilgisine ihtiyacınız varsa etkileşim payload'ındaki veriyi kullanır ya da REST API'yi çağırırsınız.
- Durum (presence) gösteremezsiniz. Botun "çevrimiçi" görünmesi gateway bağlantısıyla ilgilidir.
Buna karşılık bazı olayları gateway olmadan almanın da bir yolu vardır: Webhook Events. Bu, ayrı bir "Webhook Events URL" ile uygulama yetkilendirme gibi bazı olayların HTTP üzerinden gönderilmesidir. Desteklenen olay listesi için Discord Docs: Webhook Events sayfasına bakın. Intent'lerin hangi olayları getirdiğini intent rehberimizde anlattık.
Interactions Endpoint URL eklemeden önce
Belge, URL'nizi kaydetmeden önce uç noktanızın iki şeye hazır olmasını şart koşar. Bunlardan biri eksikse URL doğrulanmaz ve kaydedilmez:
- Discord'dan gelen
PINGisteklerini onaylamak X-Signature-Ed25519veX-Signature-Timestampbaşlıklarıyla gelen imzayı doğrulamak
PING / PONG el sıkışması
URL'yi eklediğinizde Discord, type: 1 içeren bir PING payload'ını POST eder. Uç noktanız 200 durum koduyla, yine type: 1 olan bir PONG yanıtı döndürmelidir. Belge, PING yanıtında geçerli bir Content-Type başlığı gönderilmesi gerektiğini ayrıca belirtir; JSON yanıt için bu application/json olur.
Ed25519 imza doğrulaması
Her etkileşim isteği iki başlıkla gelir: imza olarak X-Signature-Ed25519, zaman damgası olarak X-Signature-Timestamp. Doğrulama için zaman damgası ile ham istek gövdesi (body) yan yana birleştirilir ve uygulamanızın Developer Portal'daki Public Key değeriyle Ed25519 imzası kontrol edilir. İmza geçersizse 401 döndürmelisiniz.
İmzayı kontrol ederken gövdeyi ham haliyle kullanmanız gerekir. JSON'u önce ayrıştırıp sonra yeniden metne çevirirseniz imza tutmaz. discord-interactions paketinin belgesi de bu yüzden etkileşim yolunda body-parser gibi gövdeyi değiştiren ara katmanları kullanmamanızı söyler. Express ile örnek:
const express = require('express');
const {
InteractionType, InteractionResponseType, verifyKeyMiddleware,
} = require('discord-interactions');
const app = express();
app.post('/interactions', verifyKeyMiddleware(process.env.DISCORD_PUBLIC_KEY), (req, res) => {
const interaction = req.body;
if (interaction.type === InteractionType.APPLICATION_COMMAND) {
return res.send({
type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE,
data: { content: 'Merhaba!' },
});
}
});
app.listen(8999);verifyKeyMiddleware imzayı doğrular ve PING isteklerine PONG ile kendisi yanıt verir. Python tarafında belge, nacl kütüphanesinin VerifyKey sınıfıyla f"{timestamp}{body}" metnini doğrulayan bir örnek verir.
Yanıt verme kuralları

HTTP modelinde etkileşime en kolay yanıt, gelen POST isteğine doğrudan JSON döndürmektir. Belgedeki önemli kurallar:
- İlk yanıtı etkileşimi aldıktan sonra 3 saniye içinde vermelisiniz; süre aşılırsa etkileşim token'ı geçersiz olur.
- Etkileşim token'ı 15 dakika geçerlidir; bu süre içinde takip (followup) mesajı gönderebilir veya ilk yanıtı düzenleyebilirsiniz.
- Uzun sürecek işler için
DEFERRED_CHANNEL_MESSAGE_WITH_SOURCE(tür 5) ile hemen onay verin, sonucu daha sonraPATCH /webhooks/<application_id>/<interaction_token>/messages/@originalile yazın. - Yanıtı ayrı bir
/interactions/<id>/<token>/callbackisteğiyle gönderirseniz, orijinal HTTP isteğine gövdesiz202dönmelisiniz.
| Tür | Ad | Kullanım |
|---|---|---|
| 1 | PONG | PING isteğini onaylamak |
| 4 | CHANNEL_MESSAGE_WITH_SOURCE | Mesajla yanıt vermek |
| 5 | DEFERRED_CHANNEL_MESSAGE_WITH_SOURCE | Şimdi onayla, sonra düzenle (kullanıcı yükleniyor durumu görür) |
3 saniye kuralı ve "Etkileşim başarısız oldu" hatası hakkında daha fazlası için bu yazımıza bakın. Butonlar ve modallar da aynı şekilde etkileşim olarak gelir; bkz. buton, select menu ve modal rehberi.
Cloudflare Workers ile HTTP botu: resmî eğitimin özeti
Discord'un kendi belgelerinde, bir slash komut uygulamasını Cloudflare Workers üzerinde barındıran bir eğitim bulunur. Belge, Workers'ı ücretsiz katmanı, basit geliştirme modeli ve sanal makine yönetimi gerektirmemesi nedeniyle uygun bir seçenek olarak tanıtır. Eğitimdeki örnek uygulamanın kodu GitHub'da discord/cloudflare-sample-app deposundadır. Ana adımlar:
1. Uygulamayı oluşturun ve davet edin
Developer Portal'da yeni bir uygulama oluşturun, Public Key ve Application ID değerlerini not edin, Bot sekmesinden token'ı alın. OAuth2 URL Generator'da bot ve applications.commands kapsamlarını seçip uygulamayı test sunucunuza ekleyin. Bu adımları davet linki rehberimizde ayrıntılı anlattık.
2. Gizli değerleri Worker'a tanımlayın
Eğitim, gizli değerleri Wrangler CLI ile Worker ortamına eklemeyi gösterir:
wrangler secret put DISCORD_TOKEN
wrangler secret put DISCORD_PUBLIC_KEY
wrangler secret put DISCORD_APPLICATION_ID3. Komutları kaydedin
Komutlar Worker içinde değil, bir kez yerelde çalıştırılan ayrı bir betikle kaydedilir. Betik, https://discord.com/api/v10/applications/{application_id}/commands adresine Authorization: Bot başlığıyla PUT isteği atar. Global komutların yayılması zaman alabildiği için geliştirme sırasında sunucuya özel komut kaydı da kullanılabilir. Ayrıntılar slash komut rehberinde.
4. Worker kodu: imzayı doğrula, yönlendir
Cloudflare Workers bir fetch fonksiyonu dışa aktarmanızı ister; her istek buradan girer. Aşağıdaki kod eğitimdeki yapının sadeleştirilmiş halidir. Güncel discord-interactions paketinde verifyKey asenkron bir fonksiyondur ve Promise<boolean> döndürür, bu yüzden await ile çağrılır.
import { InteractionType, InteractionResponseType, verifyKey } from 'discord-interactions';
const json = (data) =>
new Response(JSON.stringify(data), {
headers: { 'content-type': 'application/json;charset=UTF-8' },
});
export default {
async fetch(request, env) {
if (request.method !== 'POST') {
return new Response('Not found', { status: 404 });
}
const signature = request.headers.get('x-signature-ed25519');
const timestamp = request.headers.get('x-signature-timestamp');
const body = await request.text();
const gecerli = signature && timestamp &&
(await verifyKey(body, signature, timestamp, env.DISCORD_PUBLIC_KEY));
if (!gecerli) {
return new Response('Bad request signature.', { status: 401 });
}
const interaction = JSON.parse(body);
if (interaction.type === InteractionType.PING) {
return json({ type: InteractionResponseType.PONG });
}
if (interaction.type === InteractionType.APPLICATION_COMMAND &&
interaction.data.name === 'merhaba') {
return json({
type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE,
data: { content: 'Cloudflare Workers üzerinden merhaba!' },
});
}
return json({ error: 'Bilinmeyen komut' });
},
};5. Yerelde test edin, sonra yayınlayın
Eğitim, geliştirme sırasında yerel sunucuyu çalıştırıp ngrok ile geçici bir HTTPS tünel açmayı ve bu adresi Developer Portal'daki Interactions Endpoint URL alanına girmeyi önerir. Worker'ı yayınladıktan sonra bu alanı Worker adresinizle güncellemeniz gerekir. Eğitimdeki depo, main dalına yapılan değişiklikleri GitHub Actions ile otomatik yayınlayacak şekilde ayarlanmıştır.
Cloudflare hakkında genel bilgi için Cloudflare nedir yazımıza bakabilirsiniz.
Hangi modeli seçmelisiniz?
- Yalnızca slash komutları, butonlar ve modallarla çalışan bir yardımcı uygulama yapıyorsanız HTTP interactions sunucu yönetimini büyük ölçüde ortadan kaldırır.
- Mesajları okuyan, üye olaylarını dinleyen, moderasyon yapan veya ses kullanan bir bot yapıyorsanız gateway gerekir. Bu durumda botu 7/24 aktif tutma rehberimize bakın.
- Discord'un kullanıcıya yüklenebilen (user-install) uygulama eğitimi de etkileşimleri bir Interactions Endpoint URL ile alır; bkz. user install rehberi.
Sık Sorulan Sorular
Interactions Endpoint URL kaydedilmiyor. Neden?
Discord URL'yi kaydetmeden önce PING gönderir ve imza doğrulamasını dener. Uç noktanız PING'e type: 1 ile yanıt vermiyorsa, geçersiz imzaya 401 dönmüyorsa veya gövdeyi ham haliyle doğrulamıyorsa URL kaydedilmez. Public Key değerinin doğru uygulamaya ait olduğunu da kontrol edin.
Hem gateway hem HTTP kullanabilir miyim?
Belgeye göre etkileşimleri alma yolları birbirini dışlar: Interactions Endpoint URL tanımlıysa etkileşimler HTTP ile gelir. Gateway bağlantısını başka olaylar için yine kurabilirsiniz, ama etkileşimleri o bağlantı üzerinden beklemeyin.
HTTP botu discord.js ile yazılabilir mi?
discord.js'in Client sınıfı gateway odaklıdır. HTTP modeli için Discord'un örneklerinde discord-interactions paketi ve doğrudan REST çağrıları kullanılır. Kütüphane seçenekleri için kütüphane karşılaştırma yazımıza bakın.
Token'ı Worker koduna yazabilir miyim?
Hayır. Eğitimde olduğu gibi gizli değerleri Wrangler secret olarak tanımlayın ve kodda env üzerinden okuyun. Token güvenliği için bu yazıya bakın.
Marka adları sahiplerine aittir. Bu yazı bağımsız bir teknik rehberdir; adı geçen kuruluşlarla bayilik veya ortaklık ilişkisi bulunduğu anlamına gelmez.
İlgili içerikler: Slash komut oluşturma · Etkileşim başarısız oldu hatası · User install uygulamalar · Botu 7/24 aktif tutma · Cloudflare nedir · Discord webhook ve bot entegrasyonu