A device is an Android phone running the app and paired with your gateway. It is the phone, not the gateway, that sends and receives the SMS, with its own SIM cards and its own carrier plan. You can pair as many phones as you like: the gateway spreads the traffic between them and takes over when one drops out.
Everything on this page happens in the Devices screen of the dashboard.
What you need
- An Android phone (a modest, dedicated phone is fine) with one or two SIM cards that have an SMS plan or credit.
- A charger that stays plugged in. See Keep the phone running.
- A network connection between the phone and the gateway: Wi-Fi or mobile data. The phone must be able to reach the address of your gateway.
- A Superadmin account: pairing, unpairing and editing quotas are reserved to that role.
Install the app
The app is distributed outside the Play Store. In Devices, the Android app panel shows a QR code: scan it with the phone's camera to download the app, or use Download the APK. Android asks you to allow installs from the browser: this is expected for an app that does not come from the Play Store.
If the panel says no app is stored on the gateway, the APK file has not been placed on your installation. See the installation guide.
If Android refuses to install it
Google Play Protect scans every app that does not come from the Play Store, and can refuse it with "Unsafe app blocked" or "App scanning". The app is not dangerous: it is simply unknown to Google, because it is yours and it is served by your own gateway.
| What the phone says | What to do |
|---|---|
| "Unsafe app blocked" | Tap More details, then Install anyway |
| "For your security, your phone is not allowed to install unknown apps from this source" | Allow your browser to install apps, then start the download again |
| The install is refused again and again | Play Store, Settings, Play Protect, turn off Improve harmful app detection for the time of the installation, then turn it back on |
The download panel shows the SHA-256 of the file: that is what proves the APK is the one your gateway holds. The dashboard also carries this guide, under the QR code of Pair a device.
On first launch, the app asks for a few permissions:
| Permission | Why |
|---|---|
| SMS | Sending and receiving SMS is the whole job of the app |
| Phone state | To list the SIM cards and pick the one that sends. No hardware identifier is transmitted |
| Phone number | To read the number written on a SIM card, when the carrier wrote one, so each card is named by its own number and a swapped card is noticed. Most cards carry no number, and the app works the same without it. It belongs to the same group as phone state, so it is granted with it |
| Camera | Only to read the pairing QR code. No image is kept |
| Notifications | Android requires a permanent notification for an app that runs continuously |
What the app shows on the phone
The app's home screen is a status page, not a control panel: the connection state, the SIM cards it found, how many SMS left today, how many were sent and received in the last 24 hours, and a 24-hour connection strip, one bar per hour, oldest on the left. A short bar is an hour the phone spent away from the gateway, for whatever reason. That history is the phone's own: it is kept even when the gateway is unreachable, which is exactly when you want to read it.
The permanent notification Android requires carries the same summary: connected or reconnecting, SMS sent and received in 24 hours, and how many are waiting. Leaving it alone is what lets Android keep the app running (see Keep the phone running).
Pair a phone
- In Devices, click Pair a device. A QR code appears, valid for five minutes.
- In the app, choose Pair and scan the code.
- The phone appears in the list, Online, with its SIM cards.
No usable camera? Under the QR code, the dialog shows a Fallback code, no camera needed of eight characters. In the app, tap Type the code instead, enter the server address and that code.
Each code works once and expires after five minutes. If it has expired, click Generate a new code. The QR code is signed by your gateway: a phone cannot be tricked into pairing with another server by an edited code.
Encrypted or unencrypted connection
The phone connects to the address encoded in the QR code, which is the public address of your
gateway (GATEWAY_PUBLIC_URL):
| Gateway address | What the dashboard shows | What the app does |
|---|---|---|
https:// (installer domain mode) |
Nothing special | Pairs directly. Home screen: Encrypted connection (https) |
http:// on your local network (.local name, private address such as 192.168.x.x) |
Nothing special | Pairs directly. Home screen: Unencrypted connection, local network only |
http:// on the internet (public address or domain) |
A warning in Pair a device: phones will connect without encryption | Shows Unencrypted connection before sending anything, with Connect anyway and Cancel. Home screen: Connection not encrypted |
With plain http:// on the internet, messages, phone numbers and the pairing secret travel in clear
text: anyone on the network path can read them. The app asks once per gateway address: reconnections
and new QR codes of the same gateway do not ask again, a different address does, and so does a new
pairing after Unpair. If you tap Cancel, nothing is sent; tap Scan again to review the
warning. HTTPS remains the recommended choice, see
Security.
Follow your phones
The Devices table shows, for each phone:
| Column | What it tells you |
|---|---|
| Device | Its name and model. A warning Battery optimisation still active appears when Android may put the app to sleep |
| SIM | The SIM cards detected, with carrier and masked number. A SIM set out of service is marked out of service |
| Status | Online when the phone is connected, Offline when the gateway has not heard from it for five minutes (longer with a long sync interval, see below) |
| Battery, Signal | The last values the phone reported |
| Today's quota | For each SIM, how many SMS it sent today against its daily quota |
| Time zone | The time zone the phone is set to |
| Uptime (24 h) | The share of the last 24 hours the phone stayed connected to the gateway. See Uptime history |
| Last seen | When the phone last gave news |
A connected phone gives news every thirty seconds, or at the Sync interval set in Settings > General, devices. After five minutes without news, or three of its intervals when that is longer (thirty minutes for a ten-minute interval), the gateway marks it Offline. The messages that phone was holding go back to the queue and leave from another phone, without counting as a failed attempt: the message did nothing wrong, the phone disappeared.
The gateway also publishes an event when a phone connects (device.online), drops out
(device.offline) or when its battery falls below 15 % (device.low_battery, sent once when the
threshold is crossed, not on every reading below it). Subscribe a webhook to these events to be
warned in your own tools: see Webhooks.
Actions on a phone
From the Actions column (Superadmin):
| Action | Effect |
|---|---|
| Rename the device | Gives it a name you recognise, for example "Front desk" or "Warehouse" |
| Take out of the pool / Put back in the pool | Out of the pool, the phone stays paired but the gateway no longer gives it anything to send. Useful for maintenance, or to keep a phone for reception only |
| Delete this device | Unpairs the phone. Its message history is kept. To use it again, pair it again |
Removing a phone your routing rules use
A phone named by routing rules is not removed silently. The removal stops and lists the rules that send through it, by name, and asks what becomes of each one: hand it to another SIM, or delete the rule. Nothing you configured disappears without you knowing, and the rerouting and the removal happen together.
One thing is not in that list, on purpose: the phone a conversation prefers to answer from. That is a preference the gateway rebuilds by itself the next time the correspondent replies, so it is simply forgotten.
The phone's own log
The gateway only ever sees what a phone had time to tell it. When Android kills the app, when the network drops, when a send is refused before it reaches the radio, the reason never leaves the handset. So the app keeps its own log, on the phone, for seven days.
To open it: tap three times, quickly, in the bottom-left corner of the app screen. There is no button there on purpose: this is a diagnostic tool, read once a year, and it would otherwise sit on the main screen forever. It works on the pairing screen too, which is exactly where you need it when a phone will not pair.
To send it here: open that log on the phone, pick the day, and press Send to the gateway. Then read it in Devices, in the menu of that phone, under Internal log. Nothing is uploaded on its own: a phone that shipped its logs by itself would spend your data without being asked.
What it never contains: no message content and no full phone number. Both are stripped on the phone, as the line is written, not when it is displayed. Short codes stay readable, because they name a service and not a subscriber.
Naming your phones and their SIM cards
Routing rules, the journal and the send screens all name SIM cards. A fleet you cannot read is a fleet you cannot steer, so the dashboard asks you to name what it does not know yet: each phone, and each SIM inside it. Give them names you would recognise in six months, such as "Front desk" and "Customer line".
Naming is reserved for a superadmin. Everyone else sees a note saying who to ask.
When a SIM card seems to have been swapped
If the card in a slot stops matching the one you confirmed, the dashboard tells you and asks you to confirm what is in there now. Nothing is renamed and nothing is rerouted on its own: the name you gave stays, and messages keep leaving from that slot.
It says seems on purpose. Android reserves the serial number of a SIM card to privileged applications, so no ordinary app can identify a card with certainty. The gateway compares what the phone does expose: the carrier, the number when the carrier publishes it, and the subscription identifier Android gives the card. Two consequences worth knowing:
- A card swapped for another from the same carrier may go unnoticed on a phone running an app older than 1.1.2, because most carriers do not publish the number.
- A factory reset can make a card look new even though nothing changed. Confirm the slot and the question goes away.
Naming a slot also confirms it: the card sitting there becomes the reference, and the warning clears. If you simply put the original card back, the warning clears on its own.
Uptime history
The gateway keeps the connection history of every phone, so you can tell a reliable phone from one that keeps dropping out. You see it in two places:
- the Device uptime card of the Dashboard, under the activity chart (the first eight phones, with a link to the others);
- the same card under the table of the Devices screen, for the whole fleet, and the Uptime (24 h) column of the table.
Choose the period with the 24 h, 7 d, 30 d and 90 d buttons. Each phone gets one row: its name, its current status, its uptime percentage over the period, and one bar per time slot (one per hour over 24 hours, per six hours over 7 days, per day over 30 and 90 days). Time slots follow the platform time zone (Settings > Sending), daylight saving included, so the day of a clock change lasts 23 or 25 hours. Hover or tap a bar for the exact times of the slot and how long the phone was in each state. At the top of the card, Fleet uptime gives one figure for all your phones together.
Each bar splits the time into three states, told apart by their position, a word and an icon in the legend and the tooltip, never by color alone:
| State | Shown as | What it means |
|---|---|---|
| Online | Green, at the bottom | The phone held its connection to the gateway |
| Offline | Red, above | The gateway was running and the phone was not connected |
| Gateway stopped (unknown) | Hatched gray, at the top | The gateway itself was stopped (update, restart, machine off): nobody could tell whether the phone was reachable |
A slot before the phone was paired stays an empty track: a phone paired this morning is not counted as offline for the night before.
Why a phone was away
The card has a Why? link, which opens the list of every absence of the period: which phone, from when, for how long, and what caused it. When there is enough to compare (at least two causes and three absences), a small chart ranks the main causes above the list.
| Cause | What it means |
|---|---|
| Phone restarted | The phone rebooted. Normal after an update of Android, a problem if it repeats |
| App closed or killed | The app was swiped away, force-stopped, or removed by a battery cleaner |
| App updated | A new version of the app replaced the running one |
| No network | The phone had no usable network at all |
| Airplane mode | Airplane mode was on |
| Phone switched off | The phone was turned off |
| Battery empty | The phone ran out of battery |
| Phone stopped answering | The phone stopped sending its heartbeat without saying why: this is what an Android that suspends the app looks like. See Keep the phone running |
| Connection dropped | The connection fell and the phone could not say why |
| Gateway stopped | The gateway itself was stopped. It says nothing about the phone, and never counts against it |
| Unknown | The absence predates this feature, or the phone has not come back yet |
The first two thirds of that table can only be known by the phone, and it can only tell the gateway when it comes back: an absence in progress shows what the gateway observed, and gains its real cause at the next connection.
How the percentage is computed. Uptime is the online time divided by the online plus offline time. Time the gateway was stopped is not counted as offline: an update of the gateway at night does not lower the uptime of your phones. When nothing was observed over the period (the gateway was stopped the whole time), the card shows No data instead of 0 %.
How long it is kept. The history is kept 90 days by default, the longest period of the
chart. Set GATEWAY_UPTIME_RETENTION_DAYS (from 90 to 3650) to keep it longer, see the
installation guide. The history starts when you install a
version of the gateway that records it: earlier time reads as unknown. Unpairing a phone deletes its
history.
Through the API. GET /devices/uptime?period=24h (or 7d, 30d, 90d) returns the same
report: for each phone and each slot, the seconds online, offline, unknown and before pairing, plus
uptimePercent (null when nothing was observed). Any key with the read scope and every
dashboard role can read it.
Daily SIM quota
Each SIM has a daily allowance of SMS, 200 by default.
Why it matters. Carriers watch consumer SIM cards. A SIM that suddenly sends thousands of SMS a day looks like spam and can be suspended, sometimes for good. The quota keeps each SIM under a volume you choose. When one SIM is spent, the gateway uses another; when every SIM is spent, the messages wait.
How it counts.
- A long message counts for as many SMS as it takes (a message of 200 plain characters is two SMS).
- The count restarts every day at midnight UTC, whatever the time zone of your platform. This is deliberate: carriers count in absolute time, and changing your time zone must never grant a second allowance for the same day.
Where you see it. In the Today's quota column: "12 of 200 today", or just "No cap" for a SIM without a cap, with a bar that turns amber from 80 % and red when the quota is reached, and a Quota reached marker. The Dashboard also shows an alert for each SIM close to or at its quota.
Change it (Superadmin). Click the pencil next to the SIM. The Quota and cadence of the SIM dialog offers:
| Field | Effect |
|---|---|
| Messages per day | The new allowance, a whole number up to 1,000,000 |
| No daily cap | Removes the limit. Do it knowingly: that is exactly what can get a consumer SIM suspended |
| SIM in service | Off, the SIM sends nothing, whatever its quota. Useful when a SIM has no credit left or is being replaced |
| Own interval for this SIM | Off (default), the SIM follows the minimum interval between two SMS of Settings > Sending, recalled under the switch. On, Seconds between two SMS on this SIM (0 to 3600) replaces it for this SIM only: a longer wait for a new SIM the carrier watches, 0 for a SIM that needs none. See SIM cadence |
What happens when you save:
- Today's count is kept. Raising from 200 to 500 at noon after 200 sends leaves 300 for the rest of the day. Lowering below what was already sent stops the SIM until midnight UTC.
- Held messages leave at once. If messages were waiting because every quota was reached, raising a quota, removing the cap or putting a SIM back in service sends them right away instead of at midnight. The Queue screen shows a banner counting those messages, with an Edit quotas link to this screen.
A SIM with its own interval shows "Own cadence: 1 SMS every 30 s" under its quota.
Through the API, the same setting is PATCH /devices/{deviceId}/sims/{slot} with dailyQuota
(0 means no cap), enabled and minIntervalSeconds (null to follow the setting again, 0 for
no wait). GET /devices returns minIntervalSeconds for each SIM, null when it follows the
setting.
The local time of each phone
Your phones do not have to be in the same country as your platform. The header of the dashboard shows, next to the live indicator, the local time of your phones: with one phone, its time directly; with several, their number, and the detail when you click it. Each phone shows its time zone and a Not on platform time marker when its clock differs from the time zone of the platform.
Why it matters. The night and Sunday pauses of campaigns and the time of scheduled sends follow the platform time zone (set in Settings > Sending), not the time of each phone. The marker tells you when a phone lives at another hour than the one your schedules use.
A phone marked Time zone unknown runs an older version of the app: update the app on that phone to see its time zone.
Keep the phone running
An SMS gateway is only as reliable as its phones. Android is designed to save battery by putting apps to sleep, which is exactly what a gateway must avoid. The app keeps a permanent connection to your gateway so that messages leave within seconds; for that, the phone has to stay awake.
Do this once for every phone:
- Keep it plugged in. A phone on its charger is not put into deep sleep by Android. This is the single most effective measure. If your phone offers a battery protection option (charge limited to 80 % or similar), turn it on: it spares the battery that stays on the charger for months.
- Turn off battery optimisation for the app. In the app, tap Fix battery settings. As long as the dashboard shows Battery optimisation still active, Android can suspend the app and the SMS stop leaving.
- Allow automatic start. Some manufacturers (Xiaomi, Huawei, Oppo, Samsung and others) block apps from restarting on their own. The app shows an Automatic start card with Open the setting. If the setting cannot be found, look for "Autostart" or "Auto-launch" in the battery settings. The Battery assistant link under the Devices table opens a site that describes the settings of each manufacturer.
- Leave the permanent notification alone. It is what lets Android keep the app running. Do not swipe the app away from the recent apps, and do not force it to stop.
- Give it a stable connection. Prefer a Wi-Fi network that does not switch off at night, or mobile data that stays on.
A paired phone restarts the app by itself when it reboots, as long as the manufacturer allows automatic start (point 3) and Start automatically is on in Settings > General, devices. With that setting off, open the app once after each restart of the phone. On a phone whose manufacturer suspends apps as soon as the screen is off despite the points above, Keep the screen on in the same tab keeps the screen lit, dimmed, while the app runs; it drains the battery, so only use it on a phone that stays plugged in.
Recovering SMS received while the app was stopped
Points 1 to 5 are what keeps the app running. This one is the net for the times they were not enough: a manufacturer overlay that forces the app to stop, or the minutes a phone takes to restart. During that time the SMS your phone receives never reach the gateway, and nothing replays them afterwards.
Recover missed SMS, on the app's home screen, closes that gap. Switched on, the app reads the phone's own message store when it reconnects, and hands the gateway what it missed. They appear in Conversations like any other received SMS, in the order they arrived, never twice.
It is off by default, on purpose: switching it on lets the app read the phone's message store, which it never does otherwise. Android asks for that permission the moment you turn the switch on, and the switch stays off if you refuse.
Two things are worth knowing before you rely on it:
- It starts counting when you switch it on. Messages your phone received before that moment are never imported, so turning it on does not pour the phone's history into your conversations.
- It repairs, it does not prevent. The app has to come back for the recovery to run: by restarting on its own, or by someone opening it. Points 1 to 5 above are still what keeps the gap short.
A phone that was switched off rarely needs this: your operator's network holds an undelivered SMS for hours, often days, and delivers it once the phone is back. The gap this setting really covers is a phone that stayed on while the app was stopped.
Options
Every setting of a phone and of its SIM cards, where to change it, and what it does to the rest of the product. All of them are reserved to a Superadmin.
| Option | Where | Default | Allowed values | Effect |
|---|---|---|---|---|
| Device name | Actions > Rename the device; API PUT /devices/{deviceId}, field name |
Set at pairing | 1 to 80 characters | Display only: the name shown in the dashboard, in the routing rules and in the queue |
| Routing pool | Actions > Take out of the pool / Put back in the pool; API PUT /devices/{deviceId}, field inRoutingPool |
In the pool | In or out | Out of the pool, the phone sends nothing at all: automatic routing skips it, a routing rule skips its SIMs, and a send that names this phone is retried, then fails with No device available to send if the phone is still out when its attempts run out. It keeps receiving SMS |
| Messages per day | Pencil in Today's quota; API PATCH /devices/{deviceId}/sims/{slot}, field dailyQuota |
200 | 0 to 1,000,000 (through the API, 0 means no cap) |
Once reached, the SIM is skipped until midnight UTC. When every usable SIM is spent, messages wait with the status Quota reached. Raising it releases those messages at once |
| No daily cap | Same dialog | Off | On or off | Same as a quota of 0: the SIM is never stopped by its quota. In the "quota" automatic routing mode, a SIM without a cap always ranks first. Releases held messages at once |
| Own interval for this SIM | Same dialog; API field minIntervalSeconds |
Off (null: follows Settings > Sending) |
0 to 3600 seconds | Least time between two SMS on this SIM, instead of the sending setting. 0: no wait on this SIM. Messages wait in the queue and leave on their own; the other SIMs keep sending |
| SIM in service | Same dialog; API field enabled |
On | On or off | Off, the SIM sends nothing whatever its quota: every routing mode and every routing rule skips it (a strict rule whose SIMs are all out of service makes its messages wait). The SIM keeps receiving. Putting it back in service releases held messages at once |
| Pairing code | Pair a device; API POST /devices/pairing |
None | Valid five minutes, single use | Generating a new code does not cancel phones already paired |
Changes to a quota or to the in-service switch apply to the very next message: there is nothing to restart, on the gateway or on the phone. The per-minute limit of each SIM, the retries and the time zone are sending settings, described in Sending messages.
The Settings > General, devices tab holds the phone settings: Sync interval, in seconds (how often the phone gives news, and so how long before a silent phone goes offline), Strip diacritics, Trim extra whitespace, Uppercase everything (applied to the text when a message leaves for the phone, and shown as such in the history), Start automatically and Keep the screen on. Each phone applies them as soon as they are saved, or when it reconnects. Their details are in Settings.
Troubleshooting
| Symptom | What to check |
|---|---|
| The QR code is refused as expired | It is valid five minutes. Click Generate a new code |
| "Gateway unreachable" in the app while pairing | The phone cannot reach the address of the gateway: check it is on the right network and that the address in the QR code is reachable from the phone |
| "The gateway refused the pairing" | The code was already used. Generate a new one |
"Gateway unreachable" with an http:// address on the internet |
Apps older than version 1.0.2 refuse unencrypted connections to the internet. Install the app offered in Devices again, then pair |
| Connection not encrypted on the phone's home screen | The gateway address is plain http:// on the internet. If that is not your choice, move the gateway to https:// and pair the phone again |
| A phone goes Offline regularly, at night | Battery optimisation or automatic start (see above), or a Wi-Fi that sleeps. Plug the phone in |
| Hatched Gateway stopped slots in the uptime chart | The gateway itself was stopped at that time (update, restart, machine off). It does not lower the uptime of the phones |
| The app says the gateway no longer recognises it | The phone was deleted from Devices, or the gateway was reinstalled with a new master key. Pair it again |
| Messages wait in Quota reached | Every usable SIM spent its daily quota. Raise a quota, or wait for midnight UTC |
| A SIM sends nothing although it is Online | Check that it is in service, that its quota is not reached, and that the phone is in the routing pool |
| Time zone unknown in the header | Update the app on that phone |