SMSTunnel for Magento
Order texts from your own phone and number
Order texts customers can reply to
Magento Open Source, Adobe Commerce and Mage-OS stores text customers about their orders from your own Android phone, from your own number. Your store hands each text to your SMSTunnel account and your phone sends it from its own SIM, so customers see a number they know, and they can simply reply.
What your store sends
Hi Ana, thanks for your order #000000042 at Luma Shop. Total: $30.00. We will text you when it ships.
New order #000000042 at Luma Shop: $30.00 from Ana Pop.
Hi Ana, your order #000000042 at Luma Shop has been invoiced. Total: $30.00.
Good news, Ana: your order #000000042 from Luma Shop is on its way. Tracking number: 1Z999AA10123456784
Luma Shop: your order #000000042 has been canceled.
Luma Shop: your order #000000042 is now On Hold.
Every text has its own on/off switch and its own wording, for each website and store view, in any language.
Built for real stores
- Checkout never waits. Texts go out in the background through Magento's message queue, with a cron job as a safety net. If SMSTunnel can't be reached, checkout carries on and the text is tried again after 1, 5, 15 and 60 minutes.
- Numbers that work. The number comes from the shipping address (or the billing address) and is
completed with the country calling code when the customer left it out:
(415) 555-0123on a US address becomes+14155550123,0722 123 456on a Romanian one+40722123456. Invalid numbers, short codes and premium-rate numbers are skipped, with the reason. - Never twice. Each text is queued once, however many times the order is saved.
- Every text in one list. Sales → SMSTunnel Texts shows what went out, what is waiting and why something was skipped, with Send Again.
- Several stores, several phones. Each website or store view can have its own wording, its own key, even its own phone.
- Nothing else to install. No extra libraries: the module uses Magento's own HTTP client, MySQL queue and cron.
1. Get your key
- 1. Install the SMSTunnel app from Google Play on your Android phone and sign in.
- 2. In your dashboard, open Apps → Add an app, pick Magento, name it (for example "Magento") and click Create the key.
- 3. Copy the key right away: it's shown only once. You can stop or delete the app there anytime, and Magento can't send texts anymore.
Get the steps with your key in them
It opens Add an app with Magento picked. Once the key is made, the dashboard shows every step and command with the key already filled in, ready to copy.
2. Install the module
composer require smstunnel/smstunnel-magento
bin/magento module:enable SmsTunnel_SmsNotifications
bin/magento setup:upgrade
bin/magento cache:flush -
In production mode, also run
bin/magento setup:di:compileandbin/magento setup:static-content:deploybeforecache:flush. - Magento Open Source, Adobe Commerce or Mage-OS 2.4.6, 2.4.7, 2.4.8 or 2.4.9, with PHP 8.1 to 8.5 (what your Magento version supports).
- Magento's cron running (every Magento store needs it). No other packages are needed.
3. Connect Magento
In the Magento admin, open Stores → Configuration → SMSTunnel → Order Texts → Your Phone:
- Send Order Texts
- Yes
- API Key
- Paste the key. Magento stores it encrypted.
- Phone ID
- Optional: to always use one phone, copy its ID from Phones in your dashboard (it has a Copy button). Leave it empty to let SMSTunnel use one of your phones.
- Default Country Code
- Optional, for example +1. It completes numbers written without a country code when the address has no country, and your own numbers. Empty means the store's default country.
Click Save Config.
4. Send a test text
Type your mobile number in Test Number and click Send a Test Text. Your phone sends it within seconds.
5. Pick the texts
Open each group (New-Order Texts to You, Customer Text: Order Placed, …), switch it on or off and change the wording. Use the scope switcher at the top left to give a website or store view its own wording, language or even its own phone. The texts can use:
- Order number
-
{{order_id}}e.g. 000000123 - Customer name
-
{{customer_firstname}} {{customer_lastname}} - Order total
-
{{grand_total}}e.g. $30.00 - Store name
-
{{store_name}}(Stores → Configuration → General → Store Information, else the store's name) - Order status
-
{{status}}as the store view shows it to customers - Tracking
-
{{tracking_number}} {{carrier}}shipment text only: the tracking numbers and carriers
A line holding {{tracking_number}} or {{carrier}} is left out
when the shipment has no tracking number, so the default shipment text works with and without tracking:
Good news, {{customer_firstname}}: your order #{{order_id}} from {{store_name}} is on its way.
Tracking number: {{tracking_number}} A text can be up to 1600 characters (a long text arrives as several joined SMS).
How texts go out
- 1. An order event (placed, invoiced, shipped, canceled, a status
change) writes the text to the
smstunnel_messagetable and publishes its ID to thesmstunnel.message.sendqueue (MySQL queue, so no RabbitMQ is needed). - 2. The
smstunnel.message.sendconsumer hands it to SMSTunnel. Magento's cron starts consumers every minute (consumers_runner); you can also run it yourself:If yourbin/magento queue:consumers:start smstunnel.message.sendapp/etc/env.phplimitscron_consumers_runnerto a list of consumers, addsmstunnel.message.send, or leave it out: thesmstunnel_send_pendingcron job sends whatever is waiting every minute anyway (up to 25 texts per run). - 3. Errors that can pass (no connection, too many requests, a problem on SMSTunnel's side) are retried after 1, 5, 15 and 60 minutes, then the text is marked Failed. A wrong API key or a refused number fails at once.
- 4. If your phone is offline, SMSTunnel keeps the text and your phone sends it as soon as it is back online; the list shows a note.
Errors and retries are also written to var/log/smstunnel.log.
Sent texts
- Sales → SMSTunnel Texts lists every text: when it was queued, what it is for, the order, the number, the text, its status (Waiting, Sent to your phone, Failed, Skipped) and the reason when it failed or was skipped. Select texts and use the Actions menu to Send Again (texts that failed or were sent) or Delete.
- The list keeps texts for 90 days by default (Stores → Configuration → SMSTunnel → Order Texts → Sent Texts); 0 keeps them. They hold customers' phone numbers, so keep them only as long as you need them.
- Admin roles: Sales → Operations → SMSTunnel Texts (view), its child Send Again and Delete, and Stores → Settings → Configuration → SMSTunnel (settings and the test text).
If it doesn't work
- No texts at all. Check that Magento's cron runs (
bin/magento cron:runfrom crontab), that Send Order Texts is Yes for the store view, and the Status and Details columns under Sales → SMSTunnel Texts. - "SMSTunnel answered 401": the API key is wrong or was deleted. Create a new one under Apps → Add an app.
- "Waiting" for a while: SMSTunnel could not be reached or asked to slow down; the text is tried again by itself. The Details column says why.
- A text was "Skipped": the number on the order is not valid for its country, or texts were turned off before it went out.
Uninstall
bin/magento module:uninstall --remove-data SmsTunnel_SmsNotifications
This removes the list of texts, the settings (the API key included) and the queue, then runs
composer remove. To keep the data, use
bin/magento module:disable SmsTunnel_SmsNotifications instead.
Questions
- Do I need a special SIM or number?
- No. Texts leave from the phone and SIM you already have.
- What if my phone is offline?
- SMSTunnel keeps the text and your phone sends it as soon as it is back online.
- Can customers reply?
- Yes: the text comes from your number, so replies reach your phone.
- Does it slow down checkout?
- No. Texts are queued and sent in the background.
- Which Magento versions?
- Magento Open Source, Adobe Commerce and Mage-OS 2.4.6, 2.4.7, 2.4.8 and 2.4.9.
- How do I stop it?
- Set Send Order Texts to No, or delete the store's key in your SMSTunnel dashboard.
Build it with an AI assistant
Copy this prompt into Claude, ChatGPT, Cursor or Copilot and replace the part in [brackets]. Don't paste your API key into the chat: the prompt doesn't need it.
Help me add a text message my Magento 2 store doesn't send yet (such as a back-in-stock alert or an appointment reminder), with SMSTunnel.
About SMSTunnel (https://smstunnel.io): my own apps and tools hand text messages (SMS) to my SMSTunnel account, and my own Android phone sends them from my own number, on my own SIM and plan. The phone runs the SMSTunnel app from Google Play (https://play.google.com/store/apps/details?id=io.smstunnel.app), signed in to my account.
What I want: [describe what should send a text, to whom, and when]
How it works:
- The module SMSTunnel for Magento is installed (composer require smstunnel/smstunnel-magento, bin/magento module:enable SmsTunnel_SmsNotifications, bin/magento setup:upgrade) on Magento Open Source, Adobe Commerce or Mage-OS 2.4.6 to 2.4.9. It already texts customers about their orders and keeps its API key encrypted in Magento's configuration (path smstunnel/general/api_key).
- Write what I want as a small Magento 2 module (observer, cron job or queue consumer). Send in the background, never inside the request that places an order or loads a page.
- Read the API key from Magento's encrypted configuration or app/etc/env.php, never from source code or anything sent to the browser.
- Retry 429 and 5xx later (from the cron job or the queue); don't retry 401 and 403.
- The API key comes from my SMSTunnel dashboard (https://dashboard.smstunnel.io): Apps → Add an app → Create the key. It is shown only once and can send texts and check whether they went out.
SMSTunnel API facts:
- Send a text: POST https://smstunnel.io/api/v1/sms/send with the headers "X-API-Key: <key>" and "Content-Type: application/json", and the JSON body {"to": "+14155550123", "message": "..."}. Optional: "deviceId" (which of my phones sends it; default: my main phone) and "defaultCountryCode". Other fields are refused with 400.
- Call it from a server: browsers can't send the X-API-Key header to SMSTunnel (CORS), and the key must stay secret.
- One recipient per call. To text several people, make one call per number.
- Numbers: international format, with + and the country code. For numbers written without + or 00, "defaultCountryCode" ("44", "+44" or "0044") completes them, and it always takes precedence over the country set for the phone.
- A text can be up to 1600 characters (10 joined SMS).
- Sign-in codes: POST https://smstunnel.io/api/v1/sms/send-2fa, same headers and fields. The text must contain the code as 4 to 10 digits standing on their own (like 482913) or as 123-456, and can be up to 320 characters; otherwise the answer is 400 "No valid verification code found". Codes have their own daily allowance. My app creates and checks the code; SMSTunnel only delivers the text.
- Success: HTTP 200 {"success": true, "messageId": "...", "data": {"messageId": "...", "branded": false, ...}}. "queued": true is added when the phone is offline: the text waits and goes out as soon as the phone is back (for up to 3 days). On the Free plan, 25 texts a day (500 a month) go out as written, up to 25 more a day go out with a short "free by smstunnel.io" line added ("branded": true), and past that the answer is 429.
- Errors: 400 bad input (the "message" field says why, sometimes as a list); 401 missing or invalid key; 403 the key lacks a permission ("code": "PERMISSION_REQUIRED", "permission": "...") or my plan does not include the feature; 429 with a Retry-After header: too many requests (30 send requests a minute per API key, 90 for all keys of one account together), so wait that many seconds, then retry; 429 without Retry-After: the plan's limit for the day or month is reached, so don't retry before then; 5xx: retry later, with a limit.
- Safe retries: send the header "Idempotency-Key: <one key per text>" (1 to 255 printable ASCII characters, such as order-1042-shipped or a UUID stored with the text). A repeat with the same key within 24 hours gets the first answer back (or the same 5xx error) instead of a second text; 409 while the first request is still running, 422 if the key was used for a different text.
- Status: GET https://smstunnel.io/api/v1/sms/status/{messageId} answers {"success": true, "data": {"status": ...}}, with pending, sent, delivered or failed. If "unconfirmed" is true, the phone handed the text to its SIM without getting a confirmation: it was probably sent, so never resend it automatically.
Rules for your answer:
- Keep the API key in an environment variable or the platform's secret store (for example SMSTUNNEL_API_KEY). Never put it in source code, in a repository, or in code that runs in a browser or a mobile app: call SMSTunnel from a server. I will not paste my key in this chat; use a placeholder.
- Validate phone numbers before sending (international format, like +14155550123) and skip or report the invalid ones.
- Handle errors: log or show what went wrong, retry only after 429, 5xx or network errors and only a few times, and never send the same text twice.
- Only send texts people expect from me: alerts to myself, reminders, sign-in codes, updates they asked for. No unsolicited texts. Responsible use
Built for alerts to yourself and your team, and texts people expect from you. One text goes to one number. Sending unsolicited messages from a consumer SIM generally breaches mobile carrier terms of service.
Magento and Adobe Commerce are trademarks of Adobe Inc. Mage-OS is a project of the Mage-OS Association. SMSTunnel is a third-party integration and is not affiliated with, endorsed by, or sponsored by Adobe Inc. or the Mage-OS Association.