Webhook Olayları
Banka Hesapları ürünü iki olay ailesi gönderir:
| Olay | Ne zaman |
|---|---|
bank_account.transaction.received | Bağlı hesaplarınızda yeni bir hareket okunduğunda. |
bank_transfer.created, bank_transfer.completed, bank_transfer.failed, bank_transfer.returned | Bir para transferi oluşturulduğunda ve sonuçlandığında. → Transfer olayları |
Teslimat, imza doğrulama ve yeniden deneme bütün ürünlerde aynıdır: Webhook'lar. Bu sayfanın ilk bölümü hareket olayını anlatır.
Ne zaman gönderilir
| Durum | Olay |
|---|---|
Olağan okumada ilk kez görülen hareket — gelen (CREDIT) ya da giden (DEBIT) | Gönderilir, hareket başına bir olay |
| Bağlantı ilk kurulduğunda geriye dönük okunan geçmiş hareketler | Gönderilmez |
| Geçmiş verinin yeniden okunmasında bulunan hareketler | Gönderilmez |
| Daha önce okunmuş bir hareketin bankadan yeniden gelmesi | Gönderilmez; aynı hareket ikinci kez kaydedilmez |
| Doğrulama için bekletilen, sonradan listede görünür hâle gelen hareket | Gönderilmez |
Olay gönderilmeyen hareketler de Hareketler ucunda görünür. Hareketlerin tamamını almak için webhook'u liste ucuyla birlikte kullanın (aşağıya bakın).
Örnek teslimat
{
"id": "00000000-0000-0000-0000-00000000e001",
"type": "bank_account.transaction.received",
"organizationId": "00000000-0000-0000-0000-00000000000a",
"productCode": "BANK_CONNECT",
"environment": "LIVE",
"eventVersion": 1,
"schemaVersion": "v1",
"createdAt": "2026-01-01T07:05:01.000Z",
"data": {
"transactionId": "00000000-0000-0000-0000-000000001000",
"accountId": "00000000-0000-0000-0000-000000000100",
"connectionId": "00000000-0000-0000-0000-000000000010",
"bankEftCode": "0000",
"bankName": "ÖRNEK BANKA",
"direction": "CREDIT",
"amountMinor": 150000,
"currency": "TRY",
"bookedAt": "2026-01-01T07:00:00.000Z",
"valueAt": null,
"receivedAt": "2026-01-01T07:05:00.000Z",
"canonicalType": "TRANSFER_IN",
"description": "ORNEK ACIKLAMA",
"counterpartyNameMasked": "Ö**** A****",
"counterpartyIbanMasked": "TR00 **** **** **** **** **00 00",
"receiptNo": null
}
}Zarf
| Alan | Anlamı |
|---|---|
id | Olay kimliği; x-lunixi-event-id başlığıyla aynı değer. |
type | bank_account.transaction.received |
organizationId | Organizasyonunuz. |
productCode | BANK_CONNECT |
environment | TEST ya da LIVE. |
eventVersion | Olayın sürümü; bugün 1. |
schemaVersion | data şemasının sürümü; bugün v1. |
createdAt | Olayın oluşturulduğu an. |
data | Hareketin alanları; aşağıya bakın. |
Zarfta bu tabloda olmayan alanlar da bulunabilir; kodunuzu yalnız burada belgelenen alanlara dayandırın.
data
| Alan | Tip | Açıklama |
|---|---|---|
transactionId | string (UUID) | Hareketin kimliği; Hareketler ucundaki transactionId ile aynı. |
accountId | string (UUID) | Hareketin ait olduğu hesap. |
connectionId | string (UUID) | Hesabın bağlantısı. |
bankEftCode | string | Bankanın EFT kodu. |
bankName | string | Bankanın adı. |
direction | string | CREDIT (giren) ya da DEBIT (çıkan). |
amountMinor | integer | Tutar, minor birimde; her zaman sıfır ya da pozitif. |
currency | string | Para birimi (ISO 4217). |
bookedAt | string | İşlem tarihi. |
valueAt | string | null | Valör tarihi. |
receivedAt | string | Hareketin Lunixi'de kaydedildiği an. |
canonicalType | string | Bankadan bağımsız hareket tipi. → Hareket tipleri |
description | string | null | Bankanın yazdığı açıklama, maskelenmeden. |
counterpartyNameMasked | string | null | Karşı tarafın maskeli adı. |
counterpartyIbanMasked | string | null | Karşı tarafın maskeli IBAN'ı. |
receiptNo | string | null | Dekont numarası. |
API yanıtlarından farklı olarak webhook'ta değeri olmayan alanlar null olarak gelir; alan yine de gövdede bulunur. Hem API'yi hem webhook'u işleyen kodunuz iki durumu da karşılamalıdır.
Abonelik
Olayı almak için Banka Bağlantıları ürünü için bir webhook endpoint'i oluşturun:
| Alan | Değer |
|---|---|
productCode | BANK_CONNECT |
eventTypes | ["bank_account.transaction.received"] ya da bu ailedeki bütün olaylar için ["bank_account.*"]. Transfer olayları için ["bank_transfer.*"] ekleyin. |
environment | TEST endpoint test ortamındaki hareketleri, LIVE endpoint canlı ortamdaki hareketleri alır. |
Endpoint oluşturma, imza secret'ı ve teslimat geçmişi: Webhook Kurulumu.
İmza, yeniden deneme ve tekilleştirme
İmzayı her teslimatta doğrulayın; imza biçimi ve yeniden deneme politikası bütün ürünlerde aynıdır: Webhook'lar.
Teslimat en az bir kez yapılır; aynı olay birden çok kez gelebilir. Olayı x-lunixi-event-id ile idempotent işleyin. Aynı hareket için olay kimliği her zaman aynıdır; ayrıca data.transactionId ile de tekilleştirebilirsiniz.
PHP ile işleme
PHP SDK imzayı doğrular ve data alanlarını tipli olarak verir:
use Lunixi\Sdk\BankConnect\BankAccountTransactionReceived;
use Lunixi\Sdk\BankConnect\BankConnectEvents;
use Lunixi\Sdk\Exception\WebhookVerificationException;
$rawBody = file_get_contents('php://input') ?: '';
try {
$event = $lunixi->webhooks()->verify($rawBody, getallheaders() ?: [], getenv('LUNIXI_WEBHOOK_SECRET'));
} catch (WebhookVerificationException $e) {
http_response_code(400);
return;
}
if ($event->type() === BankConnectEvents::TRANSACTION_RECEIVED) {
$transaction = BankAccountTransactionReceived::fromEvent($event);
// $event->id() ile tekilleştirip kaydedin; ör. $transaction->transactionId(),
// $transaction->direction(), $transaction->amountMinor(), $transaction->description()
}
http_response_code(200);BankConnectEvents::ALL_EVENTS değeri (bank_account.*) endpoint aboneliğinde kullanılabilir.
Webhook'u liste ucuyla birlikte kullanma
Webhook yeni hareketi hızlı öğrenmenin yoludur; tek kaynak değildir. Endpoint'iniz bir süre erişilemezse, ya da hareket olay üretmeyen bir yoldan geldiyse (ör. ilk geriye dönük okuma), hareketi Hareketler ucundan tamamlayın:
transactionId ile kaydedin, liste ucunu düzenli aralıklarla ilk sayfadan okuyup kaydetmediklerinizi ekleyin ve iki kaynaktan gelen aynı hareketi transactionId ile tekilleştirin.Transfer olayları
Para transferi oluşturulduğunda ve sonuçlandığında Lunixi endpoint'inize aşağıdaki olayları gönderir. Döviz işlemleri için webhook gönderilmez; sonucu Döviz İşlemi ucundan sorgulayın.
| Olay | Ne zaman | data.status |
|---|---|---|
bank_transfer.created | Transfer oluşturulduğunda. API'den oluşturulan transfer SUBMITTED, panelden başlatılan ve doğrulama kodu bekleyen transfer PENDING_OTP durumundadır. | SUBMITTED ya da PENDING_OTP |
bank_transfer.completed | Banka transferi tamamladığında. | COMPLETED |
bank_transfer.failed | Transfer gerçekleşmediğinde; sebep data.failureCode alanında. | FAILED |
bank_transfer.returned | Tamamlanan transfer alıcı bankadan iade edildiğinde. | RETURNED |
- Her transfer için her olay en çok bir kez üretilir; yeniden teslimatlarda olay kimliği aynıdır.
- Panelden başlatılıp doğrulama kodu süresinde onaylanmayan ya da iptal edilen transfer
CANCELEDolur; bunun için ayrı olay gönderilmez. Durumu transfer ucundan okuyun. - Sonucu bankadan doğrulanamayan transfer (
outcomeUnknown) için olay, sonuç kesinleştiğinde gönderilir. - Olaylar sırasız gelebilir (ör.
completed,created'dan önce). Kodunuzu olayın sırasına değildata.statusalanına ve transferin güncel durumuna göre yazın.
Örnek teslimat
{
"id": "00000000-0000-0000-0000-00000000e101",
"type": "bank_transfer.completed",
"organizationId": "00000000-0000-0000-0000-00000000000a",
"productCode": "BANK_CONNECT",
"environment": "LIVE",
"eventVersion": 1,
"schemaVersion": "v1",
"createdAt": "2026-01-01T07:00:21.000Z",
"data": {
"transferId": "00000000-0000-0000-0000-000000002000",
"connectionId": "00000000-0000-0000-0000-000000000010",
"accountId": "00000000-0000-0000-0000-000000000100",
"bankEftCode": "0000",
"bankName": "ÖRNEK BANKA",
"status": "COMPLETED",
"rail": "FAST",
"amountMinor": 150075,
"currency": "TRY",
"receiverIbanMasked": "TR00 **** **** **** **** **00 00",
"receiverNameMasked": "Ö**** T****** A.Ş.",
"paymentPurpose": null,
"description": "Fatura 2026-0042",
"failureCode": null,
"idempotencyKey": "payout-2026-0042",
"createdAt": "2026-01-01T07:00:00.000Z",
"completedAt": "2026-01-01T07:00:20.000Z",
"failedAt": null,
"returnedAt": null
}
}Zarf alanları hareket olayıyla aynıdır; type olayın adını taşır.
Transfer olayının data alanları
| Alan | Tip | Açıklama |
|---|---|---|
transferId | string (UUID) | Transferin kimliği; transfer ucundaki id ile aynı. |
connectionId | string (UUID) | Hesabın bağlantısı. |
accountId | string (UUID) | Paranın çıktığı hesap. |
bankEftCode | string | Bankanın EFT kodu. |
bankName | string | Bankanın adı. |
status | string | Olay anındaki transfer durumu. |
rail | string | null | Bankanın seçtiği yol (INTERNAL, INTRABANK, FAST, EFT, UNKNOWN). |
amountMinor | integer | Tutar, minor birimde. |
currency | string | Para birimi (ISO 4217). |
receiverIbanMasked | string | Alıcının maskeli IBAN'ı. |
receiverNameMasked | string | Alıcının maskeli adı. |
paymentPurpose | string | null | Ödeme amacı kodu. |
description | string | null | Transfer açıklaması. |
failureCode | string | null | failed ve returned olaylarında sebep kodu. → Transfer sonuç kodları |
idempotencyKey | string | Transferin Idempotency-Key'i; kendi ödeme kaydınızla eşleştirmek için kullanın. |
createdAt | string | Transferin oluşturulma zamanı. |
completedAt | string | null | Tamamlanma zamanı. |
failedAt | string | null | Başarısız olma zamanı. |
returnedAt | string | null | İade zamanı. |
Değeri olmayan alanlar null olarak gelir.
PHP ile işleme
use Lunixi\Sdk\BankConnect\BankTransferEvent;
use Lunixi\Sdk\BankConnect\BankTransferEvents;
$event = $lunixi->webhooks()->verify($rawBody, getallheaders() ?: [], getenv('LUNIXI_WEBHOOK_SECRET'));
if (in_array($event->type(), BankTransferEvents::ALL, true)) {
$transfer = BankTransferEvent::fromEvent($event);
// $event->id() ile tekilleştirin; $transfer->idempotencyKey() ile kendi ödeme kaydınızı bulun.
if ($event->type() === BankTransferEvents::FAILED) {
// $transfer->failureCode()
}
}BankTransferEvents::ALL_EVENTS değeri (bank_transfer.*) endpoint aboneliğinde kullanılabilir. PHP SDK 0.22.0 ve üstü gerekir.