Chatera Docs
API & Integrasi

Template WhatsApp

Kirim template WhatsApp yang sudah disetujui Meta untuk komunikasi di luar jendela 24 jam.

Template WhatsApp adalah pesan pre-approved oleh Meta yang bisa dikirim kapan saja — bahkan ketika kontak belum mengirim pesan ke kamu dalam 24 jam terakhir. Template umumnya dipakai untuk OTP, notifikasi order, reminder pembayaran, dan promo.

Semua path di halaman ini relatif terhadap base URL https://api.chatera.id/v1.

Identitas template: name + language, bukan ID

Pengiriman template selalu memakai template.name + template.language.code — field id (UUID) di response list hanyalah identifier internal Chatera dan tidak bisa dipakai di body POST /v1/whatsapp/messages. Nama template tidak bisa diubah setelah dibuat di Meta, jadi aman dijadikan referensi stabil di integrasi kamu. (Alternatif: endpoint POST /v1/whatsapp/templates/{id}/send menerima UUID.)

List template yang tersedia

GET /v1/whatsapp/templates

Scope yang dibutuhkan: whatsapp:templates

Endpoint ini mengembalikan daftar template yang sudah tersinkron dari Meta Business Manager dan siap dipakai (status APPROVED).

Query paramWajibKeterangan
channel_idUUID channel WhatsApp. Sangat disarankan bila akun punya lebih dari satu channel — tanpa ini dipakai channel aktif terbaru. Channel tidak ditemukan → WHATSAPP_CHANNEL_NOT_FOUND
pageHalaman (default 1)
per_pageJumlah per halaman
curl -X GET "https://api.chatera.id/v1/whatsapp/templates" \
  -H "Authorization: Bearer chatera_sk_xxxxx"

Response list

{
  "success": true,
  "data": [
    {
      "id": "9b8c1234-e5f6-4789-90ab-cdef01234567",
      "name": "order_confirmation",
      "category": "UTILITY",
      "status": "APPROVED",
      "languages": [
        { "code": "id", "status": "APPROVED" }
      ],
      "components": [
        { "type": "HEADER", "format": "TEXT", "text": "Konfirmasi Order" },
        {
          "type": "BODY",
          "text": "Halo {{1}}, order {{2}} sudah kami terima.",
          "example": { "body_text": [["Hafari", "ORD-12345"]] }
        },
        { "type": "FOOTER", "text": "Terima kasih." }
      ],
      "channel_id": "1ec6a154-02fa-49f4-bad0-ab9f89a5eb85",
      "created_at": "2026-04-27T10:30:00Z",
      "updated_at": "2026-04-27T10:30:00Z"
    }
  ],
  "meta": { "page": 1, "per_page": 25, "total": 1, "has_more": false }
}
FieldTipeKeterangan
idstring (UUID)Identifier internal Chatera — bukan untuk body template.name
namestringNama template di Meta. Ini yang dipakai saat kirim
categorystringAUTHENTICATION / MARKETING / UTILITY
statusstringSelalu APPROVED di endpoint ini
languages[]arrayBahasa yang tersedia: { code, status }. Pakai code yang ber-status APPROVED sebagai template.language.code saat kirim
components[]arrayStruktur template dari Meta: HEADER/BODY/FOOTER/BUTTONS. Variabel posisional tampil sebagai {{1}}, {{2}}, dst. di text
channel_idstring (UUID)Channel pemilik template — kirim channel_id yang sama di POST /messages supaya template pasti tersedia di nomor tujuan
created_at / updated_atstringTimestamp sinkronisasi

Mengirim template

Ada dua cara mengirim template — gunakan endpoint /messages untuk konsistensi.

POST /v1/whatsapp/messages

Scope: whatsapp:send

Body memakai type: template dan field template:

{
  "to": "628123456789",
  "type": "template",
  "template": {
    "name": "otp_verification",
    "language": { "code": "id" },
    "components": [...]
  }
}
FieldWajibKeterangan
template.nameNama template (sesuai yang terdaftar di Meta) — bukan UUID dari list
template.language.codeKode bahasa persis seperti saat template dibuat di Meta, mis. id, en, en_US. Lihat languages[].code di response list — kode yang salah menghasilkan error Meta #132001
template.componentstergantung templateKomponen yang berisi parameter dinamis
channel_idUUID channel WhatsApp pengirim. Wajib secara praktik bila punya lebih dari satu channel — pakai channel_id yang sama dengan yang muncul di response list supaya template pasti terdaftar di nomor pengirim

Kirim lewat endpoint template

Alternatif dari /messages: endpoint ini menerima UUID template Chatera (dari response list) atau nama template di path.

POST /v1/whatsapp/templates/{templateId}/send

Scope: whatsapp:send

curl -X POST "https://api.chatera.id/v1/whatsapp/templates/9b8c1234-e5f6-4789-90ab-cdef01234567/send" \
  -H "Authorization: Bearer chatera_sk_xxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "to": "628123456789",
    "components": [
      { "type": "body", "parameters": [{ "type": "text", "text": "Hafari" }] }
    ]
  }'
FieldWajibKeterangan
{templateId} (path)UUID template dari list, atau langsung nama template
toNomor tujuan E.164
languageKode bahasa. Bila templateId UUID dan field ini kosong, otomatis dipakai bahasa translation yang APPROVED; bila pakai nama template, default id
componentstergantung templateSama seperti template.components di /messages
channel_idOverride channel pengirim. Bila kosong dan templateId UUID, otomatis dipakai channel pemilik template

Kelebihan jalur UUID: nama, bahasa, dan channel di-resolve dari data template tersimpan — menghilangkan dua penyebab paling umum error #132001 (salah language.code dan salah channel).

Struktur komponen

Komponen template dipisah berdasarkan posisinya di template:

typeFungsiParameter yang valid
headerMedia / lokasi di header pesantext, image, video, document, location
bodyVariabel di bodytext, currency, date_time
buttonVariabel tombol (URL dinamis / payload)text (untuk sub_type: url), payload (untuk sub_type: quick_reply)

Contoh-contoh

1. Template OTP sederhana

{
  "to": "628123456789",
  "type": "template",
  "template": {
    "name": "otp_verification",
    "language": { "code": "id" },
    "components": [
      {
        "type": "body",
        "parameters": [
          { "type": "text", "text": "123456" }
        ]
      }
    ]
  }
}

2. Template dengan header gambar

{
  "to": "628123456789",
  "type": "template",
  "template": {
    "name": "order_confirmation",
    "language": { "code": "id" },
    "components": [
      {
        "type": "header",
        "parameters": [
          { "type": "image", "image": { "link": "https://toko-anda.com/products/item-1.jpg" } }
        ]
      },
      {
        "type": "body",
        "parameters": [
          { "type": "text", "text": "Pak Hafari" },
          { "type": "text", "text": "ORD-12345" }
        ]
      }
    ]
  }
}

3. Template dengan named parameter

Jika template kamu memakai variabel bernama (mis. {{customer_name}}):

{
  "to": "628123456789",
  "type": "template",
  "template": {
    "name": "promo_weekly",
    "language": { "code": "id" },
    "components": [
      {
        "type": "body",
        "parameters": [
          { "type": "text", "text": "John", "parameter_name": "customer_name" },
          { "type": "text", "text": "50%", "parameter_name": "discount" }
        ]
      }
    ]
  }
}

4. Template dengan tombol Quick Reply

{
  "to": "628123456789",
  "type": "template",
  "template": {
    "name": "order_status_check",
    "language": { "code": "id" },
    "components": [
      {
        "type": "body",
        "parameters": [
          { "type": "text", "text": "ORD-12345" }
        ]
      },
      {
        "type": "button",
        "sub_type": "quick_reply",
        "index": 0,
        "parameters": [{ "type": "payload", "payload": "track_shipment" }]
      },
      {
        "type": "button",
        "sub_type": "quick_reply",
        "index": 1,
        "parameters": [{ "type": "payload", "payload": "contact_support" }]
      }
    ]
  }
}
  • index adalah posisi tombol (0-based).
  • payload dikirim ke webhook ketika user menekan tombol.

5. Template dengan tombol URL dinamis

Template dengan URL tombol bernama {{1}}:

URL template di Meta: https://toko-anda.com/order/{{1}}
{
  "to": "628123456789",
  "type": "template",
  "template": {
    "name": "view_order_details",
    "language": { "code": "id" },
    "components": [
      {
        "type": "body",
        "parameters": [
          { "type": "text", "text": "John" }
        ]
      },
      {
        "type": "button",
        "sub_type": "url",
        "index": 0,
        "parameters": [
          { "type": "text", "text": "ORD-12345" }
        ]
      }
    ]
  }
}

Penerima akan melihat tombol yang membuka https://toko-anda.com/order/ORD-12345.

6. Template dengan header lokasi

{
  "to": "628123456789",
  "type": "template",
  "template": {
    "name": "store_location",
    "language": { "code": "id" },
    "components": [
      {
        "type": "header",
        "parameters": [
          {
            "type": "location",
            "location": {
              "latitude": -6.2,
              "longitude": 106.816666,
              "name": "Toko ABC Cabang Sudirman",
              "address": "Jl. Sudirman No. 123, Jakarta"
            }
          }
        ]
      }
    ]
  }
}

7. Template dengan currency

{
  "to": "628123456789",
  "type": "template",
  "template": {
    "name": "payment_reminder",
    "language": { "code": "id" },
    "components": [
      {
        "type": "body",
        "parameters": [
          { "type": "text", "text": "John" },
          {
            "type": "currency",
            "currency": {
              "fallback_value": "Rp 250.000",
              "code": "IDR",
              "amount_1000": 250000000
            }
          }
        ]
      }
    ]
  }
}

Konversi `amount_1000`

amount_1000 menyimpan nilai dalam unit terkecil × 1000 untuk menghindari floating-point error:

  • IDR (Rupiah): Rp 250.000 → 250000 × 1000 = 250000000
  • USD (Dolar): $25,50 → 25.50 × 1000 = 25500
  • MYR (Ringgit): RM 99,99 → 99.99 × 1000 = 99990

fallback_value adalah teks tampilan yang dipakai kalau penerima WhatsApp tidak mendukung format currency native.

Response sukses

{
  "success": true,
  "data": {
    "messageId": "9b8c1234-e5f6-4789-90ab-cdef01234567",
    "whatsappMessageId": "wamid.HBgNNjI4MTIz...",
    "status": "sent",
    "to": "+628123456789",
    "template": "order_confirmation",
    "timestamp": "2026-04-27T10:30:00Z"
  }
}

Pesan error template

KodePenyebabSolusi
WHATSAPP_TEMPLATE_NOT_FOUNDNama template tidak ditemukan / belum approvedCek nama dan status di Meta Business Manager
WHATSAPP_TEMPLATE_REJECTEDTemplate ditolak MetaPerbaiki konten template di Meta lalu submit ulang
WHATSAPP_TEMPLATE_INVALID_COMPONENTSStruktur components tidak validLihat details.errors[]
WHATSAPP_TEMPLATE_MISSING_BUTTON_INDEXKomponen button tidak punya indexTambahkan index: 0 (atau 1, 2, dst sesuai posisi)
WHATSAPP_TEMPLATE_INVALID_PARAMETER_TYPETipe parameter tidak cocok dengan komponenMis. currency di komponen header (tidak diperbolehkan)
WHATSAPP_SEND_FAILEDMeta menolak requestBaca details.error — berisi pesan error asli dari Meta (lihat contoh di bawah)

Detail error contoh

Validasi komponen (dari Chatera, sebelum request ke Meta):

{
  "success": false,
  "error": {
    "code": "WHATSAPP_TEMPLATE_INVALID_COMPONENTS",
    "message": "Template components validation failed",
    "details": {
      "errors": [
        {
          "field": "components[2].index",
          "message": "Button component requires index field (0-based button position)"
        }
      ]
    }
  }
}

Penolakan dari Meta (WHATSAPP_SEND_FAILED) — pesan asli Meta diteruskan apa adanya di details.error:

{
  "success": false,
  "error": {
    "code": "WHATSAPP_SEND_FAILED",
    "message": "Failed to send WhatsApp message",
    "details": {
      "error": "(#132001) Template name does not exist in the translation"
    }
  }
}

Troubleshooting #132001

Error Meta (#132001) Template name does not exist in the translation artinya kombinasi nama + bahasa + nomor pengirim tidak menemukan template. Tiga penyebab paling umum, urut dari yang paling sering:

  1. Salah language.code — template dibuat dengan bahasa en tapi kamu kirim id (atau sebaliknya). Cocokkan dengan languages[].code di response list.
  2. Salah channel — template terdaftar di channel/nomor lain. Kirim channel_id yang sama dengan channel_id template di response list.
  3. Template sudah tidak ada di Meta — mis. nomor lama dilepas/diblokir. Lakukan sinkronisasi ulang template dari dashboard; template yang sudah hilang di Meta akan dinonaktifkan otomatis dari list.

On this page