WhatsApp Cloud API: Panduan Resmi Meta

Panduan lengkap WhatsApp Cloud API dari Meta. Setup, pricing, fitur, dan best practices. Official API guide untuk developer!

WhatsApp Cloud API
WhatsApp Cloud API

WhatsApp Cloud API = Official API dari Meta!

Hosted oleh Meta, tidak perlu server sendiri. Gratis untuk mulai, bayar per conversation.


Apa Itu Cloud API?

WHATSAPP CLOUD API:
- Official API dari Meta/Facebook
- Hosted di infrastructure Meta
- Tidak perlu maintain server
- Pay-per-use model
- 1,000 free conversations/month

VS ON-PREMISE API:
- Self-hosted
- Butuh server sendiri
- Untuk enterprise besar
- More control, more responsibility

Pricing Structure

Free Tier:

1,000 free service conversations/month
(User-initiated conversations)
BUSINESS-INITIATED (Template Messages):
- Utility: ~$0.005 - 0.02/conversation
- Authentication: ~$0.005 - 0.02/conversation
- Marketing: ~$0.02 - 0.08/conversation

USER-INITIATED (24h Window):
- Service: ~$0.003 - 0.01/conversation

*Harga vary by country

Conversation Window:

1 conversation = 24 hours window
Unlimited messages dalam window
Window mulai dari:
- Business-initiated: Saat template terkirim
- User-initiated: Saat customer kirim pesan

Setup WhatsApp Cloud API

Step 1: Create Meta Developer Account

1. Buka developers.facebook.com
2. Login dengan Facebook
3. Create App → Business type
4. Add WhatsApp product

Step 2: Setup WhatsApp Business

1. Create/connect Meta Business Account
2. Add phone number (bisa test number dulu)
3. Verify phone number
4. Get Phone Number ID & Access Token

Step 3: Configure Webhook

1. Setup webhook endpoint (HTTPS)
2. Add callback URL
3. Add verify token
4. Subscribe to messages

Step 4: Send Test Message

bash

curl -X POST \
  'https://graph.facebook.com/v17.0/PHONE_NUMBER_ID/messages' \
  -H 'Authorization: Bearer ACCESS_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{
    "messaging_product": "whatsapp",
    "to": "628123456789",
    "type": "text",
    "text": {"body": "Hello from Cloud API!"}
  }'

Code Examples

Send Text Message:

javascript

const axios = require('axios');

async function sendTextMessage(to, message) {
    const response = await axios.post(
        `https://graph.facebook.com/v17.0/${PHONE_NUMBER_ID}/messages`,
        {
            messaging_product: 'whatsapp',
            to: to,
            type: 'text',
            text: { body: message }
        },
        {
            headers: {
                'Authorization': `Bearer ${ACCESS_TOKEN}`,
                'Content-Type': 'application/json'
            }
        }
    );
    
    return response.data;
}

Send Template Message:

javascript

async function sendTemplateMessage(to, templateName, language, components) {
    const response = await axios.post(
        `https://graph.facebook.com/v17.0/${PHONE_NUMBER_ID}/messages`,
        {
            messaging_product: 'whatsapp',
            to: to,
            type: 'template',
            template: {
                name: templateName,
                language: { code: language },
                components: components
            }
        },
        {
            headers: {
                'Authorization': `Bearer ${ACCESS_TOKEN}`,
                'Content-Type': 'application/json'
            }
        }
    );
    
    return response.data;
}

// Usage
await sendTemplateMessage(
    '628123456789',
    'order_confirmation',
    'id',
    [
        {
            type: 'body',
            parameters: [
                { type: 'text', text: 'John' },
                { type: 'text', text: '#12345' }
            ]
        }
    ]
);

Send Image:

javascript

async function sendImage(to, imageUrl, caption) {
    const response = await axios.post(
        `https://graph.facebook.com/v17.0/${PHONE_NUMBER_ID}/messages`,
        {
            messaging_product: 'whatsapp',
            to: to,
            type: 'image',
            image: {
                link: imageUrl,
                caption: caption
            }
        },
        {
            headers: {
                'Authorization': `Bearer ${ACCESS_TOKEN}`,
                'Content-Type': 'application/json'
            }
        }
    );
    
    return response.data;
}

Send Interactive Buttons:

javascript

async function sendButtons(to, bodyText, buttons) {
    const response = await axios.post(
        `https://graph.facebook.com/v17.0/${PHONE_NUMBER_ID}/messages`,
        {
            messaging_product: 'whatsapp',
            to: to,
            type: 'interactive',
            interactive: {
                type: 'button',
                body: { text: bodyText },
                action: {
                    buttons: buttons.map((btn, i) => ({
                        type: 'reply',
                        reply: {
                            id: `btn_${i}`,
                            title: btn
                        }
                    }))
                }
            }
        },
        {
            headers: {
                'Authorization': `Bearer ${ACCESS_TOKEN}`,
                'Content-Type': 'application/json'
            }
        }
    );
    
    return response.data;
}

// Usage
await sendButtons(
    '628123456789',
    'Pilih menu:',
    ['Order', 'Katalog', 'Bantuan']
);

Message Templates

Kenapa Butuh Template?

Business-initiated message (outside 24h window)
HARUS pakai template yang sudah di-approve.

User-initiated (dalam 24h window)
Bisa kirim free-form message.

Create Template:

1. WhatsApp Manager → Message Templates
2. Create Template
3. Pilih kategori (Marketing/Utility/Authentication)
4. Tulis template dengan variables {{1}}, {{2}}
5. Submit untuk review
6. Tunggu approval (biasanya < 24 jam)

Template Example:

Category: Utility
Name: order_status

Header: Order Update
Body: Hai {{1}}, order #{{2}} kamu sedang {{3}}. 
      Estimasi sampai: {{4}}
Footer: Terima kasih sudah belanja di Toko Kami
Buttons: [Track Order] [Hubungi CS]

Webhook Integration

Handle Incoming Messages:

javascript

app.post('/webhook', (req, res) => {
    const body = req.body;
    
    if (body.object === 'whatsapp_business_account') {
        body.entry.forEach(entry => {
            entry.changes.forEach(change => {
                if (change.value.messages) {
                    change.value.messages.forEach(message => {
                        handleMessage(message, change.value.contacts[0]);
                    });
                }
            });
        });
        
        res.sendStatus(200);
    } else {
        res.sendStatus(404);
    }
});

function handleMessage(message, contact) {
    const from = message.from;
    const name = contact.profile.name;
    
    console.log(`Message from ${name} (${from})`);
    
    switch (message.type) {
        case 'text':
            processTextMessage(from, message.text.body);
            break;
        case 'image':
            processImageMessage(from, message.image);
            break;
        case 'interactive':
            processInteractiveReply(from, message.interactive);
            break;
    }
}

Best Practices

1. Template Strategy

✅ Prepare templates untuk common use cases
✅ Use variables untuk personalisasi
✅ Test sebelum production
❌ Jangan hard-code text di template

2. Handle 24h Window

javascript

// Track conversation windows
const windows = new Map();

async function sendMessage(to, message) {
    const window = windows.get(to);
    const now = Date.now();
    
    if (window && (now - window) < 24 * 60 * 60 * 1000) {
        // Within window - send free-form
        await sendTextMessage(to, message);
    } else {
        // Outside window - need template
        await sendTemplateMessage(to, 'general_notification', 'id', [
            { type: 'body', parameters: [{ type: 'text', text: message }] }
        ]);
    }
}

// Update window saat customer kirim pesan
function onMessageReceived(from) {
    windows.set(from, Date.now());
}

3. Quality Rating

Maintain good quality rating:
✅ Relevant messages
✅ Honor opt-out
✅ Quick response time
❌ Spam
❌ Ignored complaints

FAQ

Gratis atau bayar?

1,000 free service conversations/month. Lebih dari itu bayar per conversation.

Berapa lama approval template?

Biasanya < 24 jam. Bisa lebih cepat atau lebih lama tergantung content.

Bisa pakai nomor existing?

Bisa, tapi nomor akan di-migrate ke Business Account dan tidak bisa balik ke personal.


Kesimpulan

Cloud API = Best official option!

FeatureCloud API
HostingMeta-managed
SetupEasy
ReliabilityHigh
CostPay-per-use
TemplatesRequired for business-initiated

Start with Cloud API for production!

Integrate Cloud API →


Artikel Terkait