Use cases
School fee reminders
Remind parents of balances with an approved template and track delivery.
In a nutshell
Pick the APPROVED fees template, fill its placeholders per student, send each with your own reference from a queue, and update the reminder's status from message.status callbacks.
The flow
- Load the template.
GET /businesses/{school}/whatsapp/templates?status=APPROVED&name=fees_reminder- cache it. - Create your rows first. One reminder row per parent in your database, status
pending. - Send from a queue. For each row,
POST .../messageswithtype: templateandreference: "fee-reminder-{row id}". Storedata.id. - Track.
message.statuscallbacks carry your reference - move the row to sent, delivered, read or failed.
The template
Created by the school in WhatsApp Manager (category UTILITY):
Dear {{1}}, the fees balance for {{2}} is GHS {{3}}. Please pay before {{4}}.
Sending
foreach ($reminders as $reminder) {
SendFeeReminder::dispatch($reminder->id); // queued; see Safe retries
}
// In the job:
Http::withToken(config('services.paalchat.token'))->acceptJson()
->post("https://whatsapp.paaltech.org/api/v1/businesses/{$tenantId}/messages", [
'to' => $reminder->parent_phone,
'type' => 'template',
'reference' => 'fee-reminder-'.$reminder->id,
'template' => [
'name' => 'fees_reminder',
'language' => 'en_US',
'components' => [['type' => 'body', 'parameters' => [
['type' => 'text', 'text' => $reminder->parent_name],
['type' => 'text', 'text' => $reminder->student_name],
['type' => 'text', 'text' => number_format($reminder->balance, 2)],
['type' => 'text', 'text' => $reminder->due_date->format('j F')],
]]],
],
])->throw();
for (const r of reminders) {
await queue.add('fee-reminder', { id: r.id });
}
// worker
await fetch(`${BASE}/businesses/${school}/messages`, { method: 'POST', headers: HEADERS, body: JSON.stringify({
to: r.parentPhone, type: 'template', reference: `fee-reminder-${r.id}`,
template: { name: 'fees_reminder', language: 'en_US', components: [{ type: 'body', parameters: [
{ type: 'text', text: r.parentName }, { type: 'text', text: r.studentName },
{ type: 'text', text: r.balance.toFixed(2) }, { type: 'text', text: r.dueDate }] }] },
}) });
Tracking
"data": {"reference": "fee-reminder-4411", "status": "failed", "error": {"code": "131026", "message": "Recipient is not on WhatsApp"}}
Show failed reminders to the bursar so they can call or SMS those parents instead.
Tip
Send reminders during the day. Messages at night get blocked more often, which lowers the number's quality rating.