Kami menambahkan fitur lagi di awal februari 2025.

fokus pada update ini terkait penambahan fitur dan optimasi.

TL;DR

Tambahan fitur dan optimasi :

  1. secret key webhook : menambahkan secret key di webhook data
  2. search message history by id : menambahkan filter cari berdasarkan id di message history
  3. Delete processing message : hapus history juga hapus pesan yang diproses
  4. Additional response API send : tambahan requestid di response
  5. inbox : fitur inbox jika diminta
  6. quote message on webhook : membalas dengan webhook bisa dengan quote
  7. Optimize incoming message : menonaktifkan pesan masuk tertentu
  8. Deposit : menambah sistem deposit
  9. Autoconfirm : order dengan deposit autoconfirm
  10. API order : melakukan order dengan API
  11. Fix : file corrupt saat download

Secret key webhook

Webhook sekarang dapat menggunakan tambahan secret key sebagai tambahan data untuk memverifikasi webhook ini berasal dari fonnte.

Screenshot 573

search by id message history

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.

Screenshot 574

Delete processing history

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.

requestid on response

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.

Optimize Incoming

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.

Inbox

fonnte akan menyimpan pesan masuk jika diminta.

kamu bisa mengaktifkannya dengan mengaktifkan autoread ke on dan inbox ke on di menu device->edit.

Screenshot 575

Webhook quote

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.

Deposit system

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

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

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.

Fix download attachment

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

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.

Flow

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

AI setting

Jika kamu menggunakan AI, kamu bisa mensetting AI sesuai kebutuhan.

AI data

Fonnte menyediakan fitur untuk membuat AI membalas dengan data sendiri. dengan menggunakan data sendiri, AI akan bertindak seperti pesonal assistant untuk knowledgebase sendiri.

Response Source

Screenshot 538

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.

Order

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.

Spreadsheet

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.

Screenshot 539

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 optimization

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.

Image

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

Made with in Indonesia