Kami menambahkan fitur lagi di awal februari 2025.
fokus pada update ini terkait penambahan fitur dan optimasi.
TL;DR
Tambahan fitur dan optimasi :
Webhook sekarang dapat menggunakan tambahan secret key sebagai tambahan data untuk memverifikasi webhook ini berasal dari fonnte.
pencarian pesan sekarang bisa dilakukan dengan menggunakan idnya.
hal ini berguna untuk melihat data spesifik berdasarkan idnya.
fitur ini dibuat sebagai support untuk menu inbox.
ketika menghapus pesan yang sedang dalam proses, pesan ini tidak bisa dibatalkan meskipun menghapus pesannya di message history.
sekarang, kamu bisa membatalkannya dengan menghapus pesan dari menu message history.
contoh : kamu mengirim 5 pesan dengan delay 10 detik. kemudian ternyata ada kesalahan di pesannya. sebelumnya kamu tidak bisa membatalkannya meski sudah dihapus dari message history karena sudah di proses, hanya menunggu penjadwalan/antrian pengiriman. sekarang kamu bisa membatalkannya dengan cara menghapusnya dari message history dan pesannya tidak akan diproses lagi.
seiring penambahan user fonnte, semakin banyak user fonnte yang menggunakan API. yang artinya semakin banyak juga yang terkendala saat menggunakan APInya. beberapa user komplain karena pesannya tidak sesuai dengan apa yang di request ke fonnte.
tapi saat ditanya requestnya apa, hampir semua tidak menyimpan log requestnya yang berakibat pada pengambilan keputusan sepihak bahwa ini adalah "salah fonnte" ketimbang bersama mencari kendala dan menyesuaikan requestnya.
jadi kami berinisiatif untuk membantu membuat log untuk request dan responsenya, agar user dan fonnte sama-sama dapat mengecek requestnya dan membuat win win solution bersama dan yang lebih penting lagi adalah kami bisa membantu user dengan lebih baik.
requestid ada di setiap API request terlepas dari responsenya sukses atau gagal.
sebelumnya kami memproses semua pesan masuk untuk device yang mengaktifkan autoread ke on.
proses ini menggunakan banyak resource server seiring dengan penambahan fitur dari whatapp.
sekarang kami membatasi apa saja yang perlu diproses dan tidak, sehingga penggunaan resource server bisa lebih ringan dan membuat performa secara keseluruhan menjadi lebih baik.
fonnte akan menyimpan pesan masuk jika diminta.
kamu bisa mengaktifkannya dengan mengaktifkan autoread ke on dan inbox ke on di menu device->edit.
ketika menggunakan webhook, pesan yang dibalas tidak bisa di quote.
sekarang, ada tambahan data dengan key inboxid.
ketika mengaktifkan inbox, webhook akan memiliki inboxid yang bisa digunakan untuk melakukan quote terhadap pesan yang akan dibalas.
jadi, untuk membalas pesan kamu hanya perlu menambahkan inboxid di API send.
Fonnte menggunakan BCA scrapper untuk konfirmasi pembayaran secara otomatis.
tapi belakangan ini scrappernya semakin banyak gagal dan semakin sulit diandalkan.
beberapa order sudah dibayar dan tidak terproses otomatis sampai akhirnya statusnya failed.
jadi kami membuat solusi lain (karena kami masih belum memutuskan untuk menggunaakn payment gateway), kami menambahkan fitur deposit.
fitur ini kemungkinan besar tidak digunakan oleh sebagian besar user, karena deposit berarti membayar dulu di depan untuk digunakan nanti, padahal fonnte sudah ada fitur custom durasi order.
jadi sebagian besar user memang sepertinya tidak akan menggunakan fitur deposit.
jadi, untuk siapa deposit ini?
kami memperkenalkan API order yang bersamaan dengan sistem deposit ini bisa membuat sistem autoconfirm.
fitur ini kemungkinan besar akan digunakan oleh agensi/lainnya yang membutuhkan autoconfirm saat melakukan order di fonnte. sehingga integrasinya bisa berjalan mulus beserta dengan device management API.
autoconfirm digunakan untuk membuat order otomatis aktif jika menggunakan sistem pembayaran deposit.
dengan demikian, kamu bisa mengaktifkan order segera tanpa harus menunggu BCA scrapper fonnte bekerja atau diproses manual.
fitur ini sangat berguna untuk pelaku bisnis/agensi.
API order sekarang tersedia utnuk digunakan langsung di sistem sendiri.
untuk menggunakan API order, kamu memerlukan deposit terlebih dahulu.
tanpa deposit, responnya akan selalu false karena API order menggunakan autoconfirm.
lihat dokumentasi API order atau langsung ke postman.
Ketika download pesan attachment, kadang filenya corrupt, terutama jika filenya berukuran besar.
kami melakukan fix untuk ini dan file dapat didownload dengan benar.
Di awal tahun 2025, kami sudah membuat beberapa update untuk fonnte. kami menambahkan beberapa fitur dan mengubah cara kerja beberapa item.
Delay sekarang langsung aktif untuk semua target. sebelumnya, delay cuma bekerja untuk multple. sebenarnya, walaupun cara ini bagus untuk memaksakan target pertama untuk segera dikirim tanpa menunggu delay, ternyata tindakan ini tidak diharapkan oleh kebanyakan user fonnte. ketika menggunakan delay, harapannya adalah ada jeda pengiriman, terlepas dari jumlah targetnya. jadi kami mengubah cara kerja delay menjadi delay setiap target, terlepas dari jumlah targetnya.
Kami menambahkan flow untuk mempermudah pembuatan chatbot. sebenarnya ini sama seperti autoreply, chaining dan submission. hanya saja dibuat secara visual. dan bagusnya lagi, chatbot bisa dibuat dengan mengkombinasikan semuanya jika dibutuhkan.
selain itu, AI juga hanya support via flow
Jika kamu menggunakan AI, kamu bisa mensetting AI sesuai kebutuhan.
Fonnte menyediakan fitur untuk membuat AI membalas dengan data sendiri. dengan menggunakan data sendiri, AI akan bertindak seperti pesonal assistant untuk knowledgebase sendiri.
Kami menambahkan response source di menu device->edit. sekarang ada 3 response source : autoreply, spreadsheet dan flow.
Spreadsheet tetap hanya bisa digunakan untuk paket regular keatas.
Kami tidak berencana untuk menonaktifkan autoreply, chaining dan submission. setidaknya tidak dalam waktu dekat.
tapi menggunakan flow lebih memudahkan dan dapat diprediksi karena pembuatannya secara visual.
kami menyarankan mulai sekarang untuk membuat chatbot menggunakan flow.
Kami juga membuat order semakin mudah dengan menambahkan durasi custom dan lifetime untuk AI.
Kamu bisa order 3 bulan atau berapa bulan/tahun sesuai yang dibutuhkan.
Untuk kebanyakan user fonnte, menggunakan variabel seperti 081|admin|fonnte memang sangat memudahkan. tapi penggunaan variabel ini memiliki batasan.
oleh karena itu, kami membuat integrasi ke google spreadsheet sebagai solusi. spreadsheet ini semudah penggunaan excel.
dengan spreadsheet ini, kita sudah mengelimiasi kekurangan variabel di fonnte, dan dapat didefinisikan sendiri. tidak perlu menggunakan nama variabel dari fonnte seperti name, var1, var2 dll.
kamu bisa menggunakan nama variabel sendiri.
contohnya diatas ada {name} dan {address}
meskipun demikian, kamu tetap memerlukan 1 variabel yaitu "whatsapp" sebagai target.
untuk nama variabel lain, bebas.
Server kami juga lebih teroptimasi untuk menghandle request yang lebih banyak dan lebih stabil
Anda bisa mendapatkan data pengiriman menggunakan webhook dengan javascript.
const express = require("express");
const app = express();
app.use(express.json());
async function sendFonnte(data) {
const url = "https://api.fonnte.com/send";
const customHeaders = {
"Content-Type": "application/json",
Authorization: TOKEN ,
};
const response = await fetch(url, {
method: "POST",
headers: customHeaders,
body: JSON.stringify(data),
});
console.log(await response.json());
}
app.post("/submission", function (req, res) {
console.log(req.body);
const data = {
target: "082227097005",
message: "webhook submission working great!",
sendFonnte(data);
}
res.end();
});
app.listen(3000, function (err) {
if (err) console.log(err);
console.log("Server listening on PORT", 3000);
});
Available parameter
Anda dapat mengunduh lampiran yang dikirimkan ke perangkat anda menggunakan webhook.
Fungsi ini hanya akan berfungsi pada perangkat dengan semua paket fitur.
Catatan khusus : fitur balasan otomatis apa pun tidak akan berfungsi jika anda menggunakan webhook.
const fs = require("fs");
const express = require("express");
const app = express();
app.use(express.json());
app.use(express.static("public"));
app.post("/webhook", async function (req, res) {
console.log(req.body);
const response = await fetch(req.body.url);
const result = await response.arrayBuffer();
fs.writeFile(`./public/file.${req.body.extension}`, Buffer.from(result), (err) => {
if (err) console.log(err);
});
res.end();
});
app.listen(3000, function (err) {
if (err) console.log(err);
console.log("Server listening on PORT", 3000);
});
Jika lampiran anda berisi pesan, anda dapat menemukannya di req.body.url.
Lampiran akan diunduh dan disimpan di folder publik.
Untuk menyimpan di tempat lain, tentukan jalur di mana lampiran harus disimpan.
Note: The attachment will follow file limitation rules. if you are receiving an attachment outside file limitation rules, you will not receive it on your webhook.
Catatan: Lampiran akan mengikuti aturan file limitation. jika anda menerima lampiran di luar aturan batasan file, anda tidak akan menerimanya di webhook anda.
Menggunakan webhook akan memungkinkan perangkat anda merespons pesan masuk dengan respons dinamis.
Kami akan menggunakan ekspres untuk penggunaan yang lebih mudah.
Catatan khusus : fitur balasan otomatis apa pun tidak akan berfungsi jika anda menggunakan webhook.
const express = require("express");
const app = express();
app.use(express.json());
async function sendFonnte(data) {
const url = "https://api.fonnte.com/send";
const customHeaders = {
"Content-Type": "application/json",
Authorization: TOKEN ,
};
const response = await fetch(url, {
method: "POST",
headers: customHeaders,
body: JSON.stringify(data),
});
console.log(await response.json());
}
app.post("/webhook", function (req, res) {
console.log(req.body);
if (req.body.message == "test") {
const data = {
target: req.body.sender,
message: "working great!",
};
sendFonnte(data);
} else {
const data = {
target: req.body.sender,
message: "this is default reply from fonnte",
};
sendFonnte(data);
}
res.end();
});
app.listen(3000, function (err) {
if (err) console.log(err);
console.log("Server listening on PORT", 3000);
});
Available parameter
Membalas menggunakan lampiran hanya tersedia pada perangkat dengan paket super, advanced, atau ultra.
Anda dapat mengunduh lampiran yang dikirimkan ke perangkat anda menggunakan webhook.
Fungsi ini hanya akan berfungsi pada perangkat dengan semua paket fitur.
Catatan khusus : fitur balasan otomatis apa pun tidak akan berfungsi jika anda menggunakan webhook.
<?php
header('Content-Type: application/json; charset=utf-8');
$json = file_get_contents('php://input');
$data = json_decode($json, true);
$device = $data['device'];
$sender = $data['sender'];
$message = $data['message'];
$text= $data['text']; //button text
$member= $data['member']; //group member who send the message
$name = $data['name'];
$location = $data['location'];
//data below will only received by device with all feature package
//start
$url = $data['url'];
$filename = $data['filename'];
$extension= $data['extension'];
//save the file
if($url){
file_put_contents("fonnte-file.$extension", file_get_contents($url));
}
//end
function sendFonnte($target, $data) {
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => "https://api.fonnte.com/send",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => array(
'target' => $target,
'message' => $data['message'],
'url' => $data['url'],
'filename' => $data['filename'],
),
CURLOPT_HTTPHEADER => array(
"Authorization: TOKEN"
),
));
$response = curl_exec($curl);
curl_close($curl);
return $response;
}
if ( $message == "test" ) {
$reply = [
"message" => "working great!",
];
} elseif ( $message == "image" ) {
$reply = [
"message" => "image message",
"url" => "https://filesamples.com/samples/image/jpg/sample_640%C3%97426.jpg",
];
} elseif ( $message == "audio" ) {
$reply = [
"message" => "audio message",
"url" => "https://filesamples.com/samples/audio/mp3/sample3.mp3",
"filename" => "music",
];
} elseif ( $message == "video" ) {
$reply = [
"message" => "video message",
"url" => "https://filesamples.com/samples/video/mp4/sample_640x360.mp4",
];
} elseif ( $message == "file" ) {
$reply = [
"message" => "file message",
"url" => "https://filesamples.com/samples/document/docx/sample3.docx",
"filename" => "document",
];
} else {
$reply = [
"message" => "Sorry, i don't understand. Please use one of the following keyword :
Hello
Audio
Video
Image
File",
];
}
sendFonnte($sender, $reply);
Jika lampiran anda berisi pesan, anda dapat menemukannya di $message.
Lampiran akan diunduh dan disimpan di jalur yang sama dengan url webhook anda.
Untuk menyimpan di tempat lain, tentukan jalur di mana lampiran harus disimpan.
Catatan: Lampiran akan mengikuti aturan file limitation. jika anda menerima lampiran di luar aturan batasan file, anda tidak akan menerimanya di webhook anda.
Webhook memungkinkan respons pesan masuk menggunakan data khusus.
Catatan khusus : fitur balasan otomatis apa pun tidak akan berfungsi jika Anda menggunakan webhook.
<?php
header('Content-Type: application/json; charset=utf-8');
$json = file_get_contents('php://input');
$data = json_decode($json, true);
$device = $data['device'];
$sender = $data['sender'];
$message = $data['message'];
$text= $data['text']; //button text
$member= $data['member']; //group member who send the message
$name = $data['name'];
$location = $data['location'];
$pollname= $data['pollname'];
$choices= $data['choices'];
//data below will only received by device with all feature package
//start
$url = $data['url'];
$filename = $data['filename'];
$extension= $data['extension'];
//end
function sendFonnte($target, $data) {
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => "https://api.fonnte.com/send",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => array(
'target' => $target,
'message' => $data['message'],
'url' => $data['url'],
'filename' => $data['filename'],
),
CURLOPT_HTTPHEADER => array(
"Authorization: TOKEN"
),
));
$response = curl_exec($curl);
curl_close($curl);
return $response;
}
if ( $message == "test" ) {
$reply = [
"message" => "working great!",
];
} elseif ( $message == "image" ) {
$reply = [
"message" => "image message",
"url" => "https://filesamples.com/samples/image/jpg/sample_640%C3%97426.jpg",
];
} elseif ( $message == "audio" ) {
$reply = [
"message" => "audio message",
"url" => "https://filesamples.com/samples/audio/mp3/sample3.mp3",
"filename" => "music",
];
} elseif ( $message == "video" ) {
$reply = [
"message" => "video message",
"url" => "https://filesamples.com/samples/video/mp4/sample_640x360.mp4",
];
} elseif ( $message == "file" ) {
$reply = [
"message" => "file message",
"url" => "https://filesamples.com/samples/document/docx/sample3.docx",
"filename" => "document",
];
} else {
$reply = [
"message" => "Sorry, i don't understand. Please use one of the following keyword :
Test
Audio
Video
Image
File",
];
}
sendFonnte($sender, $reply);
Available parameter
Membalas menggunakan lampiran hanya tersedia pada perangkat dengan paket super, advanced or ultra.
Anda dapat meletakkan URL webhook anda di perangkat anda->edit.
Anda harus menyetel baca otomatis ke Aktif.
jika anda membiarkannya, webhook anda tidak akan berfungsi!
Saat klien mengirimkan kirimannya, anda bisa mendapatkan datanya dan menyimpannya ke sistem anda sendiri atau melakukan apa pun dengannya.
Salin dan gunakan sesuka anda di sistem anda.
<?php
header('Content-Type: application/json; charset=utf-8');
$json = file_get_contents('php://input');
$data = json_decode($json, true);
$sender = $data["sender"];
$submission = $data["submission"];
$name = $data["name"];
$list = $data["data"];
function sendFonnte($target, $data)
{
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => "https://api.fonnte.com/send",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => array(
'target' => $target,
'message' => $data["message"],
),
CURLOPT_HTTPHEADER => array(
"Authorization: TOKEN"
),
));
$response = curl_exec($curl);
curl_close($curl);
return $response;
}
$reply = [
"message" => $json
];
sendFonnte("082227097005", $reply); //change number to your own number
Available parameter
Status pesan pembaruan webhook akan menjadi pengganti API message status untuk menjadikan status pembaruan secara real-time dan tidak memerlukan API hit untuk memperbaruinya.
Status pesan akan memiliki id dan stateid untuk memperbarui status pesan dan status pesan.
Contoh di bawah ini menunjukkan cara menyimpan status pesan ke mysql, anda dapat memodifikasi sesuai kebutuhan.
Anda perlu mengirim dari API untuk dapat menyimpannya. ini adalah contoh pengiriman API dengan menyimpan laporan ke mysql.
Anda dapat mendownload contoh tabel database disini.
API mengirim dan menyimpan laporan:
<?php
$conn = mysqli_connect("localhost","root","","db");
if (mysqli_connect_errno()) {
echo "Failed to connect to MySQL: " . mysqli_connect_error();
exit();
}
$message = "test ya";
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => 'https://api.fonnte.com/send',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS => array('target' => '083120942579','message' => $message),
CURLOPT_HTTPHEADER => array(
'Authorization: TOKEN'
),
));
$response = curl_exec($curl);
curl_close($curl);
$res = json_decode($response,true);
var_dump($res);
foreach($res["id"] as $k=>$v){
$target = $res["target"][$k];
$status = $res["process"];
mysqli_query($conn,"INSERT INTO report (id,target,message,status) VALUES ('$v','$target','$message','$status')");
}
Kemudian gunakan contoh kode di bawah ini untuk memperbarui status dan status pesan ke mysql.
Webhook script :
<?php
header('Content-Type: application/json; charset=utf-8');
$conn = mysqli_connect("localhost","root","","db");
if (mysqli_connect_errno()) {
echo "Failed to connect to MySQL: " . mysqli_connect_error();
exit();
}
$json = file_get_contents('php://input');
$data = json_decode($json, true);
$device = $data['device'];
$id = $data['id'];
$stateid = $data['stateid'];
$status= $data['status'];
$state = $data['state'];
//update status and state
if(isset($id) && isset($stateid)){
mysqli_query($conn,"UPDATE report SET status = '$status',state = '$state',stateid = '$stateid' WHERE id = '$id'");
}else if(isset($id) && !isset($stateid)){
mysqli_query($conn,"UPDATE report SET status = '$status' WHERE id = '$id'");
}else{
mysqli_query($conn,"UPDATE report SET state = '$state' WHERE stateid = '$stateid'");
}
Available parameter