> ## Documentation Index
> Fetch the complete documentation index at: https://docs.wappfy.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Webhook'lar

> Mesajlar, teslimat olayları ve örnek durum değişiklikleri için gerçek zamanlı bildirimler alın.

# Webhook'lar

Webhook'lar, WhatsApp \u00f6rneklerinizde olaylar ger\u00e7ekle\u015fti\u011finde ger\u00e7ek zamanl\u0131 HTTP geri \u00e7a\u011fr\u0131lar\u0131 alman\u0131z\u0131 sa\u011flar. API'yi s\u00fcrekli sorgulamak yerine, Wappfy olaylar\u0131 ger\u00e7ekle\u015ftik\u00e7e sunucunuza iletir.

## Desteklenen Olaylar

Wappfy 12 webhook olay t\u00fcr\u00fcn\u00fc destekler:

<AccordionGroup>
  <Accordion title="Mesaj Olaylar\u0131">
    | Olay                | A\u00e7\u0131klama                                                                                       |
    | ------------------- | -------------------------------------------------------------------------------------------------------- |
    | `message.received`  | Yeni bir gelen mesaj al\u0131nd\u0131.                                                                   |
    | `message.sent`      | Giden bir mesaj ba\u015far\u0131yla g\u00f6nderildi.                                                     |
    | `message.delivered` | G\u00f6nderilen mesaj al\u0131c\u0131n\u0131n cihaz\u0131na teslim edildi (\u00e7ift onay i\u015fareti). |
    | `message.read`      | G\u00f6nderilen mesaj al\u0131c\u0131 taraf\u0131ndan okundu (mavi onay i\u015faretleri).                |
    | `message.failed`    | Giden bir mesaj g\u00f6nderilemedi.                                                                      |
    | `message.reaction`  | Birisi bir mesaja emoji ile tepki verdi.                                                                 |
  </Accordion>

  <Accordion title="\u00d6rnek Olaylar\u0131">
    | Olay                    | A\u00e7\u0131klama                                                |
    | ----------------------- | ----------------------------------------------------------------- |
    | `instance.connected`    | Bir \u00f6rnek WhatsApp'a ba\u015far\u0131yla ba\u011fland\u0131. |
    | `instance.disconnected` | Bir \u00f6rne\u011fin WhatsApp ba\u011flant\u0131s\u0131 kesildi. |
    | `instance.qr`           | Tarama i\u00e7in yeni bir QR kod mevcut.                          |
  </Accordion>

  <Accordion title="Grup ve Ki\u015fi Olaylar\u0131">
    | Olay              | A\u00e7\u0131klama                                                        |
    | ----------------- | ------------------------------------------------------------------------- |
    | `group.joined`    | Bir kat\u0131l\u0131mc\u0131 gruba kat\u0131ld\u0131 (bot kendisi dahil). |
    | `group.left`      | Bir kat\u0131l\u0131mc\u0131 gruptan ayr\u0131ld\u0131.                   |
    | `contact.created` | Yeni bir ki\u015fi kaydedildi veya alg\u0131land\u0131.                   |
  </Accordion>
</AccordionGroup>

***

## Webhook Olu\u015fturma

Olaylar\u0131 almaya ba\u015flamak i\u00e7in bir webhook ucu noktas\u0131 kaydedin.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.wappfy.io/api/webhooks \
    -H "X-Api-Key: YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "url": "https://your-server.com/webhooks/wappfy",
      "events": ["message.received", "message.sent", "message.delivered"],
      "instance_id": "inst_abc123",
      "secret": "whsec_my_signing_secret",
      "retry_count": 3,
      "timeout_ms": 10000
    }'
  ```

  ```javascript Node.js theme={null}
  const response = await fetch("https://api.wappfy.io/api/webhooks", {
    method: "POST",
    headers: {
      "X-Api-Key": "YOUR_API_KEY",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      url: "https://your-server.com/webhooks/wappfy",
      events: ["message.received", "message.sent", "message.delivered"],
      instance_id: "inst_abc123",
      secret: "whsec_my_signing_secret",
      retry_count: 3,
      timeout_ms: 10000,
    }),
  });

  const webhook = await response.json();
  console.log(webhook.data.id);
  ```
</CodeGroup>

**Yan\u0131t:**

```json theme={null}
{
  "data": {
    "id": "wh_xyz789",
    "url": "https://your-server.com/webhooks/wappfy",
    "events": ["message.received", "message.sent", "message.delivered"],
    "instance_id": "inst_abc123",
    "is_active": true,
    "retry_count": 3,
    "timeout_ms": 10000,
    "created_at": "2026-02-10T12:00:00Z"
  }
}
```

### Yap\u0131land\u0131rma Se\u00e7enekleri

| Alan          | T\u00fcr  | Varsay\u0131lan | A\u00e7\u0131klama                                                                                                               |
| ------------- | --------- | --------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `url`         | string    | **zorunlu**     | Webhook POST isteklerini alacak HTTPS URL'si.                                                                                    |
| `events`      | string\[] | **zorunlu**     | Abone olunacak olay t\u00fcrleri dizisi.                                                                                         |
| `instance_id` | string    | `null`          | Webhook'\u0131 belirli bir \u00f6rnekle s\u0131n\u0131rlay\u0131n. Null ise t\u00fcm \u00f6rneklerden olaylar\u0131 al\u0131r.   |
| `secret`      | string    | `null`          | Veri y\u00fck\u00fc do\u011frulamas\u0131 i\u00e7in HMAC imzalar\u0131 olu\u015fturmak \u00fczere kullan\u0131lan gizli anahtar. |
| `retry_count` | number    | `3`             | Teslimat ba\u015far\u0131s\u0131zl\u0131\u011f\u0131nda yeniden deneme say\u0131s\u0131 (0-5).                                   |
| `timeout_ms`  | number    | `10000`         | Milisaniye cinsinden istek zaman a\u015f\u0131m\u0131 (1000-30000).                                                              |

<Note>
  `instance_id` alan\u0131 iste\u011fe ba\u011fl\u0131d\u0131r. Belirtilmezse webhook, hesab\u0131n\u0131zdaki **t\u00fcm** \u00f6rneklerden olaylar\u0131 alacakt\u0131r.
</Note>

***

## Webhook'lar\u0131 Listeleme

```bash theme={null}
curl https://api.wappfy.io/api/webhooks \
  -H "X-Api-Key: YOUR_API_KEY"
```

**Yan\u0131t:**

```json theme={null}
{
  "data": [
    {
      "id": "wh_xyz789",
      "url": "https://your-server.com/webhooks/wappfy",
      "events": ["message.received", "message.sent", "message.delivered"],
      "instance_id": "inst_abc123",
      "is_active": true,
      "retry_count": 3,
      "timeout_ms": 10000
    }
  ]
}
```

***

## Webhook G\u00fcncelleme

Mevcut bir webhook'\u0131n URL'sini, olaylar\u0131n\u0131 veya yap\u0131land\u0131rmas\u0131n\u0131 g\u00fcncelleyin.

```bash theme={null}
curl -X PATCH https://api.wappfy.io/api/webhooks/wh_xyz789 \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "events": ["message.received", "message.sent", "message.delivered", "message.read"],
    "is_active": true
  }'
```

***

## Webhook Silme

```bash theme={null}
curl -X DELETE https://api.wappfy.io/api/webhooks/wh_xyz789 \
  -H "X-Api-Key: YOUR_API_KEY"
```

***

## Teslimat Veri Y\u00fck\u00fc Format\u0131

Bir olay ger\u00e7ekle\u015fti\u011finde, Wappfy webhook URL'nize a\u015fa\u011f\u0131daki yap\u0131da bir POST iste\u011fi g\u00f6nderir:

```json theme={null}
{
  "id": "dlv_abc123def456",
  "event": "message.received",
  "instance_id": "inst_abc123",
  "timestamp": "2026-02-10T14:30:00Z",
  "data": {
    "message_id": "BAE5F2C4D3B2A1",
    "chat_id": "5511999998888@s.whatsapp.net",
    "from": "5511999998888@s.whatsapp.net",
    "type": "text",
    "text": "Hello!",
    "timestamp": "2026-02-10T14:30:00Z"
  }
}
```

### Veri Y\u00fck\u00fc Alanlar\u0131

| Alan          | A\u00e7\u0131klama                                                                                             |
| ------------- | -------------------------------------------------------------------------------------------------------------- |
| `id`          | Benzersiz teslimat kimli\u011fi. Tekrar\u0131 \u00f6nleme i\u00e7in kullan\u0131n.                             |
| `event`       | Bu teslimati tetikleyen olay t\u00fcr\u00fc.                                                                   |
| `instance_id` | Olay\u0131 \u00fcreten \u00f6rnek.                                                                             |
| `timestamp`   | Olay\u0131n ger\u00e7ekle\u015fti\u011fi ISO 8601 zaman damgas\u0131.                                          |
| `data`        | Olaya \u00f6zel veri y\u00fck\u00fc. \u0130\u00e7eri\u011fi olay t\u00fcr\u00fcne g\u00f6re de\u011fi\u015fir. |

***

## HMAC \u0130mza Do\u011frulamas\u0131

Webhook olu\u015ftururken bir `secret` sa\u011flarsan\u0131z, her teslimat istek g\u00f6vdesinin HMAC-SHA256 imzas\u0131n\u0131 i\u00e7eren bir `X-Wappfy-Signature` ba\u015fl\u0131\u011f\u0131 i\u00e7erecektir.

\u0130ste\u011fin Wappfy'den geldi\u011finden ve de\u011fi\u015ftirilmedi\u011finden emin olmak i\u00e7in **bu imzay\u0131 her zaman do\u011frulay\u0131n**.

### Do\u011frulama \u00d6rnekleri

<CodeGroup>
  ```javascript Node.js (Express) theme={null}
  const crypto = require("crypto");

  function verifyWebhookSignature(req, secret) {
    const signature = req.headers["x-wappfy-signature"];
    if (!signature) return false;

    const expectedSignature = crypto
      .createHmac("sha256", secret)
      .update(JSON.stringify(req.body))
      .digest("hex");

    return crypto.timingSafeEqual(
      Buffer.from(signature),
      Buffer.from(expectedSignature)
    );
  }

  // Express middleware
  app.post("/webhooks/wappfy", (req, res) => {
    const isValid = verifyWebhookSignature(req, "whsec_my_signing_secret");

    if (!isValid) {
      return res.status(401).json({ error: "Invalid signature" });
    }

    const { event, data } = req.body;
    console.log(`Received event: ${event}`, data);

    // Always respond with 200 quickly to prevent retries
    res.status(200).json({ received: true });
  });
  ```

  ```python Python (Flask) theme={null}
  import hmac
  import hashlib
  import json
  from flask import Flask, request, jsonify

  app = Flask(__name__)
  WEBHOOK_SECRET = "whsec_my_signing_secret"

  def verify_signature(payload, signature):
      expected = hmac.new(
          WEBHOOK_SECRET.encode(),
          json.dumps(payload).encode(),
          hashlib.sha256
      ).hexdigest()
      return hmac.compare_digest(expected, signature)

  @app.route("/webhooks/wappfy", methods=["POST"])
  def handle_webhook():
      signature = request.headers.get("X-Wappfy-Signature", "")
      if not verify_signature(request.json, signature):
          return jsonify({"error": "Invalid signature"}), 401

      event = request.json["event"]
      data = request.json["data"]
      print(f"Received event: {event}", data)

      return jsonify({"received": True}), 200
  ```
</CodeGroup>

<Warning>
  Zamanlama sald\u0131r\u0131lar\u0131n\u0131 \u00f6nlemek i\u00e7in imzalar\u0131 do\u011frularken her zaman sabit zamanl\u0131 kar\u015f\u0131la\u015ft\u0131rma (`timingSafeEqual` veya `hmac.compare_digest` gibi) kullan\u0131n.
</Warning>

***

## Yeniden Deneme Davran\u0131\u015f\u0131

Sunucunuz yap\u0131land\u0131r\u0131lm\u0131\u015f `timeout_ms` s\u00fcresi i\u00e7inde `2xx` durum kodu ile yan\u0131t vermezse, Wappfy teslimati yeniden dener.

| Deneme            | Gecikme   |
| ----------------- | --------- |
| 1. yeniden deneme | 10 saniye |
| 2. yeniden deneme | 60 saniye |
| 3. yeniden deneme | 5 dakika  |
| 4. yeniden deneme | 30 dakika |
| 5. yeniden deneme | 2 saat    |

<Note>
  `2xx` yan\u0131t al\u0131nd\u0131\u011f\u0131nda veya `retry_count` t\u00fckendi\u011finde yeniden denemeler durur. Varsay\u0131lan yeniden deneme say\u0131s\u0131 3't\u00fcr.
</Note>

### Teslimat Ge\u00e7mi\u015fini G\u00f6r\u00fcnt\u00fcleme

Ge\u00e7mi\u015f teslimat denemelerini ve sonu\u00e7lar\u0131n\u0131 g\u00f6rmek i\u00e7in webhook teslimat g\u00fcnl\u00fc\u011f\u00fcn\u00fc kontrol edin.

```bash theme={null}
curl https://api.wappfy.io/api/webhooks/wh_xyz789/deliveries \
  -H "X-Api-Key: YOUR_API_KEY"
```

**Yan\u0131t:**

```json theme={null}
{
  "data": [
    {
      "id": "dlv_abc123def456",
      "event": "message.received",
      "status": "delivered",
      "http_status": 200,
      "attempts": 1,
      "created_at": "2026-02-10T14:30:00Z",
      "delivered_at": "2026-02-10T14:30:01Z"
    },
    {
      "id": "dlv_ghi789jkl012",
      "event": "message.sent",
      "status": "failed",
      "http_status": 500,
      "attempts": 3,
      "created_at": "2026-02-10T14:31:00Z",
      "last_error": "Server returned 500 Internal Server Error"
    }
  ]
}
```

***

## Olay Veri Y\u00fck\u00fc \u00d6rnekleri

<AccordionGroup>
  <Accordion title="message.received">
    ```json theme={null}
    {
      "id": "dlv_abc123",
      "event": "message.received",
      "instance_id": "inst_abc123",
      "timestamp": "2026-02-10T14:30:00Z",
      "data": {
        "message_id": "BAE5F2C4D3B2A1",
        "chat_id": "5511999998888@s.whatsapp.net",
        "from": "5511999998888@s.whatsapp.net",
        "type": "text",
        "text": "Hello, I need help with my order",
        "timestamp": "2026-02-10T14:30:00Z"
      }
    }
    ```
  </Accordion>

  <Accordion title="message.delivered">
    ```json theme={null}
    {
      "id": "dlv_def456",
      "event": "message.delivered",
      "instance_id": "inst_abc123",
      "timestamp": "2026-02-10T14:30:05Z",
      "data": {
        "message_id": "BAE5A1B2C3D4E5",
        "chat_id": "5511999998888@s.whatsapp.net",
        "status": "delivered"
      }
    }
    ```
  </Accordion>

  <Accordion title="message.read">
    ```json theme={null}
    {
      "id": "dlv_ghi789",
      "event": "message.read",
      "instance_id": "inst_abc123",
      "timestamp": "2026-02-10T14:31:00Z",
      "data": {
        "message_id": "BAE5A1B2C3D4E5",
        "chat_id": "5511999998888@s.whatsapp.net",
        "status": "read"
      }
    }
    ```
  </Accordion>

  <Accordion title="message.reaction">
    ```json theme={null}
    {
      "id": "dlv_jkl012",
      "event": "message.reaction",
      "instance_id": "inst_abc123",
      "timestamp": "2026-02-10T14:32:00Z",
      "data": {
        "message_id": "BAE5F2C4D3B2A1",
        "chat_id": "5511999998888@s.whatsapp.net",
        "from": "5511999998888@s.whatsapp.net",
        "reaction": "\u2764\ufe0f"
      }
    }
    ```
  </Accordion>

  <Accordion title="instance.connected">
    ```json theme={null}
    {
      "id": "dlv_mno345",
      "event": "instance.connected",
      "instance_id": "inst_abc123",
      "timestamp": "2026-02-10T12:00:00Z",
      "data": {
        "instance_id": "inst_abc123",
        "status": "connected",
        "phone_number": "5511999998888"
      }
    }
    ```
  </Accordion>

  <Accordion title="instance.qr">
    ```json theme={null}
    {
      "id": "dlv_pqr678",
      "event": "instance.qr",
      "instance_id": "inst_abc123",
      "timestamp": "2026-02-10T11:59:00Z",
      "data": {
        "instance_id": "inst_abc123",
        "qr": "data:image/png;base64,iVBORw0KGgo..."
      }
    }
    ```
  </Accordion>

  <Accordion title="group.joined">
    ```json theme={null}
    {
      "id": "dlv_stu901",
      "event": "group.joined",
      "instance_id": "inst_abc123",
      "timestamp": "2026-02-10T15:00:00Z",
      "data": {
        "group_id": "120363012345678901@g.us",
        "participant": "5511888887777@s.whatsapp.net"
      }
    }
    ```
  </Accordion>
</AccordionGroup>

***

## En \u0130yi Uygulamalar

<CardGroup cols={2}>
  <Card title="H\u0131zl\u0131 yan\u0131t verin" icon="bolt">
    5 saniye i\u00e7inde `200` durumu d\u00f6nd\u00fcr\u00fcn. Zaman a\u015f\u0131m\u0131n\u0131 \u00f6nlemek i\u00e7in olay\u0131 asenkron olarak i\u015fleyin.
  </Card>

  <Card title="Tekrar\u0131 \u00f6nleyin" icon="clone">
    Yeniden denemelerden kaynaklanan tekrar teslimatlar\u0131 tespit etmek ve atlamak i\u00e7in teslimat `id`'sini kullan\u0131n.
  </Card>

  <Card title="\u0130mzalar\u0131 do\u011frulay\u0131n" icon="shield-halved">
    Bir gizli anahtar yap\u0131land\u0131rd\u0131ysan\u0131z her zaman `X-Wappfy-Signature` ba\u015fl\u0131\u011f\u0131n\u0131 do\u011frulay\u0131n.
  </Card>

  <Card title="HTTPS kullan\u0131n" icon="lock">
    Webhook URL'leri HTTPS kullanmal\u0131d\u0131r. HTTP ucu noktalar\u0131 reddedilecektir.
  </Card>
</CardGroup>
