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

# Channel Message In

> Event pesan masuk dari pelanggan

## Pengenalan

Event `channel.message_in` dipicu ketika pesan diterima dari channel komunikasi manapun (WhatsApp, Telegram, Slack, Instagram, Facebook, dll.).

<Callout>
  Event ini adalah webhook paling umum yang akan Anda terima, karena mewakili setiap pesan pelanggan yang masuk.
</Callout>

## Trigger Event

```
Pelanggan mengirim pesan
       ↓
   Platform CSKU AI
       ↓
   Trigger webhook channel.message_in
       ↓
   HTTP POST → URL Webhook Anda
```

## Struktur Payload

```json theme={null}
{
  "event": "channel.message_in",
  "timestamp": 1738056000,
  "conversation_id": "conv_abc123",
  "conversation_label": "John Doe",
  "need_human": 0,
  "message": {
    "id": "msg_xyz789",
    "sender_name": "John Doe",
    "channel": {
      "id": "channel_merchant_id",
      "name": "WhatsApp Business",
      "engine": "wa"
    },
    "bisnis": {
      "id": "biz_123",
      "name": "My Business"
    },
    "user": {
      "id": "merchant_456",
      "name": "Merchant Name"
    },
    "content": {
      "type": "text",
      "text": "Halo, saya butuh bantuan dengan pesanan saya"
    }
  }
}
```

## Deskripsi Field

### Field Root

| Field                | Tipe    | Deskripsi                                           |
| -------------------- | ------- | --------------------------------------------------- |
| `event`              | string  | Identifier event: `channel.message_in`              |
| `timestamp`          | integer | Unix timestamp saat event terjadi                   |
| `conversation_id`    | string  | Identifier percakapan unik                          |
| `conversation_label` | string  | Nama tampilan percakapan                            |
| `need_human`         | integer | Flag (0/1) jika percakapan butuh intervensi manusia |
| `message`            | object  | Detail pesan (lihat di bawah)                       |

### Field Message

| Field                 | Tipe   | Deskripsi                                |
| --------------------- | ------ | ---------------------------------------- |
| `message.id`          | string | Identifier pesan unik                    |
| `message.sender_name` | string | Nama pengirim pesan                      |
| `message.channel`     | object | Informasi channel (lihat di bawah)       |
| `message.bisnis`      | object | Informasi bisnis (lihat di bawah)        |
| `message.user`        | object | Informasi user merchant (lihat di bawah) |
| `message.content`     | object | Konten pesan (lihat di bawah)            |

### Field Channel

| Field            | Tipe   | Deskripsi                                        |
| ---------------- | ------ | ------------------------------------------------ |
| `channel.id`     | string | Identifier unik channel                          |
| `channel.name`   | string | Nama tampilan channel                            |
| `channel.engine` | string | Tipe engine channel (lihat engine yang didukung) |

### Engine Channel yang Didukung

| Engine      | Channel            |
| ----------- | ------------------ |
| `wa`        | WhatsApp           |
| `telegram`  | Telegram           |
| `slack`     | Slack              |
| `intercom`  | Intercom           |
| `instagram` | Instagram          |
| `facebook`  | Facebook Messenger |

<Note>
  Field `channel.engine` membantu Anda mengidentifikasi platform asal pesan.
</Note>

### Field Bisnis & User

| Field                 | Tipe   | Deskripsi        |
| --------------------- | ------ | ---------------- |
| `message.bisnis.id`   | string | ID Bisnis        |
| `message.bisnis.name` | string | Nama bisnis      |
| `message.user.id`     | string | ID user merchant |
| `message.user.name`   | string | Nama merchant    |

### Field Konten (Pesan Teks)

| Field                  | Tipe   | Deskripsi                                                 |
| ---------------------- | ------ | --------------------------------------------------------- |
| `message.content.type` | string | Tipe pesan: `text`, `image`, `video`, `audio`, `document` |
| `message.content.text` | string | Konten teks pesan (untuk pesan teks)                      |

## Payload Pesan Media

Untuk pesan non-teks, payload mencakup attachments:

```json theme={null}
{
  "event": "channel.message_in",
  "timestamp": 1738056000,
  "conversation_id": "conv_abc123",
  "conversation_label": "John Doe",
  "need_human": 0,
  "message": {
    "id": "msg_xyz789",
    "sender_name": "John Doe",
    "channel": {
      "id": "channel_merchant_id",
      "name": "WhatsApp Business",
      "engine": "wa"
    },
    "bisnis": {
      "id": "biz_123",
      "name": "My Business"
    },
    "user": {
      "id": "merchant_456",
      "name": "Merchant Name"
    },
    "content": {
      "type": "image",
      "attachments": [
        {
          "url": "https://example.com/media/image123.jpg",
          "mime_type": "image/jpeg"
        }
      ]
    }
  }
}
```

### Field Attachment

| Field       | Tipe   | Deskripsi                                         |
| ----------- | ------ | ------------------------------------------------- |
| `url`       | string | URL untuk mengakses file media                    |
| `mime_type` | string | MIME type file (misal, `image/jpeg`, `video/mp4`) |

## Tipe Media yang Didukung

| Tipe       | MIME Types                                            |
| ---------- | ----------------------------------------------------- |
| `image`    | `image/jpeg`, `image/png`, `image/gif`, `image/webp`  |
| `video`    | `video/mp4`, `video/avi`, `video/mov`, `video/webm`   |
| `audio`    | `audio/mp3`, `audio/wav`, `audio/ogg`, `audio/aac`    |
| `document` | `application/pdf`, `application/msword`, `text/plain` |

## Contoh Implementasi

### Node.js

```javascript theme={null}
app.post('/webhook', async (req, res) => {
  const { event, message } = req.body;
  
  if (event === 'channel.message_in') {
    const { id, sender_name, content, channel } = message;
    
    console.log(`Pesan baru dari ${sender_name}`);
    
    // Tangani pesan teks
    if (content.type === 'text') {
      console.log('Pesan:', content.text);
      // Simpan ke database
      await db.messages.create({
        message_id: id,
        sender: sender_name,
        text: content.text,
        channel: channel.engine
      });
    }
    
    // Tangani pesan media
    if (content.attachments) {
      content.attachments.forEach(attachment => {
        console.log('URL Media:', attachment.url);
        // Download atau proses media
      });
    }
  }
  
  res.status(200).send('OK');
});
```

### Python

```python theme={null}
@app.route('/webhook', methods=['POST'])
def webhook():
    data = request.get_json()
    event = data.get('event')
    message = data.get('message')
    
    if event == 'channel.message_in':
        msg_id = message['id']
        sender = message['sender_name']
        content = message['content']
        channel = message['channel']
        
        print(f"Pesan baru dari {sender}")
        
        # Tangani pesan teks
        if content['type'] == 'text':
            text = content['text']
            print(f"Pesan: {text}")
            # Simpan ke database
            db.messages.create(
                message_id=msg_id,
                sender=sender,
                text=text,
                channel=channel['engine']
            )
        
        # Tangani pesan media
        if 'attachments' in content:
            for attachment in content['attachments']:
                print(f"URL Media: {attachment['url']}")
    
    return 'OK', 200
```

## Use Case

<AccordionGroup>
  <Accordion title="Otomasi Dukungan Pelanggan">
    Trigger respons otomatis atau arahkan ke tim dukungan yang tepat berdasarkan konten pesan.
  </Accordion>

  <Accordion title="Integrasi CRM">
    Log pesan pelanggan di sistem CRM Anda untuk riwayat percakapan lengkap.
  </Accordion>

  <Accordion title="Analitik">
    Analisis pola pesan masuk, waktu puncak, dan sentimen pelanggan.
  </Accordion>

  <Accordion title="Lead Generation">
    Tangkap dan kualifikasi lead dari pertanyaan pelanggan yang masuk.
  </Accordion>

  <Accordion title="Penyimpanan Media">
    Download dan simpan gambar atau dokumen yang dikirim pelanggan.
  </Accordion>
</AccordionGroup>

## Praktik Terbaik

<Callout type="info">
  Ikuti praktik ini saat menangani event `channel.message_in`.
</Callout>

1. **Validasi Struktur Payload**
   ```javascript theme={null}
   if (!event || !message || !message.content) {
     console.error('Struktur payload tidak valid');
     return res.status(400).send('Invalid payload');
   }
   ```

2. **Deduplikasi Event**
   ```javascript theme={null}
   const processedEvents = new Set();
   const eventId = `${event}_${message.id}`;

   if (processedEvents.has(eventId)) {
     return res.status(200).send('OK');
   }

   processedEvents.add(eventId);
   ```

3. **Tangani Berbagai Tipe Konten**
   ```javascript theme={null}
   if (content.type === 'text') {
     // Tangani teks
   } else if (content.attachments) {
     // Tangani media
   } else {
     console.warn('Tipe konten tidak dikenal:', content.type);
   }
   ```

4. **Simpan Konteks Percakapan**
   ```javascript theme={null}
   // Lacak state percakapan
   const conversationState = {
     id: conversation_id,
     label: conversation_label,
     needsHuman: need_human === 1
   };

   await db.conversations.upsert(conversationState);
   ```

## Penanganan Error

```javascript theme={null}
app.post('/webhook', async (req, res) => {
  try {
    const { event, message } = req.body;
    
    if (event === 'channel.message_in') {
      // Proses pesan
      await handleIncomingMessage(message);
    }
    
    res.status(200).send('OK');
  } catch (error) {
    console.error('Error memproses channel.message_in:', error);
    // Tetap kembalikan 200 untuk menghindari retry pada error pemrosesan
    res.status(200).send('OK');
  }
});
```

<Note>
  Kembalikan 200 OK meskipun Anda mengalami error pemrosesan, kecuali Anda ingin CSKU AI me-retry webhook.
</Note>

## Event Terkait

<CardGroup cols={2}>
  <Card title="Agent Message Out" icon="user" href="/webhooks/events/agent-message-out">
    Agen manusia mengirim pesan
  </Card>

  <Card title="AI Message Generated" icon="bot" href="/webhooks/events/ai-message-generated">
    Agen AI merespons
  </Card>
</CardGroup>
