# WhatsApp-mediacarousels

Een mediacarousel is een reeks van twee tot tien kaarten waar de ontvanger naast elkaar doorheen veegt, elk met een eigen afbeelding of video, een eigen korte tekst en eigen knoppen. Gebruik het om meerdere items tegelijk te tonen, zoals een handvol producten, in plaats van één bericht per item te versturen.

## Een carousel versturen

Stel `interactive.type` in op `carousel`, met een `body_text` op berichtniveau en een `cards`-array van 2 tot 10 items:

**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](/nl-nl/documentatie/guides/whatsapp/message-types/interactive/carousels.ts.md) · [Python](/nl-nl/documentatie/guides/whatsapp/message-types/interactive/carousels.py.md) · [Go](/nl-nl/documentatie/guides/whatsapp/message-types/interactive/carousels.go.md) · [PHP](/nl-nl/documentatie/guides/whatsapp/message-types/interactive/carousels.php.md) · [CLI](/nl-nl/documentatie/guides/whatsapp/message-types/interactive/carousels.cli.md) · [MCP](/nl-nl/documentatie/guides/whatsapp/message-types/interactive/carousels.mcp.md) · [cURL](/nl-nl/documentatie/guides/whatsapp/message-types/interactive/carousels.curl.md)

`from` is vereist bij elk servicebericht: een nummer dat je werkruimte bezit, niet een door Bird beheerd nummer. De volledige structuur voegt de eigen tekst van een kaart, een tweede quick-reply-knop en een citaat van een eerder bericht toe:

```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` citeert een eerder bericht in hetzelfde gesprek. Zie in de hub [een bericht citeren om een antwoord te correleren](/docs/guides/whatsapp/message-types/interactive#quoting-a-message-to-correlate-a-reply) voor hoe de resolutie werkt en wat het kan missen.

Een carousel heeft geen header en geen footer op berichtniveau: de `body_text` van het bericht is de enige tekst boven de kaarten. Zie de sectie [knoppen](/docs/guides/whatsapp/message-types/interactive#buttons) in de hub voor de gedeelde knopstructuur die de kaarten van dit type hergebruiken.

## Kaarten

Elke kaart heeft een eigen mediaheader, een eigen korte tekst en eigen knoppen:

- **`header`** is vereist op elke kaart, en het is alleen `image` of `video`: geen tekst en geen documentheader, in tegenstelling tot de andere interactieve typen.
- **`body_text`** is optioneel. Het staat onder de media van de kaart, is korter dan een berichttekst en staat maximaal twee regeleinden toe.
- **`buttons`** is vereist: ofwel één `cta_url`-knop, ofwel maximaal drie `quick_reply`-knoppen, nooit een mix op dezelfde kaart.

Kaarten worden van links naar rechts weergegeven in de volgorde waarin ze in de `cards`-array staan. Een kaart heeft geen footer en geen eigen indexveld; de positie in de array is de positie in de carousel.

## Elke kaart heeft dezelfde knoppen

Elke kaart in een carousel moet **dezelfde knoptypen, hetzelfde aantal en dezelfde volgorde** hebben. Een carousel waarbij kaart 1 één `cta_url`-knop heeft en kaart 2 twee `quick_reply`-knoppen, wordt geweigerd. Hetzelfde geldt voor een carousel waarbij elke kaart twee `quick_reply`-knoppen heeft maar in een andere volgorde.

De reden is hoe WhatsApp het bericht rendert: een carousel is één kaartweergave met een gedeelde lay-out, niet een set onafhankelijk opgemaakte kaarten. Een kaart met een andere knoprij zou die gedeelde lay-out breken, dus WhatsApp vereist dat elke kaart overeenkomt en Bird controleert dit voordat de verzending wordt aangemaakt of in rekening gebracht. Een mismatch retourneert [E15059](/docs/api/errors/E15059).

Knoplabels zijn een aparte regel, en die regel heeft een ander bereik: een label moet uniek zijn **binnen een kaart**, niet binnen de hele carousel. "Buy now" op elk van de tien kaarten is prima; "Buy now" twee keer op dezelfde kaart retourneert [E15056](/docs/api/errors/E15056).

## Limieten

| Veld                                           | Grens                                                                       |
| ---------------------------------------------- | --------------------------------------------------------------------------- |
| `cards`                                        | 2 tot 10 items                                                              |
| Kaart `header`                                 | vereist op elke kaart; alleen `image` of `video`                            |
| Kaart `header.url`                             | vereist, geen maximumlengte                                                 |
| Kaart `body_text`                              | optioneel, 1 tot 160 tekens, maximaal 2 regeleinden                         |
| Kaart `buttons`                                | 1 tot 3 items: één `cta_url`, of maximaal drie `quick_reply`, nooit gemengd |
| Knoplabel (`quick_reply.text`, `cta_url.text`) | vereist, 1 tot 20 tekens, uniek binnen de kaart                             |
| `quick_reply.slug`                             | vereist, 1 tot 256 tekens                                                   |
| `cta_url.url`                                  | vereist, 1 tot 2000 tekens                                                  |
| Bericht `body_text`                            | vereist, 1 tot 1024 tekens                                                  |
| Berichtheader, footer                          | niet toegestaan op een carousel: geen `header`, geen `footer_text`          |

Bird beperkt `quick_reply`-knoppen tot drie per kaart. Meta zelf noemt geen numerieke limiet, alleen dat een kaart ofwel één linkknop ofwel één of meer antwoordknoppen heeft, dus dit plafond is van Bird, niet van WhatsApp.

## Het antwoord lezen

Alleen een `quick_reply`-kaartknop levert een antwoord op. Een tik erop komt binnen als een eigen inbound bericht, met `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"
}
```

De `slug` die je op de aangetikte knop hebt ingesteld, komt letterlijk terug op `interactive_reply.button.slug`, dezelfde structuur als bij een tik op reply-buttons. Je ziet dit antwoord via de berichtenlijst of `GET /v1/whatsapp/messages/{id}`; zie in de hub [een antwoord lezen](/docs/guides/whatsapp/message-types/interactive#reading-a-reply) voor het volledige pad.

Een `cta_url`-knop op een kaart opent de link in de browser van de ontvanger en stuurt niets terug, net als een losse [linkknop](/docs/guides/whatsapp/message-types/interactive/cta-url-buttons).

## Vrije-vormcarousels en templatecarousels

Deze pagina behandelt de vrije-vormcarousel die je inline verstuurt met `interactive.type: "carousel"`, alleen leverbaar binnen een open klantenservicevenster en nooit beoordeeld door Meta. [WhatsApp-templates](/docs/guides/whatsapp/templates) heeft een eigen, aparte carousel: een templatecomponent die je eenmalig opstelt, ter goedkeuring bij Meta indient en per slug verstuurt zoals elke andere template, ook buiten het venster. De twee delen het woord "carousel" en Meta's bereik van 2 tot 10 kaarten, en verder niets: verschillende wire-structuren, verschillende beoordelingspaden, en het aantal kaarten van een templatecarousel ligt vast bij de goedkeuring van de template in plaats van per verzending te worden gekozen. Als je door templates bladert en daar "carousel" ziet, is dat het templatetype, niet deze pagina.

## Limieten en randgevallen

- **Het klantenservicevenster moet open zijn.** Een carousel is een servicebericht, alleen leverbaar binnen een open venster; zie in de hub [klantenservicevenster](/docs/guides/whatsapp/message-types#the-customer-service-window). De venstercontrole faalt open, dus een `202` is geen bewijs dat het venster daadwerkelijk open was toen de verzending uitgaat.
- **`from` moet een nummer zijn dat je werkruimte bezit.** Weglaten, of een nummer opgeven dat geen verbonden afzender is, wordt geweigerd voordat de verzending wordt aangemaakt.
- **Kaartmedia moet publiek bereikbaar zijn wanneer de verzending wordt verstuurd.** Bird slaat het bestand niet op en proxyt het niet: WhatsApp haalt de `url` van elke kaart zelf op, op het moment van verzenden, dus een ondertekende URL moet langer geldig zijn dan de verzending.
- **Een kaartmedia-URL die WhatsApp niet kan ophalen wordt geaccepteerd, faalt vervolgens asynchroon en wordt alsnog in rekening gebracht.** De requestvalidatie van Bird controleert alleen of de `url` van een kaart een goed gevormde URI is, niet of WhatsApp hem kan bereiken of dat hij `https` gebruikt. Een te groot bestand, een 404, een niet-oplosbare host of het verkeerde bestandstype komen allemaal terug als een `202` bij acceptatie, dan `whatsapp.accepted` dan `whatsapp.sent` dan `whatsapp.failed`, met `media_rejected` op de `last_error` van het bericht en de kosten van de verzending al in rekening gebracht zonder restitutiepad. Test de URL van elke kaart voordat je verstuurt, want een defecte URL wordt pas achteraf opgemerkt.
- **Elke kaart moet dezelfde knoppen hebben.** Zie [Elke kaart heeft dezelfde knoppen](#elke-kaart-heeft-dezelfde-knoppen) hierboven; dit is de enige carouselregel die het requestschema niet op zichzelf kan uitdrukken, dus wordt het apart gecontroleerd en retourneert [E15059](/docs/api/errors/E15059) in plaats van een generieke validatiefout.
- **Geen header of footer op berichtniveau.** De enige tekst boven de kaarten van een carousel is `body_text`; er is geen plek voor kleine lettertjes zoals de andere typen `footer_text` gebruiken.
- **Het antwoord bevat geen kaartindex.** Een tik op `quick_reply` van een kaart rapporteert alleen `{slug, text}`, dezelfde structuur als een tik op reply-buttons, zonder een veld dat aangeeft van welke kaart het afkomstig is. Als je wilt weten op welke kaart is getikt, codeer je de kaart in de `slug` van elke knop, zoals `buy-echeveria` in plaats van een kale `buy`.
- **Een `cta_url`-kaartknop genereert geen inbound event.** Als je wilt weten of er interactie met een kaart was, gebruik dan `quick_reply`-knoppen op die kaart, of volg de klik op je eigen bestemmings-URL.

Naast E15059 is de enige interactieve fout specifiek voor een carousel [E15056](/docs/api/errors/E15056) voor een herhaald knoplabel op één kaart. Een citaat dat niet kan worden opgelost laat het request falen voordat er iets wordt aangemaakt of in rekening gebracht: `404` [`E15071`](/docs/api/errors/E15071) wanneer het id geen bericht noemt dat deze werkruimte bezit, `422` [`E15072`](/docs/api/errors/E15072) wanneer het er een noemt die niet kan worden geciteerd. Zie voor de fouten die elke WhatsApp-verzending kan tegenkomen, zoals een gesloten venster, een ontbrekende of ongeldige afzender, of een ongeldige ontvanger, de [fouten](/docs/guides/whatsapp/message-types/interactive#errors) en [WhatsApp-berichten versturen](/docs/guides/whatsapp/sending-whatsapp) in de hub.

## Volgende stappen

- [Interactieve WhatsApp-berichten](/docs/guides/whatsapp/message-types/interactive): wat alle zes interactieve typen delen
- [WhatsApp-templates](/docs/guides/whatsapp/templates): voor een carousel die buiten het klantenservicevenster verstuurt
- [WhatsApp-berichten versturen](/docs/guides/whatsapp/sending-whatsapp): de request-envelop, het `202`-model en veilig opnieuw proberen

## 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)
