diff --git a/server/notification-providers/sevenio.js b/server/notification-providers/sevenio.js
new file mode 100644
index 000000000..d363e95d0
--- /dev/null
+++ b/server/notification-providers/sevenio.js
@@ -0,0 +1,78 @@
+const NotificationProvider = require("./notification-provider");
+const axios = require("axios");
+const { DOWN, UP } = require("../../src/util");
+
+class SevenIO extends NotificationProvider {
+ name = "SevenIO";
+
+ /**
+ * @inheritdoc
+ */
+ async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
+ const okMsg = "Sent Successfully.";
+
+ const data = {
+ to: notification.sevenioTo,
+ from: notification.sevenioSender || "Uptime Kuma",
+ text: msg,
+ };
+
+ const config = {
+ baseURL: "https://gateway.seven.io/api/",
+ headers: {
+ "Content-Type": "application/json",
+ "X-API-Key": notification.sevenioApiKey,
+ },
+ };
+
+ try {
+ // testing or certificate expiry notification
+ if (heartbeatJSON == null) {
+ await axios.post("sms", data, config);
+ return okMsg;
+ }
+
+ let address = "";
+
+ switch (monitorJSON["type"]) {
+ case "ping":
+ address = monitorJSON["hostname"];
+ break;
+ case "port":
+ case "dns":
+ case "gamedig":
+ case "steam":
+ address = monitorJSON["hostname"];
+ if (monitorJSON["port"]) {
+ address += ":" + monitorJSON["port"];
+ }
+ break;
+ default:
+ if (![ "https://", "http://", "" ].includes(monitorJSON["url"])) {
+ address = monitorJSON["url"];
+ }
+ break;
+ }
+
+ if (address !== "") {
+ address = `(${address}) `;
+ }
+
+ // If heartbeatJSON is not null, we go into the normal alerting loop.
+ if (heartbeatJSON["status"] === DOWN) {
+ data.text = `Your service ${monitorJSON["name"]} ${address}went down at ${heartbeatJSON["localDateTime"]} ` +
+ `(${heartbeatJSON["timezone"]}). Error: ${heartbeatJSON["msg"]}`;
+ } else if (heartbeatJSON["status"] === UP) {
+ data.text = `Your service ${monitorJSON["name"]} ${address}went back up at ${heartbeatJSON["localDateTime"]} ` +
+ `(${heartbeatJSON["timezone"]}).`;
+ }
+ await axios.post("sms", data, config);
+ return okMsg;
+ } catch (error) {
+ this.throwGeneralAxiosError(error);
+ }
+ }
+
+}
+
+module.exports = SevenIO;
diff --git a/server/notification.js b/server/notification.js
index f5a952061..b64bb1b56 100644
--- a/server/notification.js
+++ b/server/notification.js
@@ -56,6 +56,7 @@ const GoAlert = require("./notification-providers/goalert");
const SMSManager = require("./notification-providers/smsmanager");
const ServerChan = require("./notification-providers/serverchan");
const ZohoCliq = require("./notification-providers/zoho-cliq");
+const SevenIO = require("./notification-providers/sevenio");
const Whapi = require("./notification-providers/whapi");
const GtxMessaging = require("./notification-providers/gtx-messaging");
const Cellsynt = require("./notification-providers/cellsynt");
@@ -132,6 +133,7 @@ class Notification {
new WeCom(),
new GoAlert(),
new ZohoCliq(),
+ new SevenIO(),
new Whapi(),
new GtxMessaging(),
new Cellsynt(),
diff --git a/src/components/NotificationDialog.vue b/src/components/NotificationDialog.vue
index f57e0628a..347fa2308 100644
--- a/src/components/NotificationDialog.vue
+++ b/src/components/NotificationDialog.vue
@@ -154,6 +154,7 @@ export default {
"webhook": "Webhook",
"GoAlert": "GoAlert",
"ZohoCliq": "ZohoCliq",
+ "SevenIO": "SevenIO",
"whapi": "WhatsApp (Whapi)",
"gtxmessaging": "GtxMessaging",
"Cellsynt": "Cellsynt",
diff --git a/src/components/notifications/SevenIO.vue b/src/components/notifications/SevenIO.vue
new file mode 100644
index 000000000..fcf746ec8
--- /dev/null
+++ b/src/components/notifications/SevenIO.vue
@@ -0,0 +1,31 @@
+
+
+
+
+
+ {{ $t("wayToGetSevenIOApiKey") }}
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ $t("receiverInfoSevenIO") }}
+
+
+
+
+
diff --git a/src/components/notifications/index.js b/src/components/notifications/index.js
index 458322384..51107ac9f 100644
--- a/src/components/notifications/index.js
+++ b/src/components/notifications/index.js
@@ -55,6 +55,7 @@ import WeCom from "./WeCom.vue";
import GoAlert from "./GoAlert.vue";
import ZohoCliq from "./ZohoCliq.vue";
import Splunk from "./Splunk.vue";
+import SevenIO from "./SevenIO.vue";
import Whapi from "./Whapi.vue";
import Cellsynt from "./Cellsynt.vue";
@@ -119,6 +120,7 @@ const NotificationFormList = {
"GoAlert": GoAlert,
"ServerChan": ServerChan,
"ZohoCliq": ZohoCliq,
+ "SevenIO": SevenIO,
"whapi": Whapi,
"gtxmessaging": GtxMessaging,
"Cellsynt": Cellsynt,
diff --git a/src/lang/en.json b/src/lang/en.json
index 696b0ca67..45e800d9e 100644
--- a/src/lang/en.json
+++ b/src/lang/en.json
@@ -890,6 +890,11 @@
"deleteRemoteBrowserMessage": "Are you sure want to delete this Remote Browser for all monitors?",
"GrafanaOncallUrl": "Grafana Oncall URL",
"Browser Screenshot": "Browser Screenshot",
+ "wayToGetSevenIOApiKey": "Visit the dashboard under app.seven.io > developer > api key > the green add button",
+ "senderSevenIO": "Sending number or name",
+ "receiverSevenIO": "Receiving number",
+ "receiverInfoSevenIO": "If the receiving number is not located in Germany, you have to add the country code in front of the number (e.g. for the country code 1 from the US use 117612121212 instead of 017612121212)",
+ "apiKeySevenIO": "SevenIO API Key",
"wayToWriteWhapiRecipient": "The phone number with the international prefix, but without the plus sign at the start ({0}), the Contact ID ({1}) or the Group ID ({2}).",
"wayToGetWhapiUrlAndToken": "You can get the API URL and the token by going into your desired channel from {0}",
"whapiRecipient": "Phone Number / Contact ID / Group ID",