G-SMS · Use case
Appointment reminders by SMS in Cameroon
A booked slot that nobody shows up for cannot be recovered: it is simply lost. Here is how to send a reminder the day before from a scheduled job, what it costs per appointment, and the one limitation to know before you write the message.
The problem: the appointment is booked, then forgotten
In a dental practice, a garage or a training centre, appointments are usually made face to face or over the phone, sometimes weeks ahead, and written into a diary that notifies nobody. Between booking and the date itself, nothing reminds the customer that they reserved a slot.
Calling people one by one does not scale: phoning fifty patients the day before takes up half a day at the front desk, and half of those calls reach voicemail.
What a no-show costs
Use your own figures from last month rather than an average found elsewhere: count the booked slots that stayed empty. On 200 monthly appointments, thirty no-shows represent XAF 300,000 of revenue that never arrived, at XAF 10,000 a slot — for a practitioner who was present and paid all the same.
An empty slot costs twice: the revenue lost, and the next customer who could have taken it had they known a place was free.
The solution in three steps
1. Settle on the timing, once
The day before, late afternoon: the customer still has time to cancel, and you still have time to offer the slot to someone else. A second reminder two hours ahead makes sense for long or expensive appointments; past two messages a reminder turns into a nuisance and is ignored.
A reminder is not a verification code: it holds no secret and carries no urgency. What matters is not that it leaves immediately, but that it arrives at the right moment.
2. Send from a scheduled job
import logging
import os
import time
from datetime import date, timedelta
import requests
API = 'https://api.sms.gworldship.com/v1/sms'
KEY = os.environ['GSMS_API_KEY']
CLINIC = 'Akwa Clinic'
FRONT_DESK = '233 42 10 10'
tomorrow = date.today() + timedelta(days=1)
def post(payload):
return requests.post(API, timeout=10, json=payload,
headers={'Authorization': f'Bearer {KEY}'})
for appointment in appointments_on(tomorrow):
text = (f'Reminder: your appointment is tomorrow {tomorrow:%d/%m} '
f'at {appointment.time} at {CLINIC}. To cancel, call {FRONT_DESK}.')
response = post({
'to': appointment.phone, # +237690000000
'text': text,
# One reminder per appointment per date: if the job runs twice, the API
# answers 409 with the message already sent, no second send or charge.
'clientReference': f'reminder-{appointment.id}-{tomorrow:%Y%m%d}',
})
if response.status_code in (202, 409):
appointment.save_reminder(response.json()['messageId'])
else:
logging.warning('G-SMS %s %s', response.status_code,
response.json().get('code'))
time.sleep(0.2) # 10 requests per second per key: stay under the limitThe example message is 99 characters in the standard alphabet: a single segment, with 61 characters to spare. The client reference includes the date, which makes the job replayable — run twice on the same day, it does not send two reminders. How idempotency works →
3. Handle by hand what did not get through
# On the morning itself: who did not get their reminder?
failed = requests.get(
API,
timeout=10,
headers={'Authorization': f'Bearer {KEY}'},
params={'status': 'FAILED', 'from': f'{tomorrow:%Y-%m-%d}T00:00:00Z', 'size': 100},
).json()
for message in failed['content']:
# The credit is already refunded: what is left to do is human.
call_list.add(message['clientReference'], message['to'])An unreachable number stays an unreachable number: the failed SMS is credited back automatically, but it is the front desk that will call. The list is short, and that is precisely the point: manual work now only covers the cases that deserve it.
The real cost, in CFA francs
Assumption: 200 appointments a month. Weighted average price of XAF 5.30, from 85% of sends to Orange and MTN at XAF 5 and 15% to Camtel and Nexttel at XAF 7.
| Reminder | Monthly volume | Monthly cost |
|---|---|---|
| Reminder the day before, at 5 pm | 200 | XAF 1,060 |
| Second reminder, two hours ahead (optional) | 200 | XAF 1,060 |
| Both reminders | 400 SMS | XAF 2,120 |
That is XAF 5.30 per appointment reminded once. A single XAF 10,000 slot saved by the reminder pays for more than nine months of sending.
Good practice
- Between 8 am and 7 pm, never outside. A reminder arriving at 10 pm irritates, and is no longer on screen the next morning.
- Two reminders at most, and one in most cases. The third message turns a service into harassment.
- Everything in one sentence: date, time, place and how to cancel. The customer will not read the message twice.
- Name the practice. The sender shown is a number, not a name: without it the recipient has no idea who is writing.
- Give a number that is answered. The reminder exists to collect cancellations: if nobody picks up, the slot stays lost.
- Use a client reference containing the appointment date, not just its identifier: a rescheduled appointment must be allowed a new reminder.
- Only send for appointments still active. Read the diary at send time, not from an extract frozen the evening before.
- Stay under 10 requests per second per key. A short pause between sends is enough; beyond that the API answers 429 with a
Retry-Afterheader.
What G-SMS does not do
- No inbound SMS, so no confirmation by reply. The “reply YES to confirm” pattern is impossible: no incoming message is ever read. This is a settled design decision, not a pending feature. Give a phone number or a link, and design the reminder as a statement rather than a question.
- No custom sender name. The recipient sees the number of the sending SIM. Hence the previous rule: your name has to be in the text.
- No scheduling on the G-SMS side. There is no “send at this time” field: your scheduled job decides the moment. The API sends when it is called.
- No diary management. G-SMS knows neither your slots nor your patients: it takes a number and a text, and returns a delivery status.
Frequently asked questions
How much does an appointment reminder SMS cost in Cameroon?
XAF 5 per segment to Orange and MTN, XAF 7 to Camtel and Nexttel. A reminder of about a hundred characters fits in a single segment, so budget 5 to 7 francs per appointment reminded.
When should the reminder go out?
Late afternoon the day before, while the patient can still free up or move the slot. A reminder sent on the morning itself leaves no time to reorganise the day.
Can the patient confirm by replying to the SMS?
No: G-SMS does not receive messages, by design. Put a phone number or a link in the text instead — and make sure that number is actually answered.
Ready to send your first SMS?
Create an account, get 100 FCFA of credit and an API key straight away.