SMS and one-time codes
Texts go out from a real SIM, so they reach any number the SIM can text, with no sender registration.
- Choose the SIM on a dual-SIM phone
- Long messages are split automatically
- Sent one by one, paced to keep the phone healthy
Send one-time codes, customer updates and WhatsApp messages, and run USSD requests, from your own software. UGO | Gateway turns an Android phone and its SIM into your sender: you call an API, the phone does the sending and reports back.
Early access. We are working with a first group of businesses and are not publishing prices yet. Tell us what you send and we will reply.
No SMS provider contract and no WhatsApp setup on your server. The phone you already own does the sending.
One JSON request says what to send: the channel, the number and the text, or the USSD code and the answers to type.
It is stored safely and can be scheduled for later. If you repeat the same call by accident, you still send once.
The UGO | Gateway app on your Android phone picks the job up and sends it with its own SIM or its linked WhatsApp account.
Sent or failed, with the reason. For USSD you also get the operator's answer. Ask by message id or by your own reference.
Use one, or all three from the same API. Each one runs on the phone itself.
Texts go out from a real SIM, so they reach any number the SIM can text, with no sender registration.
Messages go out from a WhatsApp account linked to the gateway phone, in the places where your customers already read.
Dial a code and read the answer, or walk through a menu: each answer you list is typed into the next prompt.
Plain JSON over HTTPS with one key in a header. You receive your endpoint address and key when your access is approved.
curl -X POST "$GATEWAY_URL?action=enqueue" \
-H "X-API-Key: $GATEWAY_KEY" \
-H "Content-Type: application/json" \
-d '{"channel":"sms","to":"+237600000000",
"body":"Your code is 481 922","idem_key":"otp-1042"}'
# {"status":"ok","id":123,"duplicate":false}
# later: what happened to it?
curl "$GATEWAY_URL?action=message&id=123" \
-H "X-API-Key: $GATEWAY_KEY"
# {"status":"ok","message":{"id":123,"status":"sent", ...}}$ch = curl_init(getenv('GATEWAY_URL') . '?action=enqueue');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'X-API-Key: ' . getenv('GATEWAY_KEY'),
],
CURLOPT_POSTFIELDS => json_encode([
'channel' => 'whatsapp',
'to' => '+237600000000',
'body' => 'Your repair is ready for pickup.',
'ref' => 'repair-42',
'idem_key' => 'repair-42-ready',
]),
]);
$reply = json_decode(curl_exec($ch), true); // ['status' => 'ok', 'id' => 124]const res = await fetch(`${GATEWAY_URL}?action=enqueue`, {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'X-API-Key': GATEWAY_KEY },
body: JSON.stringify({
channel: 'ussd',
body: '*126#',
ussd_steps: ['1', '699999999', '5000'], // typed into the menu, in order
sim: 0,
ref: 'momo-77',
}),
});
const { id } = await res.json();
// poll for the operator's answer
const r = await fetch(`${GATEWAY_URL}?action=message&id=${id}`, { headers: { 'X-API-Key': GATEWAY_KEY } });
const { message } = await r.json(); // message.status, message.result, message.error| Field | What it does |
|---|---|
channel | sms, whatsapp or ussd |
to | The phone number, with country code |
body | The text, or the USSD code to dial |
ussd_steps | Answers to type into a USSD menu, in order (up to 12) |
sim | SIM slot on a dual-SIM phone (0 or 1) |
send_at | Send later, up to 30 days ahead |
device_id | Only this phone may send it |
ref | Your own reference, to look the message up later |
idem_key | Repeat the call safely: you still send once |
A message is pending, processing, sent or failed. A failed one carries the reason.
A phone is not a data centre, so the gateway is designed around the things that go wrong with phones.
Repeat a call with the same idem_key and you get the original message back. The phone also remembers what it already sent.
If WhatsApp is not connected, the message goes back in the queue and is tried again a little later, up to five attempts.
Sent or failed, with the error, and the operator's answer for USSD. Nothing is "probably delivered".
Queue a reminder today for next week. It waits on the server until its time.
Add phones for more volume, pin a message to one of them, or switch a lost phone off from the server.
Phone keys are stored only in scrambled form and USSD answers are wiped when the job ends. The SIM and the number stay yours.
Write to us with the kind of messages you send and roughly how many a day. We reply on WhatsApp or by phone, and if it is a fit we set you up with the app, an API key and an endpoint.
Before you start, read the Gateway terms (draft).
send_at schedules a message up to 30 days ahead, sim picks the SIM slot on a dual-SIM phone, and idem_key makes a call safe to repeat.Something else? Contact us.