Getting Started
MSGly menyediakan REST API berkecepatan tinggi dengan autentikasi berbasis standar industri OAuth 2.0 (Client Credentials). Pengiriman pesan didukung oleh cluster antrean Redis asinkron dan device pool WhatsApp yang berputar secara dinamis (round-robin).
| Konfigurasi | Nilai Produksi |
|---|---|
| Production Base URL | https://api.msgly.id/api/v1 |
| Otentikasi | OAuth 2.0 (Bearer Token via Client Credentials) |
| Format Data | JSON (Request Body & Response), URL-Encoded (OAuth Token) |
| ID Idempotency | xid (Wajib unik per transaksi pengiriman) |
Alur Persiapan Integrasi
- Login ke Dashboard MSGly: Akses dashboard.msgly.id dengan akun Client Anda.
- Buat API Client: Masuk ke menu API Client di sidebar, lalu klik Create New API Client. Masukkan nama aplikasi dan daftarkan
Webhook URL(opsional) untuk callback status delivery. - Simpan Kredensial: Salin
client_iddanclient_secretAnda. Pastikan menyimpannya di environment variable backend. - Request Access Token: Tukar Client ID & Secret dengan Bearer Token melalui endpoint
POST /api/v1/oauth/token. - Kirim Pesan: Kirim WhatsApp OTP atau pesan tunggal melalui endpoint
POST /api/v1/message.
client_secret pada kode frontend (React, Vue, mobile apps, atau browser scripts). Seluruh interaksi dengan API MSGly wajib dilakukan dari server/backend Anda.
Authentication (OAuth 2.0)
MSGly menggunakan grant type client_credentials. Kredensial client_id dan client_secret ditukarkan dengan Access Token yang berlaku selama 24 jam (86.400 detik).
Mendapatkan access token Bearer untuk otentikasi request berikutnya.
Request Header & Body (application/x-www-form-urlencoded):
| Parameter | Tipe | Wajib | Deskripsi |
|---|---|---|---|
grant_type | string | Wajib | Harus bernilai tepat client_credentials |
client_id | string | Wajib | Client ID yang diterbitkan dari Dashboard MSGly |
client_secret | string | Wajib | Client Secret yang diterbitkan dari Dashboard MSGly |
curl -X POST https://api.msgly.id/api/v1/oauth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials&client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET"
{
"success": true,
"message": "token issued",
"data": {
"access_token": "msgly_tk_eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 86400
}
}
/oauth/token pada setiap pengiriman pesan agar tidak terkena rate limit.
Kirim Pesan (/message)
Pengiriman pesan WhatsApp API eksternal dikirimkan melalui endpoint terpadu POST /api/v1/message dengan tipe otp. Sistem akan otomatis memilih WhatsApp device yang berstatus aktif dari device pool dan meng-enqueue pesan ke dalam antrean Redis dengan prioritas tertinggi.
Parameter Request (JSON Body):
| Field | Tipe | Wajib | Keterangan |
|---|---|---|---|
xid |
string | Wajib | ID unik transaksi Anda (Idempotency Key). Menjamin tidak ada pesan ganda terkirim saat terjadi retry jaringan. |
to |
string | Wajib | Nomor WhatsApp tujuan dalam format internasional (contoh: 628123456789). Awalan lokal 08... otomatis dinormalkan sistem ke 628.... |
type |
string | Wajib | Harus bernilai otp. |
code |
string | Wajib (Mode Rotasi) | Kode OTP angka/alfanumerik yang akan disubstitusikan ke template secara acak oleh server. |
template |
object | Opsional (Mode Manual) | Objek template spesifik { "template_id": "UUID", "params": ["..."] } bila tidak menggunakan rotasi otomatis. |
{
"messages": {
"id": "7c4817a5-d85c-48c0-845f-c9ab579899eb",
"xid": "trx-unique-001",
"status": "queued",
"timestamp": 1718451123456
}
}
queued beserta id (MSGly Message UUID) dalam waktu < 50ms. Status delivery lanjutan (sent, delivered, read, failed) dan WhatsApp Message ID (oid) akan dikirimkan secara asinkron melalui Webhook Callback.
WhatsApp OTP
Pengiriman kode verifikasi OTP WhatsApp dirancang dengan latensi minimal dan tingkat pengiriman tinggi. MSGly mendukung dua skenario integrasi:
Skenario A: OTP Template Rotation (Direkomendasikan)
Jika fitur OTP Rotation diaktifkan untuk akun Anda di Dashboard, server MSGly secara dinamis memilih template pesan acak dari template yang telah di-whitelist. Anda cukup mengirimkan nomor tujuan dan kode OTP-nya saja. Cara ini terbukti paling efektif menjaga performa nomor sender dari deteksi spam WhatsApp.
{
"xid": "otp-trx-993",
"to": "628123456789",
"type": "otp",
"code": "482019"
}
Skenario B: Manual Template Selection
Jika Anda perlu menggunakan template tertentu (misalnya template login khusus atau registrasi tertentu), sertakan UUID template_id dan array params.
{
"xid": "otp-trx-992",
"to": "628123456789",
"type": "otp",
"template": {
"template_id": "c8f7a1b2-3c4d-5e6f-7a8b-9c0d1e2f3a4b",
"params": ["482019"]
}
}
WhatsApp Blast (Campaign)
Untuk pengiriman pesan promosi dan broadcast massal ke ribuan kontak sekaligus, MSGly menyediakan Campaign Blast Engine terintegrasi di Dashboard MSGly:
| Fitur Proteksi Blast | Mekanisme Kerja |
|---|---|
| Device Pool Auto-Distribution | Daftar penerima campaign didistribusikan secara round-robin ke seluruh device WhatsApp yang terhubung di pool akun Anda, menjaga beban kirim per device tetap seimbang. |
| Dynamic Throttling & Delays | Jeda antar pesan diacak (randomized interval delay) untuk menghindari pola pengiriman bot yang mencurigakan bagi WhatsApp. |
| Chat Presence Simulation | Worker otomatis mengirimkan sinyal composing (mengetik) beberapa detik sebelum pesan dikirimkan, mensimulasikan perilaku pengguna manusia asli. |
| Realtime Stop & Pause | Campaign dapat dipause, dibatalkan, atau dijadwalkan secara real-time langsung melalui dashboard. |
Webhooks & Delivery Status
Daftarkan Webhook URL pada pengaturan API Client Anda untuk menerima notifikasi callback secara real-time saat status pesan berubah.
Siklus Status Pengiriman (Delivery Lifecycle)
queued: Pesan berhasil diterima oleh API dan masuk ke antrean worker Redis.sent: Pesan berhasil dikirimkan oleh device WhatsApp gateway ke server WhatsApp.delivered: Pesan telah sampai di perangkat penerima (centang dua abu-abu).read: Pesan telah dibuka dan dibaca oleh penerima (centang dua biru).failed: Pesan gagal terkirim (misal: nomor tujuan tidak terdaftar di WhatsApp atau device gateway offline).
{
"event": "message.status",
"data": {
"id": "7c4817a5-d85c-48c0-845f-c9ab579899eb",
"xid": "trx-unique-001",
"recipient": "628123456789",
"status": "delivered",
"oid": "3EB0B892819024D98A",
"timestamp": 1718451125000,
"error": ""
}
}
2xx atau terjadi timeout. Pastikan endpoint webhook Anda mengembalikan respon HTTP 200 OK dengan cepat.
Error Codes & Response
Jika terjadi kendala validasi, autentikasi, atau saldo, API akan mengembalikan HTTP status code yang sesuai beserta objek error berformat JSON:
{
"error": {
"message": "duplicate xid"
}
}
| HTTP Status | Pesan Error | Penyebab & Solusi |
|---|---|---|
400 Bad Request |
duplicate xid |
Nilai xid ini sudah pernah digunakan sebelumnya. Gunakan ID unik yang baru untuk setiap transaksi. |
400 Bad Request |
invalid phone number |
Nomor penerima tidak valid atau memiliki format karakter yang salah. |
400 Bad Request |
insufficient balance |
Saldo wallet akun Anda tidak mencukupi untuk memproses pengiriman pesan. Lakukan topup saldo melalui dashboard. |
400 Bad Request |
template not found |
UUID template_id yang dikirim tidak ditemukan atau belum disetujui. |
401 Unauthorized |
The access token has expired |
Access token OAuth 2.0 telah habis masa berlakunya. Lakukan request token baru via /oauth/token. |
429 Too Many Requests |
rate limit exceeded |
Jumlah request melebihi batas rate limit akun Anda (default: 100 req/menit). Tunggu beberapa saat sebelum mencoba kembali. |
Rate Limits
Untuk menjaga kestabilan sistem dan mencegah lonjakan lalu lintas yang tidak wajar, setiap API Client memiliki batasan kecepatan request:
| Area Endpoint | Default Limit | Mekanisme Kontrol |
|---|---|---|
POST /api/v1/message |
100 request / menit per Client ID | Redis distributed rate limiter (Sliding Window). Hubungi tim sales jika aplikasi Anda memerlukan limit throughput lebih besar. |
POST /api/v1/oauth/token |
20 request / menit per IP | Proteksi brute-force token generation. Simpan token selama 24 jam. |
Official SDKs & Libraries
MSGly menyediakan pustaka (SDK) resmi untuk mempermudah integrasi ke backend Anda tanpa perlu mengelola OAuth token refresh, serialisasi JSON, ataupun parsing error secara manual.
| Bahasa | Package Manager | Perintah Instalasi |
|---|---|---|
| Node.js (JS/TS) | NPM | npm install msgly-sdk |
| Go (Golang) | Go Modules | go get github.com/msgly-official/msgly-sdk-go |
| Python | PyPI | pip install msgly-sdk |
| PHP | Composer | composer require msgly/msgly-sdk-php |
| Java | JitPack (Maven / Gradle) | com.github.msgly-official:msgly-sdk-java:v1.0.0 |
Contoh Integrasi Lengkap per Bahasa
import { MsglyClient } from 'msgly-sdk';
const msgly = new MsglyClient({
baseUrl: 'https://api.msgly.id', // Opsional, default https://api.msgly.id
clientId: 'YOUR_CLIENT_ID',
clientSecret: 'YOUR_CLIENT_SECRET'
});
// 1. Kirim WhatsApp OTP (Mode Rotasi Otomatis)
try {
const otpResponse = await msgly.message.sendOTP({
xid: 'otp_' + Date.now(),
to: '6281234567890',
code: '482910'
});
console.log('OTP Queued ID:', otpResponse.messages.id);
} catch (error) {
console.error('Gagal mengirim OTP:', error.message);
}
// 2. Kirim Pesan Tunggal / Reminder
try {
const singleResponse = await msgly.message.sendSingle({
xid: 'rem_' + Date.now(),
to: '6281234567890',
message: 'Halo, pesanan Anda #INV-1029 telah selesai diproses.'
});
console.log('Message Queued ID:', singleResponse.messages.id);
} catch (error) {
console.error('Gagal mengirim pesan:', error.message);
}
package main
import (
"context"
"fmt"
"log"
"time"
msgly "github.com/msgly-official/msgly-sdk-go"
)
func main() {
client := msgly.New(msgly.Config{
BaseURL: "https://api.msgly.id",
ClientID: "YOUR_CLIENT_ID",
ClientSecret: "YOUR_CLIENT_SECRET",
})
ctx := context.Background()
// 1. Kirim WhatsApp OTP (Mode Rotasi Otomatis)
otpResp, err := client.Message.SendOTP(ctx, msgly.SendOTPRequest{
XID: fmt.Sprintf("otp_%d", time.Now().Unix()),
To: "6281234567890",
Code: "482910",
})
if err != nil {
log.Fatalf("Error kirim OTP: %v", err)
}
fmt.Printf("OTP Queued! ID: %s, Status: %s\n", otpResp.Messages.ID, otpResp.Messages.Status)
// 2. Kirim Pesan Tunggal / Reminder
singleResp, err := client.Message.SendSingle(ctx, msgly.SendSingleRequest{
XID: fmt.Sprintf("rem_%d", time.Now().Unix()),
To: "6281234567890",
Message: "Halo! Jadwal konsultasi Anda terkonfirmasi besok pukul 10:00 WIB.",
})
if err != nil {
log.Fatalf("Error kirim pesan: %v", err)
}
fmt.Printf("Pesan Queued! ID: %s\n", singleResp.Messages.ID)
}
import time
from msgly import MsglyClient
client = MsglyClient(
client_id="YOUR_CLIENT_ID",
client_secret="YOUR_CLIENT_SECRET",
base_url="https://api.msgly.id"
)
# 1. Kirim WhatsApp OTP (Mode Rotasi Otomatis)
try:
otp_resp = client.message.send_otp(
xid=f"otp_{int(time.time())}",
to="6281234567890",
code="482910"
)
print("OTP Queued ID:", otp_resp["messages"]["id"])
except Exception as e:
print("Error kirim OTP:", e)
# 2. Kirim Pesan Tunggal / Reminder
try:
single_resp = client.message.send_single(
xid=f"rem_{int(time.time())}",
to="6281234567890",
message="Halo Budi, pembayaran Anda telah berhasil kami verifikasi."
)
print("Message Queued ID:", single_resp["messages"]["id"])
except Exception as e:
print("Error kirim pesan:", e)
<?php
require_once 'vendor/autoload.php';
use Msgly\MsglyClient;
use Msgly\Exceptions\MsglyException;
$msgly = new MsglyClient([
'base_url' => 'https://api.msgly.id',
'client_id' => 'YOUR_CLIENT_ID',
'client_secret' => 'YOUR_CLIENT_SECRET',
]);
// 1. Kirim WhatsApp OTP (Mode Rotasi Otomatis)
try {
$result = $msgly->message()->sendOTP([
'xid' => 'otp_' . time(),
'to' => '6281234567890',
'code' => '482910',
]);
echo "OTP Queued! ID: " . $result['messages']['id'] . PHP_EOL;
} catch (MsglyException $e) {
echo "Gagal kirim OTP: " . $e->getMessage() . PHP_EOL;
}
// 2. Kirim Pesan Tunggal / Reminder
try {
$single = $msgly->message()->sendSingle([
'xid' => 'rem_' . time(),
'to' => '6281234567890',
'message' => 'Halo, pesanan Anda #ORD-998 telah kami kirim via kurir.',
]);
echo "Pesan Queued! ID: " . $single['messages']['id'] . PHP_EOL;
} catch (MsglyException $e) {
echo "Gagal kirim pesan: " . $e->getMessage() . PHP_EOL;
}
?>
import id.msgly.MsglyClient;
import id.msgly.message.SendMessageRequest;
import id.msgly.message.SendMessageResponse;
public class App {
public static void main(String[] args) {
MsglyClient client = MsglyClient.builder()
.baseUrl("https://api.msgly.id")
.clientId("YOUR_CLIENT_ID")
.clientSecret("YOUR_CLIENT_SECRET")
.build();
// 1. Kirim WhatsApp OTP (Mode Rotasi Otomatis)
try {
SendMessageResponse otpResp = client.message().sendOtp(
SendMessageRequest.builder()
.xid("otp_" + System.currentTimeMillis())
.to("6281234567890")
.code("482910")
.build()
);
System.out.println("OTP Queued ID: " + otpResp.getMessages().getId());
} catch (Exception e) {
e.printStackTrace();
}
}
}
