# Carousel media WhatsApp

Carousel media adalah sekumpulan dua hingga sepuluh kartu yang digeser penerima secara berdampingan, masing-masing dengan gambar atau video, teks pendek, dan tombol sendiri. Gunakan carousel untuk menampilkan beberapa item sekaligus, misalnya beberapa produk, alih-alih mengirim satu pesan per item.

## Mengirim carousel

Atur `interactive.type` ke `carousel`, dengan `body_text` di level pesan dan array `cards` berisi 2 hingga 10 entri:

**TypeScript**

```typescript
const msg = await bird.whatsapp.send({
  to: "+16505551234",
  from: "+13124495648",
  interactive: {
    type: "carousel",
    body_text: "Here are two of our latest arrivals, each under $25:",
    cards: [
      {
        header: { type: "image", url: "https://cdn.example.com/plants/blue-echeveria.jpeg" },
        buttons: [
          {
            type: "cta_url",
            cta_url: { text: "Buy now", url: "https://shop.example.com/blue-echeveria" },
          },
        ],
      },
      {
        header: { type: "image", url: "https://cdn.example.com/plants/zebra-haworthia.jpeg" },
        buttons: [
          {
            type: "cta_url",
            cta_url: { text: "Buy now", url: "https://shop.example.com/zebra-haworthia" },
          },
        ],
      },
    ],
  },
});
console.log(msg.id, msg.status);
```

Examples: [TypeScript](/id-id/dokumentasi/guides/whatsapp/message-types/interactive/carousels.ts.md) · [Python](/id-id/dokumentasi/guides/whatsapp/message-types/interactive/carousels.py.md) · [Go](/id-id/dokumentasi/guides/whatsapp/message-types/interactive/carousels.go.md) · [PHP](/id-id/dokumentasi/guides/whatsapp/message-types/interactive/carousels.php.md) · [CLI](/id-id/dokumentasi/guides/whatsapp/message-types/interactive/carousels.cli.md) · [MCP](/id-id/dokumentasi/guides/whatsapp/message-types/interactive/carousels.mcp.md) · [cURL](/id-id/dokumentasi/guides/whatsapp/message-types/interactive/carousels.curl.md)

`from` wajib ada di setiap pesan layanan: nomor milik workspace Anda, bukan nomor yang dikelola Bird. Bentuk lengkapnya menambahkan teks kartu sendiri, tombol quick-reply kedua, dan kutipan pesan sebelumnya:

```json
{
  "to": "+16505551234",
  "from": "+13124495648",
  "in_reply_to_message_id": "wam_01kya19eknftrs2s6p82asmvnh",
  "interactive": {
    "type": "carousel",
    "body_text": "Here are two of our latest arrivals, each under $25:",
    "cards": [
      {
        "header": { "type": "image", "url": "https://cdn.example.com/plants/blue-echeveria.jpeg" },
        "body_text": "Blue Echeveria. Powdery blue leaves.",
        "buttons": [
          { "type": "quick_reply", "quick_reply": { "slug": "buy-echeveria", "text": "Buy" } },
          { "type": "quick_reply", "quick_reply": { "slug": "info-echeveria", "text": "Details" } }
        ]
      },
      {
        "header": { "type": "image", "url": "https://cdn.example.com/plants/zebra-haworthia.jpeg" },
        "body_text": "Zebra Haworthia. White stripes on deep green leaves.",
        "buttons": [
          { "type": "quick_reply", "quick_reply": { "slug": "buy-haworthia", "text": "Buy" } },
          { "type": "quick_reply", "quick_reply": { "slug": "info-haworthia", "text": "Details" } }
        ]
      }
    ]
  },
  "tags": [{ "name": "category", "value": "catalog" }],
  "metadata": { "order_id": "A-1" }
}
```

`in_reply_to_message_id` mengutip pesan sebelumnya dalam percakapan yang sama. Lihat bagian [mengutip pesan untuk mengorelasikan balasan](/docs/guides/whatsapp/message-types/interactive#quoting-a-message-to-correlate-a-reply) di hub untuk cara resolusi bekerja dan apa yang bisa terlewat.

Carousel tidak memiliki header level pesan maupun footer: `body_text` pesan adalah satu-satunya teks di atas kartu. Lihat bagian [tombol](/docs/guides/whatsapp/message-types/interactive#buttons) di hub untuk bentuk tombol bersama yang digunakan kembali oleh kartu tipe ini.

## Kartu

Setiap kartu memiliki header media, teks pendek, dan tombol sendiri:

- **`header`** wajib ada di setiap kartu, dan nilainya hanya `image` atau `video`: tidak ada header teks maupun dokumen, berbeda dengan tipe interaktif lainnya.
- **`body_text`** bersifat opsional. Letaknya di bawah media kartu, lebih pendek dari body pesan, dan mengizinkan maksimal dua jeda baris.
- **`buttons`** wajib ada: satu tombol `cta_url` atau hingga tiga tombol `quick_reply`, tidak boleh dicampur dalam satu kartu.

Kartu ditampilkan dari kiri ke kanan sesuai urutan kemunculannya di array `cards`. Kartu tidak memiliki footer maupun field indeks sendiri; posisinya di array adalah posisinya di carousel.

## Setiap kartu memiliki tombol yang sama

Setiap kartu dalam carousel harus memiliki **tipe tombol yang sama, jumlah yang sama, dalam urutan yang sama**. Carousel di mana kartu 1 memiliki satu tombol `cta_url` dan kartu 2 memiliki dua tombol `quick_reply` akan ditolak, begitu pula carousel di mana setiap kartu memiliki dua tombol `quick_reply` tetapi dalam urutan berbeda.

Alasannya adalah cara WhatsApp merender pesan: carousel adalah satu tampilan kartu dengan layout bersama, bukan sekumpulan kartu dengan layout masing-masing. Kartu dengan baris tombol berbeda akan merusak layout bersama tersebut, sehingga WhatsApp mengharuskan setiap kartu cocok dan Bird memeriksanya sebelum pengiriman dibuat atau dikenakan biaya. Ketidakcocokan menghasilkan [E15059](/docs/api/errors/E15059).

Label tombol adalah aturan terpisah, dan cakupannya berbeda: label harus unik **dalam satu kartu**, bukan di seluruh carousel. "Buy now" di setiap satu dari sepuluh kartu tidak masalah; "Buy now" dua kali di kartu yang sama menghasilkan [E15056](/docs/api/errors/E15056).

## Batas

| Field                                             | Batas                                                                                  |
| ------------------------------------------------- | -------------------------------------------------------------------------------------- |
| `cards`                                           | 2 hingga 10 entri                                                                      |
| Card `header`                                     | wajib di setiap kartu; hanya `image` atau `video`                                      |
| Card `header.url`                                 | wajib, tanpa panjang maksimum                                                          |
| Card `body_text`                                  | opsional, 1 hingga 160 karakter, maksimal 2 jeda baris                                 |
| Card `buttons`                                    | 1 hingga 3 entri: satu `cta_url`, atau hingga tiga `quick_reply`, tidak boleh dicampur |
| Label tombol (`quick_reply.text`, `cta_url.text`) | wajib, 1 hingga 20 karakter, unik dalam satu kartu                                     |
| `quick_reply.slug`                                | wajib, 1 hingga 256 karakter                                                           |
| `cta_url.url`                                     | wajib, 1 hingga 2.000 karakter                                                         |
| Message `body_text`                               | wajib, 1 hingga 1.024 karakter                                                         |
| Header pesan, footer                              | tidak diizinkan pada carousel: tidak ada `header`, tidak ada `footer_text`             |

Bird membatasi tombol `quick_reply` menjadi tiga per kartu. Meta sendiri tidak menyebutkan batas numerik, hanya menyatakan bahwa kartu menerima satu tombol link atau satu atau lebih tombol reply, sehingga batas ini milik Bird, bukan WhatsApp.

## Membaca balasan

Hanya tombol `quick_reply` pada kartu yang menghasilkan balasan. Ketukan pada tombol tersebut masuk sebagai pesan inbound tersendiri, membawa `interactive_reply`:

```json
{
  "id": "wam_01kyb2m4xq7whs0d8n3prv6tez",
  "direction": "inbound",
  "from": { "phone_number": "+16505551234" },
  "to": { "phone_number": "+13124495648" },
  "status": "received",
  "in_reply_to_message_id": "wam_01kya19eknftrs2s6p82asmvnh",
  "interactive_reply": {
    "type": "button",
    "button": {
      "slug": "buy-echeveria",
      "text": "Buy"
    }
  },
  "created_at": "2026-08-25T09:04:11Z"
}
```

`slug` yang Anda atur pada tombol yang diketuk dikembalikan persis sama pada `interactive_reply.button.slug`, bentuk yang sama seperti ketukan reply-buttons. Anda melihat balasan ini melalui daftar pesan atau `GET /v1/whatsapp/messages/{id}`; lihat bagian [membaca balasan](/docs/guides/whatsapp/message-types/interactive#reading-a-reply) di hub untuk alur lengkapnya.

Tombol `cta_url` pada kartu membuka link-nya di browser penerima dan tidak mengirim apa pun kembali, sama seperti [tombol link](/docs/guides/whatsapp/message-types/interactive/cta-url-buttons) mandiri.

## Carousel free-form dan carousel template

Halaman ini membahas carousel free-form yang Anda kirim secara inline dengan `interactive.type: "carousel"`, hanya dapat dikirim di dalam jendela layanan pelanggan yang terbuka dan tidak pernah ditinjau oleh Meta. [Template WhatsApp](/docs/guides/whatsapp/templates) memiliki carousel terpisah: komponen template yang dibuat sekali, diajukan ke Meta untuk persetujuan, dan dikirim berdasarkan slug seperti template lainnya, termasuk di luar jendela. Keduanya berbagi kata "carousel" dan rentang 2-hingga-10 kartu dari Meta, dan tidak ada kesamaan lain: bentuk wire berbeda, jalur peninjauan berbeda, dan jumlah kartu carousel template ditetapkan saat persetujuan template, bukan dipilih per pengiriman. Jika Anda menelusuri template dan melihat "carousel" di sana, itu adalah tipe template, bukan halaman ini.

## Batas dan kasus khusus

- **Jendela layanan pelanggan harus terbuka.** Carousel adalah pesan layanan, hanya dapat dikirim di dalam jendela yang terbuka; lihat bagian [jendela layanan pelanggan](/docs/guides/whatsapp/message-types#the-customer-service-window) di hub. Pemeriksaan jendela bersifat fails open, sehingga `202` bukan bukti bahwa jendela benar-benar terbuka saat pengiriman berlangsung.
- **`from` harus berupa nomor milik workspace Anda.** Menghilangkannya, atau menyebutkan nomor yang bukan sender terhubung, akan ditolak sebelum pengiriman dibuat.
- **Media kartu harus dapat diakses publik saat pengiriman diproses.** Bird tidak menyimpan atau mem-proxy file: WhatsApp mengambil `url` setiap kartu sendiri, pada saat pengiriman, sehingga signed URL harus tetap berlaku lebih lama dari pengiriman.
- **URL media kartu yang tidak dapat diambil WhatsApp akan diterima, lalu gagal secara asinkron, dan tetap dikenakan biaya.** Validasi permintaan Bird hanya memeriksa bahwa `url` kartu adalah URI yang valid secara format, bukan apakah WhatsApp dapat menjangkaunya atau apakah menggunakan `https`. File terlalu besar, 404, host tidak dapat di-resolve, atau tipe file salah semuanya dikembalikan sebagai `202` saat diterima, lalu `whatsapp.accepted` lalu `whatsapp.sent` lalu `whatsapp.failed`, dengan `media_rejected` pada `last_error` pesan dan biaya pengiriman sudah dikenakan tanpa jalur pengembalian dana. Uji setiap URL kartu sebelum mengirim, karena URL yang rusak tidak terdeteksi sampai setelahnya.
- **Setiap kartu harus memiliki tombol yang sama.** Lihat [Setiap kartu memiliki tombol yang sama](#setiap-kartu-memiliki-tombol-yang-sama) di atas; ini adalah satu-satunya aturan carousel yang tidak dapat dinyatakan oleh skema permintaan sendiri, sehingga diperiksa secara terpisah dan menghasilkan [E15059](/docs/api/errors/E15059) alih-alih error validasi generik.
- **Tidak ada header atau footer level pesan.** Satu-satunya teks di atas kartu pada carousel adalah `body_text`; tidak ada tempat untuk meletakkan catatan kecil seperti yang digunakan tipe lain pada `footer_text`.
- **Balasan tidak menyertakan indeks kartu.** Ketukan `quick_reply` kartu hanya melaporkan `{slug, text}`, bentuk yang sama seperti ketukan reply-buttons, tanpa field yang menyebutkan kartu mana asalnya. Jika Anda perlu mengetahui kartu mana yang diketuk, encode kartu di `slug` setiap tombol, misalnya `buy-echeveria` alih-alih `buy` saja.
- **Tombol `cta_url` pada kartu tidak menghasilkan event inbound.** Jika Anda perlu mengetahui bahwa kartu berinteraksi, gunakan tombol `quick_reply` pada kartu tersebut, atau lacak klik di URL tujuan Anda sendiri.

Selain E15059, satu-satunya error interaktif khusus carousel adalah [E15056](/docs/api/errors/E15056) untuk label tombol yang berulang pada satu kartu. Kutipan yang tidak ter-resolve akan menggagalkan permintaan sebelum apa pun dibuat atau dikenakan biaya: `404` [`E15071`](/docs/api/errors/E15071) ketika id menyebutkan pesan yang tidak dimiliki workspace ini, `422` [`E15072`](/docs/api/errors/E15072) ketika menyebutkan pesan yang tidak dapat dikutip. Untuk error yang dapat terjadi pada pengiriman WhatsApp mana pun, jendela tertutup, sender yang hilang atau tidak valid, atau penerima yang tidak valid, lihat bagian [error](/docs/guides/whatsapp/message-types/interactive#errors) dan [Mengirim pesan WhatsApp](/docs/guides/whatsapp/sending-whatsapp) di hub.

## Langkah selanjutnya

- [Pesan interaktif WhatsApp](/docs/guides/whatsapp/message-types/interactive): kesamaan di antara enam tipe interaktif
- [Template WhatsApp](/docs/guides/whatsapp/templates): untuk carousel yang dikirim di luar jendela layanan pelanggan
- [Mengirim pesan WhatsApp](/docs/guides/whatsapp/sending-whatsapp): envelope permintaan, model `202`, dan coba lagi yang aman

## Related resources

- [Connecting WhatsApp to Bird: from buying a number to a live channel](/learn/whatsapp/connecting-whatsapp-to-bird) (video)
- [What is the 24-hour customer service window on WhatsApp?](/explained/whatsapp/what-is-the-24-hour-customer-service-window) (answer)
- [WhatsApp message builder](/tools/whatsapp-message-builder) (tool)
- [WhatsApp](/products/whatsapp) (product)

[Get an implementation brief](/learn/workspace?topic=whatsapp)
