Panduan/Untuk developer

Mengirim WhatsApp dari aplikasi saya sendiri (API)

Autentikasi, ambil template, kirim — dengan contoh curl, Node, dan PHP. 7 menit baca

WACO menyediakan API sederhana supaya aplikasi Anda sendiri — sistem absensi, tagihan, antrean, PPDB — bisa mengirim WhatsApp lewat nomor resmi Anda. Dua endpoint, satu header autentikasi. Tidak perlu menyentuh dashboard Meta.

Autentikasi

Buat kunci API di halaman Developer. Kunci berbentuk waco_… dan hanya tampil sekali — simpan baik-baik. Kirim di setiap permintaan:

Authorization: Bearer waco_KUNCI_ANDA

Base URL: https://waco.id. Kunci yang dicabut, atau tenant yang ditangguhkan karena tagihan, langsung berhenti bekerja.

1. Lihat template yang siap dipakai

curl https://waco.id/api/v1/template \
  -H "Authorization: Bearer waco_KUNCI_ANDA"

Jawaban berisi hanya template yang sudah disetujui Meta:

{
  "template": [
    { "nama": "absensi_hadir", "bahasa": "id", "kategori": "UTILITY",
      "isi": "Halo {{1}}, {{2}} hadir pukul {{3}}.",
      "jumlah_nilai": 3, "tombol": [] }
  ]
}

jumlah_nilai memberi tahu berapa nilai yang harus Anda kirim untuk mengisi {{1}}, {{2}}, dan seterusnya.

2. Kirim notifikasi

curl -X POST https://waco.id/api/v1/kirim \
  -H "Authorization: Bearer waco_KUNCI_ANDA" \
  -H "Content-Type: application/json" \
  -d '{
    "nomor": "628123456789",
    "nama": "Ibu Ani",
    "template": "absensi_hadir",
    "isi": ["Budi", "Budi", "07:15"]
  }'

Medan: nomor (E.164 tanpa +, wajib), template (wajib), isi (larik nilai variabel — jumlahnya harus sama dengan jumlah_nilai), nama (opsional, untuk pengenalan kontak). Template berheader gambar wajib membawa gambar_url (https publik, JPEG/PNG ≤5 MB) — Meta tidak menyimpan gambar contoh, jadi tiap kiriman menyebut gambarnya lagi; template berheader PDF memakai dokumen_url (+ dokumen_nama opsional). Jawaban sukses:

{ "status": "terkirim", "message_id": "wamid.HBg…", "percakapan_id": 81 }

message_id adalah wamid dari WhatsApp — simpan ini, karena pesan_id pada webhook message.status memakai id yang sama. Itulah cara melacak sent → delivered → read per pesan. percakapan_id hanya muncul kalau nomor Anda punya kotak masuk; akun mode API murni tidak mendapatkannya.

Contoh Node.js

const res = await fetch('https://waco.id/api/v1/kirim', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer ' + process.env.WACO_KEY,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    nomor: '628123456789',
    template: 'absensi_hadir',
    isi: ['Budi', 'Budi', '07:15'],
  }),
});
const data = await res.json();

Contoh PHP

$ch = curl_init('https://waco.id/api/v1/kirim');
curl_setopt_array($ch, [
  CURLOPT_POST => true,
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => [
    'Authorization: Bearer ' . getenv('WACO_KEY'),
    'Content-Type: application/json',
  ],
  CURLOPT_POSTFIELDS => json_encode([
    'nomor' => '628123456789',
    'template' => 'absensi_hadir',
    'isi' => ['Budi', 'Budi', '07:15'],
  ]),
]);
$data = json_decode(curl_exec($ch), true);

Membalas percakapan (tanpa template)

Kalau pelanggan baru saja mengirim pesan (dalam 24 jam terakhir), Anda bisa membalas teks bebas tanpa template — cocok untuk alur interaktif: terima balasan lewat webhook, lalu jawab lewat sini.

curl -X POST https://waco.id/api/v1/balas \
  -H "Authorization: Bearer waco_KUNCI_ANDA" \
  -H "Content-Type: application/json" \
  -d '{
    "nomor": "628123456789",
    "teks": "Baik Bu, pendaftaran atas nama Ananda sudah kami terima."
  }'

Jawaban: { "status": "terkirim", "message_id": "wamid…" }. Batas teks 4096 karakter.

Hanya berlaku dalam jendela 24 jam. Di luar itu Meta menolak (kode 131047) dan Anda harus memakai /api/v1/kirim dengan template. Kenapa begitu, ada di panduan template.

Mengirim media (gambar, dokumen, video, audio)

Kirim file lewat URL publik — Meta yang mengunduhnya, jadi Anda tidak perlu mengunggah dulu. Cocok untuk hasil lab, invoice PDF, atau foto. Sama seperti balas, ini hanya dalam jendela 24 jam.

curl -X POST https://waco.id/api/v1/kirim-media \
  -H "Authorization: Bearer waco_KUNCI_ANDA" \
  -H "Content-Type: application/json" \
  -d '{
    "nomor": "628123456789",
    "tipe": "document",
    "url": "https://app.anda.com/invoice/INV-001.pdf",
    "filename": "Invoice-INV-001.pdf",
    "caption": "Invoice pendaftaran"
  }'

tipe: image, document, video, atau audio. url wajib HTTPS dan dapat diakses publik. caption opsional (tidak untuk audio); filename hanya untuk document. Batas ukuran mengikuti WhatsApp (mis. dokumen 100 MB, gambar 5 MB).

Membuat template lewat API

Template juga bisa dibuat dari aplikasi Anda, tanpa membuka dashboard:

curl -X POST https://waco.id/api/v1/template \
  -H "Authorization: Bearer waco_KUNCI_ANDA" \
  -H "Content-Type: application/json" \
  -d '{
    "nama": "konfirmasi_pesanan",
    "kategori": "UTILITY",
    "isi": "Halo {{1}}, pesanan {{2}} sudah kami terima.",
    "contoh": ["Budi", "INV-123"]
  }'

Jawaban sukses (201): { "id": "…", "status": "PENDING", … }.

Penting: sukses berarti diajukan, belum bisa dipakai. Setiap template ditinjau Meta dulu — biasanya beberapa menit sampai beberapa jam, dan bisa ditolak. Pantau statusnya sampai APPROVED:

curl "https://waco.id/api/v1/template?status=semua" \
  -H "Authorization: Bearer waco_KUNCI_ANDA"

Dengan ?status=semua, tiap template membawa kolom status (PENDING / APPROVED / REJECTED) dan alasan_tolak bila ditolak. Setelah APPROVED, kirim lewat /kirim seperti biasa.

Medan lain yang tersedia: bahasa (bawaan id), footer (≤60 karakter), tombol (balasan cepat, maks 3), tombol_url ({"teks":"…","url":"https://…"}), dan untuk kategori AUTHENTICATION objek otp — isi badannya disusun Meta, jangan menulis sendiri. Aturan yang paling sering membuat pengajuan ditolak sudah kami periksa lebih dulu: jumlah contoh wajib sama dengan banyaknya variabel di isi.

Menghapus: DELETE /api/v1/template/nama_template. Nama yang dihapus dikarantina Meta 30 hari — tidak bisa langsung dipakai ulang.

Template bergambar (blast dengan media)

Pesan template bisa memuat gambar di atas teks (header gambar) — cocok untuk blast promo berposter atau pengingat dengan foto. Tiga jalan, semuanya sudah tersedia:

curl -X POST https://waco.id/api/v1/template \
  -H "Authorization: Bearer waco_KUNCI_ANDA" \
  -H "Content-Type: application/json" \
  -d '{
    "nama": "promo_september",
    "kategori": "MARKETING",
    "isi": "Halo {{1}}, promo September sudah dibuka. Lihat posternya di atas ya!",
    "contoh": ["Budi"],
    "gambar_url": "https://cdn.tokoanda.id/poster-september.jpg"
  }'

# setelah APPROVED:
curl -X POST https://waco.id/api/v1/kirim \
  -H "Authorization: Bearer waco_KUNCI_ANDA" \
  -H "Content-Type: application/json" \
  -d '{
    "nomor": "628123456789",
    "template": "promo_september",
    "isi": ["Budi"],
    "gambar_url": "https://cdn.tokoanda.id/poster-september.jpg"
  }'

Gambar harus JPEG/PNG ≤5 MB di URL https yang bisa diunduh publik. Pesan bebas bergambar di dalam jendela 24 jam tetap lewat /api/v1/kirim-media dengan caption; di luar jendela itu, satu-satunya jalan adalah template berheader gambar seperti di atas. Header PDF dan video belum bisa dibuat lewat API — buat dari dashboard.

Memilih nomor pengirim (multi-cabang)

Punya lebih dari satu nomor (mis. tiap cabang klinik)? Tambahkan dari untuk memilih nomor mana yang mengirim. Tanpa dari, dipakai nomor pertama Anda. Berlaku untuk /kirim, /balas, dan /kirim-media:

curl -X POST https://waco.id/api/v1/kirim \
  -H "Authorization: Bearer waco_KUNCI_ANDA" \
  -H "Content-Type: application/json" \
  -d '{
    "dari": "628158825011",
    "nomor": "628123456789",
    "template": "absensi_hadir",
    "isi": ["Budi", "Budi", "07:15"]
  }'

dari dicocokkan dengan nomor tampilan cabang Anda. Kalau tidak cocok dengan nomor mana pun, jawabannya 400 — jadi salah ketik nomor pengirim ketahuan, bukan diam-diam terkirim dari cabang lain.

Kode kesalahan

Kapan wajib template? Hanya saat Anda memulai chat ke orang yang belum membalas dalam 24 jam. Kalau mereka baru saja chat, Anda bebas membalas tanpa template. Selengkapnya di panduan template.

Untuk menerima balasan dan status pesan di aplikasi Anda, lihat Menerima balasan & status lewat webhook.

Masih menemui kendala setelah mengikuti panduan ini? Hubungi kami dari dashboard — sertakan tangkapan layar bila ada, itu mempercepat semuanya.