Skip to Content

Messaging

Sending on the official provider uses the exact same builder as the unofficial one — Zaileys translates it to Graph API payloads for you. So this page does not re-teach the builder; it links you to the shared docs and details only what’s different on cloud.

⚠️

Hitting errors like 131047 or 132000? The Cloud API is heavily gated by Meta. Read Limits, Gotchas & Solutions — every restriction (the 24-hour window, template approval, media sizes, rate limits, …) with a concrete fix.

Shared — documented in the main guide

You want to…Read
Send text, and the chainable builder basicsSending Messages
Send image / video / audio / document / stickerMedia
Send buttons and listsInteractive
Understand the inbound message payload (msg.text, msg.senderId, msg.reply()…)Message Payload
React, quote-reply, forwardSending Messages
// identical to the unofficial provider: await wa.send(to).text('halo dunia') await wa.send(to).image('https://…/a.jpg', { caption: 'lihat ini 📸' }) await wa.send(to).document('https://…/invoice.pdf', { fileName: 'invoice.pdf' }) await wa.send(to).location(-6.2, 106.8, { name: 'Monas', address: 'Jakarta' }) await wa.send(to).buttons([{ id: 'yes', text: 'Ya' }], { text: 'Setuju?' }) await msg.reply('siap!') await wa.react(msg.message().key, '🔥')

Media accepts a URL, a local path, or a Buffer — Zaileys uploads it to Meta’s media endpoint and references the returned id automatically. Download inbound media with wa.downloadMedia(key).

Cloud-only differences

Limits on interactive & message types

⚠️
  • Reply buttons max out at 3 (Meta hard limit). More throws a typed error.
  • Carousels and polls are not available on the Cloud API.
  • Media headers on interactive buttons aren’t supported yet.
  • Albums must be sent as individual media messages.

Every unsupported builder call throws ZaileysProviderError('UNSUPPORTED_ON_CLOUD') immediately — see the feature comparison.

markRead takes a message id

Because there’s no chat-level cursor, the cloud markRead marks a single message and can show a typing indicator in the same call:

wa.on('text', async (msg) => { await wa.markRead(msg.chatId, { typing: true }) // mark read + show "typing…" await msg.reply('got it') })

The 24-hour window

You can only send free-form messages inside Meta’s customer-service window:

  • A user messages you → a 24-hour window opens → send anything freely.
  • Outside the window, or to a user who never texted you → only approved templates.
// ✅ always allowed (business-initiated) await wa.sendTemplate(to, 'welcome', 'en_US') // ❌ fails with Graph error 131047 outside the window await wa.send(to).text('hi')

This is Meta policy, enforced server-side. See Templates & Campaigns for how to open conversations, and Events & Errors for 131047.

Contacts need a first name

A cloud contact’s name requires a formatted_name and at least one of first_name / last_name. Zaileys derives them from the vCard’s FN:/N: fields automatically, so this just works — but if you build the vCard yourself, include an N: line:

await wa.send(to).contact('BEGIN:VCARD\nVERSION:3.0\nFN:Budi Santoso\nN:Santoso;Budi\nTEL:+62811\nEND:VCARD')

Delivery tracking

Outbound messages emit a cloud-only message-status event as they progress through sentdeliveredread (or failed).

Last updated on