SMSTunnel for Apprise

One Apprise URL that texts you from your own phone

Built into Apprise · no plugin
json:// notification URL
Apprise json:// docs

Every tool that speaks Apprise

Apprise sends notifications from the command line, from the Apprise API, and from the many self-hosted tools that take Apprise URLs, such as changedetection.io and Bazarr. With one URL, each of them hands its message to your SMSTunnel account and your own Android phone texts it to you from your own number.

1. Get your key

  1. 1. Install the SMSTunnel app from Google Play on your Android phone and sign in.
  2. 2. In your dashboard, open Apps → Add an app, pick Script or server, name it (for example "Apprise") and click Create the key.
  3. 3. Copy the key right away: it's shown only once. You can stop or delete the app there anytime, and Apprise can't send texts anymore.

Get the steps with your key in them

It opens Add an app with Script or server picked. Once the key is made, the dashboard shows every step and command with the key already filled in, ready to copy.

2. Your Apprise URL

Replace the key, and the number after :to=%2B (your number without its +):

jsons://smstunnel.io/api/v1/sms/send?+X-API-Key=sk_live_...&:version=&:title=&:attachments=&:type=&:to=%2B14155550123
  • +X-API-Key=… sends your key in the header SMSTunnel reads.
  • :version=, :title=, :attachments= and :type= remove Apprise's own fields, which SMSTunnel would refuse.
  • :to=%2B14155550123 adds your number: %2B is the +, written so it can't turn into a space.
  • Apprise then sends the body as the text. The title is left out.

Try it from the command line:

apprise -vv -b "Backup finished on nas1" \
  "jsons://smstunnel.io/api/v1/sms/send?+X-API-Key=sk_live_...&:version=&:title=&:attachments=&:type=&:to=%2B14155550123"

Then paste the same URL wherever a tool asks for an Apprise URL. A native smstunnel:// plugin has been proposed to Apprise; until it ships, this URL does the job.

Without a key: a webhook address

A webhook address texts up to 10 numbers saved with it, so the Apprise URL needs nothing else. In your dashboard, open Apps → Webhooks → New webhook, pick Something else, add your numbers, click Create the webhook and copy the address. Put jsons:// in place of its https://, and SMSTunnel reads Apprise's own JSON and texts "title: body":

jsons://smstunnel.io/api/v1/webhook/<token>

Worth knowing

  • The URL holds your key. Keep it in a config file only you can read, and give Apprise its own app in SMSTunnel, so you can stop it without touching your other apps.
  • Several people? One URL per number; they can share an Apprise tag. SMSTunnel sends one text to one number per request.
  • 30 sends a minute, up to 1600 characters per text.
  • Phone offline? The text waits and goes out as soon as the phone is back.

If it doesn't work

  • Run Apprise with -vv: it prints SMSTunnel's answer, for example Failed to send JSON POST notification: Verification Failed., error=401.
  • 400 "property … should not exist" after an Apprise update: a new field was added to Apprise's JSON. Add : + that field + = to the URL.
  • 401 "Invalid or expired API key": the key is wrong or was deleted. "API key is required. Use X-API-Key header.": the key isn't in an X-API-Key header. SMSTunnel reads the key only from that header: Bearer or Basic authentication won't work.
  • 403 with PERMISSION_REQUIRED: the key may not send texts. Make a new one under Apps → Add an app.
  • 400 "property … should not exist": the body has a field SMSTunnel doesn't know. Send only to and message (and, if you need them, deviceId and defaultCountryCode). "message must be shorter than or equal to 1600 characters": shorten the text. "Phone number must contain…": put the number in international format, like +14155550123.
  • 400 with "to must be a string" and "message must be a string": the body didn't arrive as JSON. Add the header Content-Type: application/json.
  • 404 "Cannot GET /api/v1/sms/send": the tool sent a GET. Choose POST.
  • 404 "Webhook not found or disabled": the address is wrong, was replaced with New address, or the webhook is stopped or deleted. Copy it again from Apps → Webhooks → Address and setup.
  • 400 "Could not build a message from the payload": the call had no words in it. Add ?message=… to a GET, or a message field to the JSON. With a text of the message, check that the names between braces are the call's.
  • 429: too many texts at once. SMSTunnel takes 30 send requests a minute. Wait a minute and try again.
  • 429 "Rate limit reached for this webhook (20/hour)": the webhook took all its calls for this hour. Wait, or raise Calls an hour (up to 500) with Edit in Apps → Webhooks. It counts calls, not texts: each call texts every number of the webhook.
  • In Apps → Webhooks, the webhook's row shows when it was last used and, if its last call sent no text, why.
  • No text, but no error? If your phone is offline, the text waits and goes out as soon as the phone is back online. Open the SMSTunnel app on the phone to check it's linked.

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 send text messages from my own phone through Apprise (the CLI, the Apprise API, or a tool that takes Apprise URLs), 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:
- No plugin: Apprise's generic json:// (jsons:// for HTTPS) notification calls SMSTunnel's API. A native smstunnel:// plugin has been proposed to Apprise but isn't released yet.
- URL: jsons://smstunnel.io/api/v1/sms/send?+X-API-Key=sk_live_...&:version=&:title=&:attachments=&:type=&:to=%2B14155550123
- How it works: "+X-API-Key=…" adds the header; ":version=", ":title=", ":attachments=" and ":type=" drop Apprise's own JSON fields (SMSTunnel refuses unknown fields with 400); ":to=%2B14155550123" adds the number (%2B is the +). Apprise then posts {"message": "<body>", "to": "+14155550123"} as JSON. The title is dropped: only the body is texted.
- Without a key: jsons://smstunnel.io/api/v1/webhook/<token> (an SMSTunnel webhook address made in my dashboard with Something else picked, with jsons:// in place of https://). Apprise's own JSON goes there and SMSTunnel texts "<title>: <body>" to the numbers saved in the webhook.
- Without a key: an SMSTunnel webhook address, https://smstunnel.io/api/v1/webhook/<token>. I make it in my dashboard (https://dashboard.smstunnel.io): Apps → Webhooks → New webhook, pick the tool that will call it (Grafana, Uptime Kuma, Healthchecks, Gatus, Alertmanager, Odoo Online, or Something else), add 1 to 10 numbers (each gets its own text), optionally a text of the message that pulls fields out of the JSON with {{path}}, like {{alarm.name}}, then Create the webhook and copy the address. A GET with ?message=… or a POST with JSON (its message, text, title or body field) texts those numbers; the call never sets the number. Texts are cut at 480 characters. "Calls an hour" (20 unless I set another number, up to 500) counts calls, not texts: each call texts every number, and calls past it are refused until the hour is over. The address can be copied again under Address and setup; New address replaces it if it leaks. Scripts can make one with POST https://smstunnel.io/api/v1/webhooks and my sign-in token instead.
- One recipient per request: SMSTunnel sends one text to one number. For several people, one request (or one notification) per number. In Apprise, one URL per number (they can share a tag).
- The key is part of the URL, so the URL is a secret: keep it in a config file only I can read, not in a shared script.
- Answers: 200 {"success": true, "messageId": "…"}; 401 wrong or deleted key; 403 the key lacks a permission ("code": "PERMISSION_REQUIRED"); 400 a missing, unknown or too long field; 429 too many requests (30 sends a minute, with Retry-After): wait and retry; without Retry-After, the plan's limit for the day or month is reached. If my phone is offline the text waits and goes out when it is back, within 3 days.
- 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.

Rules for your answer:
- Do not ask for my SMSTunnel password or API key and do not put a real key in your answer; I will not paste it in this chat.
- Phone numbers must be in international format (+ and the country code).
- Help me test it with my own number first.
- Only send texts people expect from me. No unsolicited texts.
- If a newer Apprise adds a field to its JSON and SMSTunnel answers 400 "property … should not exist", add ":<that field>=" to the URL.

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.

Apprise is an open-source project by Chris Caron. SMSTunnel is a third-party integration and is not affiliated with, endorsed by, or sponsored by the Apprise project.

No phone paired yet?

Install the Android app and sign in with your account, and you're ready in about a minute.

Get it on Google Play