Webhook'lar
Firma ya da kişi oluşturulduğunda, sözleşme onaylandığında, tahsilat kaydedildiğinde ya da ziyaretçi kaydolduğunda efuar'ın sisteminize gönderdiği imzalı iletiler ve doğrulanmaları.
- Menüdeki yeri
- Ayarlar › API ve Webhook
- Gerekli yetki
- API anahtarlarını ve webhook'ları yönetme
- Paket özelliği
- API Erişimi
Ne işe yarar
Webhook, efuar'da bir olay olduğunda sizin sisteminize kendiliğinden gönderilen bir iletidir. Sisteminiz API'yi sürekli sorgulamak yerine, örneğin bir sözleşme onaylandığında ya da bir tahsilat kaydedildiğinde haberi kısa sürede alır. İletiyi alacak adrese uç denir; uçlar Ayarlar › API ve Webhook ekranının Webhook'lar sekmesinde tanımlanır.
Her ileti, ucun imza anahtarıyla imzalanır. Sisteminiz imzayı denetleyerek iletinin efuar'dan geldiğini ve yolda değişmediğini doğrular.
Olaylar
| Ekrandaki adı | Kod | Ne zaman gönderilir |
|---|---|---|
| Firma oluşturuldu | company.created |
Bir firma kaydı oluşturulduğunda, nasıl oluşturulduğundan bağımsız olarak. |
| Kişi oluşturuldu | contact.created |
Bir firmaya kişi eklendiğinde. |
| Sözleşme onaylandı | contract.approved |
Bir satış sözleşmesi onaylandığında; yeni sözleşme sürümünün onayı da bildirilir. Devir sözleşmeleri bildirilmez. |
| Tahsilat alındı | payment.received |
Yeni bir tahsilat kaydedildiğinde. |
| Ziyaretçi kaydoldu | visitor.registered |
Bir ziyaretçi bir fuara kaydolduğunda: online formla, davetiyeyle, girişte ya da dosyadan aktarımla. |
Yalnız bu beş olay bildirilir. Bir kaydın değişmesi, silinmesi ya da iptali için (örneğin tahsilatın iptali ya da kart ödemesinin iadesi) ileti gönderilmez.
Uç tanımlamak
- Ayarlar › API ve Webhook ekranında Webhook'lar sekmesini açın.
- Adres alanına iletileri alacak adresi yazın. Adres
https://ile başlayan tam bir adres olmalıdır (en fazla 500 karakter). efuar yalnız internete açık adreslere ileti gönderir; yerel ağ adresleri (ör.192.168.…) çalışmaz. - Açıklama alanına ucun hangi sisteme ait olduğunu yazın (isteğe bağlı, en fazla 200 karakter).
- Bildirilecek olaylar altında en az bir olay işaretleyin.
- Uç ekle düğmesine tıklayın.
- Sayfanın üstündeki kutuda gösterilen imza anahtarını kopyalayıp iletileri alacak sistemin ayarlarına yazın.
Anahtar
whsec_ile başlar ve bir daha gösterilmez. - Satırdaki Deneme gönder simgesiyle bir deneme iletisi gönderin ve ulaştığını görün.
Bir organizatörde en fazla 10 uç olabilir. Aynı olay birden çok uca bildirilebilir; her uç kendi iletisini alır.
İletinin biçimi
efuar, seçilen olay olunca ucun adresine JSON gövdeli bir POST isteği gönderir:
POST /fuar/webhook HTTP/1.1
Host: ornek.com
Content-Type: application/json; charset=utf-8
User-Agent: FairPlatform-Webhooks/1
X-FairPlatform-Event: contract.approved
X-FairPlatform-Delivery: 1234
X-FairPlatform-Signature: t=1791619200,v1=5f0c…
{"id":"6f1d…","type":"contract.approved","createdAt":"2026-10-10T08:00:00+00:00","data":{…}}
| Başlık | İçeriği |
|---|---|
X-FairPlatform-Event |
Olayın kodu; deneme iletisinde ping. |
X-FairPlatform-Delivery |
İletinin numarası; aynı iletinin yeniden denemelerinde değişmez. |
X-FairPlatform-Signature |
İmza: t= gönderim anı (Unix saniye), v1= imzanın kendisi. |
Gövdedeki alanlar:
id: olayın kimliği. Aynı olay birden çok uca aynıidile gider. Bir ileti ikinci kez gelirse onu bu kimlikle tanıyıp yok sayın.type: olayın kodu.createdAt: olayın kaydedildiği an (UTC).data: olayın konusu olan kaydın bilgileri. Tutarlar, ekranlarda gördüğünüz kayıttan gelir.
data alanları
| Olay | Alanlar |
|---|---|
company.created |
id, name, legalName, taxNumber, taxOffice, stage (Lead Potansiyel, Prospect Aday müşteri, Customer Müşteri), phone, email, website |
contact.created |
id, companyId, firstName, lastName, title, department, email, phone, mobile, isPrimary |
contract.approved |
id, number, revision, revisedFromId, companyId, companyName, fairId, participationId, contractDate, approvedAt, currency, subtotal, discountTotal, vatTotal, grandTotal |
payment.received |
id, number, companyId, fairId, date, method (Cash Nakit, BankTransfer Havale / EFT, CreditCard Kredi kartı, Cheque Çek, PromissoryNote Senet, Other Diğer), amount, currency, reference |
visitor.registered |
id, fairId, visitorId, firstName, lastName, email, companyName, source (Online Online kayıt, Invitation Davetiye, OnSite Girişte kayıt, Import Dosyadan aktarım), registeredAt |
fairId ve participationId, Organizatör API'si içindeki fuar ve
katılım numaralarıdır; ayrıntıyı oradan okuyabilirsiniz. Bir fuara bağlanmamış tahsilatta fairId boştur.
Sözleşmenin yeni sürümünde revision sürüm numarasını, revisedFromId yerini aldığı sözleşmeyi verir; bütün
sürümler aynı number değerini taşır. visitor.registered iletisinde id ziyaretçinin fuar kaydının, visitorId
kişinin numarasıdır. Günler (contractDate, date) yyyy-MM-dd, anlar UTC olarak yazılır.
{
"id": "6f1d2c3a-0b7e-4c1d-9a55-2f3e4d5c6b7a",
"type": "contract.approved",
"createdAt": "2026-10-10T08:00:00+00:00",
"data": {
"id": 3105,
"number": "SZL-2026-00042",
"revision": 2,
"revisedFromId": 3090,
"companyId": 881,
"companyName": "Örnek Ahşap A.Ş.",
"fairId": 229,
"participationId": 5120,
"contractDate": "2026-10-09",
"approvedAt": "2026-10-10T07:59:41+00:00",
"currency": "EUR",
"subtotal": 12000.00,
"discountTotal": 600.00,
"vatTotal": 2280.00,
"grandTotal": 13680.00
}
}
İmzayı doğrulamak
X-FairPlatform-Signaturebaşlığını virgülden bölün vetilev1değerlerini alın.tdeğerini, bir noktayı ve gövdeyi yan yana yazın:{t}.{gövde}. Gövdeyi geldiği haliyle kullanın; JSON'u ayrıştırıp yeniden yazarsanız imza tutmaz.- Bu metnin HMAC-SHA256 değerini ucun imza anahtarıyla hesaplayın ve küçük harfli onaltılık (hex) metne çevirin.
Anahtar, başındaki
whsec_dahil olduğu gibi kullanılır. - Sonuç
v1ile aynı değilse iletiyi reddedin. tçok eskiyse (örneğin 5 dakikadan eski) iletiyi yine reddedin; böylece yakalanıp sonradan yeniden gönderilen bir ileti kabul edilmez.
Her deneme gönderildiği anda yeniden imzalanır; yeniden denenen bir ileti yeni bir t taşır.
using System.Linq;
using System.Security.Cryptography;
using System.Text;
static bool IsValidSignature(string signatureHeader, string rawBody, string secret)
{
var parts = signatureHeader.Split(',')
.Select(part => part.Trim().Split('=', 2))
.Where(pair => pair.Length == 2)
.ToDictionary(pair => pair[0], pair => pair[1]);
if (!parts.TryGetValue("t", out var t) || !parts.TryGetValue("v1", out var v1)
|| !long.TryParse(t, out var sentAt)
|| Math.Abs(DateTimeOffset.UtcNow.ToUnixTimeSeconds() - sentAt) > 300)
{
return false;
}
var mac = HMACSHA256.HashData(Encoding.UTF8.GetBytes(secret), Encoding.UTF8.GetBytes($"{t}.{rawBody}"));
var expected = Convert.ToHexString(mac).ToLowerInvariant();
return CryptographicOperations.FixedTimeEquals(Encoding.ASCII.GetBytes(expected), Encoding.ASCII.GetBytes(v1));
}
const crypto = require('node:crypto');
function isValidSignature(signatureHeader, rawBody, secret) {
const parts = Object.fromEntries(signatureHeader.split(',').map((part) => part.trim().split('=')));
const sentAt = Number(parts.t);
if (!parts.v1 || !Number.isInteger(sentAt) || Math.abs(Date.now() / 1000 - sentAt) > 300) {
return false;
}
const expected = crypto.createHmac('sha256', secret).update(`${parts.t}.${rawBody}`, 'utf8').digest('hex');
const a = Buffer.from(expected);
const b = Buffer.from(parts.v1);
return a.length === b.length && crypto.timingSafeEqual(a, b);
}
İki örnekte de rawBody, isteğin gövdesinin geldiği haliyle okunmuş metnidir.
Yanıt, yeniden deneme ve duraklatma
- Yanıt verin: iletiyi aldığınızda 10 saniye içinde
2xxbir kodla (ör.200ya da204) yanıt verin. Uzun sürecek işleri yanıttan sonra yapın; 10 saniyede yanıt gelmezse ileti ulaşmamış sayılır. - Gönderim: iletiler dakikada bir, eskiden yeniye gönderilir (her seferde organizatör başına en çok 100 ileti). Değişiklik kaydedildiyse iletisi de kaydedilmiştir; kaydedilmeyen bir değişiklik için ileti yazılmaz.
- Yeniden deneme:
2xxalınamazsa ileti Yeniden denenecek olur ve en çok 6 kez denenir: ilk denemeden sonra yaklaşık 1 dakika, 5 dakika, 30 dakika, 2 saat ve 6 saat arayla. Altıncı deneme de başarısız olursa ileti Bırakıldı durumuna geçer. - Sıra ve tekrar: yeniden denenen bir ileti, kendisinden sonraki olayların iletilerinden sonra ulaşabilir; sıra
için
createdAtalanına bakın. Sisteminiz iletiyi işlediği halde yanıtı efuar'a zamanında ulaşmadıysa aynı ileti yeniden gelir;idile tanıyıp yok sayın. - Duraklatma: bir uca art arda 20 deneme başarısız olursa uç Duraklatıldı durumuna geçer; ulaşan her ileti bu sayacı sıfırlar. Sorunu giderdikten sonra ucu satırdaki Aç simgesiyle yeniden açın.
- Kapalı uç: kapalı ya da duraklatılmış bir uç için yeni ileti yazılmaz; uç yeniden açıldığında arada olan olaylar sonradan gönderilmez. Uç kapalıyken sırası gelen iletiler Bırakıldı olur.
- Paket: paketinizde API Erişimi kapanırsa ya da aboneliğiniz geçerliliğini yitirirse sırası gelen iletiler gönderilmez, Bırakıldı olur.
İpucu: Deneme gönder, kapalı ya da duraklatılmış bir uca da gönderilir ve duraklatma sayacına eklenmez. Ucu yeniden açmadan önce alıcının düzeldiğini bununla denetleyebilirsiniz.
Son iletiler ve yeniden gönderme
Sekmenin altındaki Son iletiler tablosu gönderilen son 50 iletiyi gösterir: Zaman, Olay, Uç, Durum ve Yanıt (alıcının HTTP kodu ya da "Alıcı 10 saniye içinde yanıt vermedi." gibi bir hata). Birden çok denenen iletide deneme sayısı da yazar. Durumlar: Sırada, Ulaştı, Yeniden denenecek ve Bırakıldı.
Yeniden denenecek ya da Bırakıldı durumundaki bir iletinin satırındaki Yeniden gönder düğmesi, iletiyi deneme sayısını sıfırlayarak hemen sıraya alır; ileti bir sonraki gönderimde, yaklaşık bir dakika içinde gider. Ulaşmış iletiler ve deneme iletileri yeniden gönderilmez.
Günlükte ulaşan iletiler 30 gün, bırakılan iletiler 90 gün tutulur; sonra silinir.
Deneme iletisi
Deneme gönder, uca hemen bir ping iletisi gönderir ve sonucu sayfanın üstünde söyler: "Deneme iletisi ulaştı
(HTTP 200)." ya da "Deneme iletisi ulaşmadı: …". Deneme bir kez gönderilir, yeniden denenmez ve Son iletiler
tablosunda Deneme olarak görünür. Gövdesi diğer iletilerle aynı biçimdedir ve aynı anahtarla imzalanır:
{"id":"…","type":"ping","createdAt":"2026-10-10T08:00:00+00:00","data":{"message":"FairPlatform webhook test","organization":"Örnek Fuarcılık A.Ş."}}
İmza anahtarını yenilemek ve ucu değiştirmek
- İmza anahtarını yenile, onay sorusundan sonra yeni bir anahtar üretir ve bir kez gösterir. Eski anahtar hemen
geçersiz olur: bundan sonraki her gönderim, sırada bekleyen iletiler dahil, yeni anahtarla imzalanır. Geçiş
sırasında imzası tutmayan iletiyi
2xxdışı bir kodla reddederseniz ileti yeniden denenir ve yeni anahtarı sisteminize yazdıktan sonra ulaşır. - Düzenle ile adresi, açıklamayı ve olayları değiştirebilirsiniz. Sırada bekleyen iletiler de yeni adrese gider; olay seçimi yalnız bundan sonraki olayları etkiler.
- Sil ucu kaldırır; sırada bekleyen iletileri gönderilmez.
Kişisel veriler
contact.created ve visitor.registered iletileri ad, e-posta ve telefon gibi kişisel veriler taşır; bu olaylar
için yalnız kendi sisteminize ait bir adres tanımlayın. Bir kişinin ya da ziyaretçinin kişisel verileri efuar'da
silindiğinde onunla ilgili iletiler günlükten silinir; henüz gönderilmemiş olanlar hiç gönderilmez.
Önemli: Daha önce ulaşmış iletiler sizin sisteminizde kalır. Bir silme talebini kendi sisteminizde ayrıca karşılayın; efuar silme için ileti göndermez.