Rehberler
Webhook'lar
Bir şey olduğunda Ödecik, tanımladığın HTTPS adresine imzalı bir JSON isteği gönderir. Yoklama yapmana gerek kalmaz.
Endpoint tanımlama
Panelde Geliştirici → Webhook'lar bölümünden ya da POST /webhooks ile ekleyebilirsin. Oluşturma yanıtındaki secret (whsec_…) yalnızca bir kez gösterilir; imza doğrulamada kullanılır.
- Adres
https://olmalı ve herkese açık bir sunucuya çözülmeli. IP adresi,localhostve özel ağ adresleri kabul edilmez. - Yönlendirmeler (redirect) takip edilmez.
- Yanıtın 6 saniye içinde
2xxdönmeli; işi kuyruğa alıp hemen yanıtla.
Olaylar
| Olay | Ne zaman |
|---|---|
| order.created | Sipariş oluştu (ödeme onaylandığı anda order.paid ile birlikte gelir). |
| order.paid | Ödeme onaylandı; sipariş teslime hazır. |
| order.shipped | Kargo bilgisi girildi. |
| order.refunded | Sipariş iade edildi. |
| payout.completed | Bakiye talebin IBAN'a aktarıldı. |
İstek biçimi
POST /odecik-webhook HTTP/1.1
Content-Type: application/json
User-Agent: Odecik-Webhooks/1.0
X-Odecik-Event: order.paid
X-Odecik-Delivery: evt_3f9a1c2b7d4e5f60a1b2
X-Odecik-Signature: t=1768473000,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd{
"id": "evt_3f9a1c2b7d4e5f60a1b2",
"event": "order.paid",
"createdAt": "2026-01-15T10:30:00.000Z",
"data": {
"orderNo": "ODC-M2K9X1-A4F2",
"status": "PAID",
"totalKurus": 11920,
"netKurus": 11503,
"buyerEmail": "ayse@example.com",
"items": [
{ "name": "Premium şablon paketi", "variant": null, "quantity": 1, "priceKurus": 14900 }
]
}
}{
"orderNo": "ODC-M2K9X1-A4F2",
"status": "SHIPPED",
"carrier": "yurtici",
"carrierName": "Yurtiçi Kargo",
"trackingNo": "123456789012",
"trackingUrl": "https://www.yurticikargo.com/…",
"buyerEmail": "ayse@example.com"
}{
"orderNo": "ODC-M2K9X1-A4F2",
"status": "REFUNDED",
"totalKurus": 11920,
"buyerEmail": "ayse@example.com"
}{
"payoutId": "cm9x2k1a30077",
"amountKurus": 250000,
"iban": "TR330006100519786457841326"
}İmza doğrulama
Her istek X-Odecik-Signature: t=ZAMAN,v1=İMZA başlığıyla imzalanır. İmza, ZAMAN + "." + ham_gövde metninin secret ile HMAC-SHA256 hesaplanıp hex yazılmış halidir.
import crypto from "node:crypto";
// Express: app.post("/odecik-webhook", express.raw({ type: "application/json" }), handler)
export function verifyOdecik(rawBody, header, secret, toleranceSec = 300) {
const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));
const t = Number(parts.t);
if (!t || Math.abs(Date.now() / 1000 - t) > toleranceSec) return false;
const expected = crypto
.createHmac("sha256", secret)
.update(`${t}.${rawBody}`)
.digest("hex");
const a = Buffer.from(expected);
const b = Buffer.from(parts.v1 ?? "");
return a.length === b.length && crypto.timingSafeEqual(a, b);
}Yeniden deneme
2xx dışında yanıt veya zaman aşımı olursa teslimat 4 kez denenir: hemen, 5 saniye, 30 saniye ve 3 dakika sonra. 429 dışındaki 4xx yanıtlar kalıcı ret sayılır ve yeniden denenmez. Her deneme aynı id'yi taşır — bu değeri idempotentlik anahtarı olarak kullan ve aynı olayı iki kez işleme.
Teslimat geçmişini panelden ya da GET /webhooks/:id/deliveries ile görebilir, POST /webhooks/:id/test ile örnek olay gönderebilirsin.
Discord ve Slack
Endpoint adresi bir Discord veya Slack webhook adresiyse Ödecik olayı o platformun biçiminde, imzasız ve okunaklı bir mesaj olarak gönderir. Ayrıca bir sunucu yazmana gerek yoktur.
- Discord: kanal ayarları → Entegrasyonlar → Webhook'lar → yeni webhook → URL'yi kopyala.
- Slack: Incoming Webhooks uygulamasını ekle → kanal seç → URL'yi kopyala.
- Panelde Geliştirici → Discord veya Slack kanalına bildirim alanına yapıştır.
curl https://odecik.com/api/v1/webhooks \
-X POST \
-H "Authorization: Bearer $ODECIK_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://discord.com/api/webhooks/123456789/abcdef",
"events": ["order.paid", "order.shipped", "order.refunded"]
}'