diff --git a/.gitignore b/.gitignore
index 6a7d6d8e..be89c02e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -121,6 +121,7 @@ dist
 
 # Stores VSCode versions used for testing VSCode extensions
 .vscode-test
+.vscode
 
 # yarn v2
 .yarn/cache
diff --git a/cpp/whatsapp-with-vonage/.gitignore b/cpp/whatsapp-with-vonage/.gitignore
new file mode 100644
index 00000000..8ab9d44f
--- /dev/null
+++ b/cpp/whatsapp-with-vonage/.gitignore
@@ -0,0 +1,39 @@
+# Prerequisites
+*.d
+
+# Compiled Object files
+*.slo
+*.lo
+*.o
+*.obj
+
+# Precompiled Headers
+*.gch
+*.pch
+
+# Compiled Dynamic libraries
+*.so
+*.dylib
+*.dll
+
+# Fortran module files
+*.mod
+*.smod
+
+# Compiled Static libraries
+*.lai
+*.la
+*.a
+*.lib
+
+# Executables
+*.exe
+*.out
+*.app
+
+# Specific files
+appwrite.json
+RuntimeContext.h
+RuntimeOutput.h
+RuntimeResponse.h
+RuntimeRequest.h
\ No newline at end of file
diff --git a/cpp/whatsapp-with-vonage/README.md b/cpp/whatsapp-with-vonage/README.md
new file mode 100644
index 00000000..2c284e54
--- /dev/null
+++ b/cpp/whatsapp-with-vonage/README.md
@@ -0,0 +1,104 @@
+# 💬 C++ WhatsApp Bot with Vonage Function
+
+Simple bot to answer WhatsApp messages.
+
+## 🧰 Usage
+
+### GET /
+
+HTML form for interacting with the function.
+
+### POST /
+
+Receives a message, validates its signature, and sends a response back to the sender.
+
+**Parameters**
+
+| Name          | Description                        | Location | Type                | Sample Value         |
+| ------------- | ---------------------------------- | -------- | ------------------- | -------------------- |
+| Content-Type  | Content type of the request        | Header   | `application/json ` | N/A                  |
+| Authorization | Webhook signature for verification | Header   | String              | `Bearer <signature>` |
+| from          | Sender's identifier.               | Body     | String              | `12345`              |
+| text          | Text content of the message.       | Body     | String              | `Hello!`             |
+
+> All parameters are coming from Vonage webhook. Exact documentation can be found in [Vonage API Docs](https://developer.vonage.com/en/api/messages-olympus#inbound-message).
+
+**Response**
+
+Sample `200` Response:
+
+```json
+{
+  "ok": true
+}
+```
+
+Sample `400` Response:
+
+```json
+{
+  "ok": false,
+  "error": "Missing required parameter: from"
+}
+```
+
+Sample `401` Response:
+
+```json
+{
+  "ok": false,
+  "error": "Payload hash mismatch."
+}
+```
+
+## ⚙️ Configuration
+
+| Setting           | Value                                                                                                                                             |
+| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
+| Runtime           | C++ (cpp-20)                                                                                                                                      |
+| Entrypoint        | `src/main.cc`                                                                                                                                     |
+| Build Commands    | `git clone https://github.com/Thalhammer/jwt-cpp.git && cd jwt-cpp && mkdir build && cd build && cmake .. && make -j\"$(nproc)\" && make install` |
+| Permissions       | `any`                                                                                                                                             |
+| Timeout (Seconds) | 15                                                                                                                                                |
+
+## 🔒 Environment Variables
+
+### VONAGE_API_KEY
+
+API Key to use the Vonage API.
+
+| Question      | Answer                                                                                                                   |
+| ------------- | ------------------------------------------------------------------------------------------------------------------------ |
+| Required      | Yes                                                                                                                      |
+| Sample Value  | `62...97`                                                                                                                |
+| Documentation | [Vonage: Q&A](https://api.support.vonage.com/hc/en-us/articles/204014493-How-do-I-find-my-Voice-API-key-and-API-secret-) |
+
+### VONAGE_API_SECRET
+
+Secret to use the Vonage API.
+
+| Question      | Answer                                                                                                                   |
+| ------------- | ------------------------------------------------------------------------------------------------------------------------ |
+| Required      | Yes                                                                                                                      |
+| Sample Value  | `Zjc...5PH`                                                                                                              |
+| Documentation | [Vonage: Q&A](https://api.support.vonage.com/hc/en-us/articles/204014493-How-do-I-find-my-Voice-API-key-and-API-secret-) |
+
+### VONAGE_API_SIGNATURE_SECRET
+
+Secret to verify the webhooks sent by Vonage.
+
+| Question      | Answer                                                                                                         |
+| ------------- | -------------------------------------------------------------------------------------------------------------- |
+| Required      | Yes                                                                                                            |
+| Sample Value  | `NXOi3...IBHDa`                                                                                                |
+| Documentation | [Vonage: Webhooks](https://developer.vonage.com/en/getting-started/concepts/webhooks#decoding-signed-webhooks) |
+
+### VONAGE_WHATSAPP_NUMBER
+
+Vonage WhatsApp number to send messages from.
+
+| Question      | Answer                                                                                                                        |
+| ------------- | ----------------------------------------------------------------------------------------------------------------------------- |
+| Required      | Yes                                                                                                                           |
+| Sample Value  | `+14000000102`                                                                                                                |
+| Documentation | [Vonage: Q&A](https://api.support.vonage.com/hc/en-us/articles/4431993282580-Where-do-I-find-my-WhatsApp-Number-Certificate-) |
diff --git a/cpp/whatsapp-with-vonage/src/main.cc b/cpp/whatsapp-with-vonage/src/main.cc
new file mode 100644
index 00000000..8797268f
--- /dev/null
+++ b/cpp/whatsapp-with-vonage/src/main.cc
@@ -0,0 +1,139 @@
+#include <curl/curl.h>
+#include <json/value.h>
+#include <jwt-cpp/jwt.h>
+
+#include <any>
+#include <cstdlib>
+#include <filesystem>
+#include <fstream>
+#include <iostream>
+#include <sstream>
+
+#include "../RuntimeContext.h"
+#include "../RuntimeOutput.h"
+#include "../RuntimeRequest.h"
+#include "../RuntimeResponse.h"
+#include "utils.h"
+
+namespace runtime {
+class Handler {
+   public:
+    static RuntimeOutput main(RuntimeContext& context) {
+        RuntimeRequest req = context.req;
+        RuntimeResponse res = context.res;
+
+        std::string error = checkEnvVars({
+            "VONAGE_API_KEY",
+            "VONAGE_API_SECRET",
+            "VONAGE_API_SIGNATURE_SECRET",
+            "VONAGE_WHATSAPP_NUMBER",
+        });
+        if (error != "") {
+            context.error(error);
+            Json::Value response;
+            response["error"] = error;
+            response["ok"] = false;
+            return res.json(response, 500);
+        }
+
+        if (req.method == "GET") {
+            std::string indexHtml = getStaticFile("index.html");
+            Json::Value headers;
+            headers["Content-Type"] = "text/html; charset=utf-8";
+            return res.send(indexHtml, 200, headers);
+        }
+
+        Json::Value payload = stringToJson(req.bodyRaw);
+        context.log("Payload from webhook\n" + payload.toStyledString());
+        std::vector<std::string> requiredFields = {"from", "text"};
+        std::vector<std::string> missingFields;
+
+        for (const std::string& field : requiredFields)
+            if (!payload.isMember(field)) missingFields.push_back(field);
+        if (!missingFields.empty()) {
+            std::string error = "Missing required fields";
+            int i = 0;
+            for (const std::string& field : missingFields) {
+                error += field;
+                if (i++ < missingFields.size() - 1) error += ", ";
+            }
+            context.error(error);
+            Json::Value response;
+            response["error"] = error;
+            response["ok"] = false;
+            return res.json(response, 400);
+        }
+
+        std::string token = req.headers["authorization"].asString();
+        int space = token.find(" ");
+        token = token.substr(space + 1);
+        jwt::verifier<jwt::default_clock, jwt::traits::kazuho_picojson>
+            verifier = jwt::verify().allow_algorithm(jwt::algorithm::hs256(
+                std::getenv("VONAGE_API_SIGNATURE_SECRET")));
+
+        jwt::decoded_jwt<jwt::traits::kazuho_picojson> decoded =
+            jwt::decode(token);
+        verifier.verify(decoded);
+
+        std::string bodyHash = sha256(req.bodyRaw.c_str());
+        Json::Value jwtBody = stringToJson(decoded.get_payload());
+
+        if (strcmp(jwtBody["payload_hash"].asCString(), bodyHash.c_str()) !=
+            0) {
+            context.error("Payload hash mismatch.");
+            Json::Value response;
+            response["error"] = "Payload hash mismatch.";
+            response["ok"] = false;
+            return res.json(response, 401);
+        }
+
+        std::string apiKey = std::getenv("VONAGE_API_KEY");
+        std::string apiSecret = std::getenv("VONAGE_API_SECRET");
+        std::string basicAuthToken = base64Encode(apiKey + ":" + apiSecret);
+
+        CURL* curl;
+        CURLcode ret;
+        curl = curl_easy_init();
+        struct curl_slist* headers = NULL;
+        std::string url = "https://messages-sandbox.nexmo.com/v1/messages";
+
+        if (curl) {
+            headers =
+                curl_slist_append(headers, "Content-Type: application/json");
+            std::string authHeader = "Authorization: Basic " + basicAuthToken;
+            headers = curl_slist_append(headers, authHeader.c_str());
+            curl_easy_setopt(curl, CURLOPT_URL,
+                             "https://messages-sandbox.nexmo.com/v1/messages");
+            curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
+            Json::Value reqBody;
+            reqBody["from"] = getenv("VONAGE_WHATSAPP_NUMBER");
+            reqBody["to"] = payload["from"];
+            reqBody["message_type"] = "text";
+            reqBody["text"] =
+                "Hi there! You sent me: " + payload["text"].asString();
+            reqBody["channel"] = "whatsapp";
+
+            std::string data = reqBody.toStyledString();
+            curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data.c_str());
+            curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, data.length());
+            curl_easy_setopt(curl, CURLOPT_POST, 1);
+            ret = curl_easy_perform(curl);
+            if (ret != CURLE_OK) {
+                context.error(curl_easy_strerror(ret));
+                Json::Value response;
+                response["error"] = curl_easy_strerror(ret);
+                response["ok"] = false;
+                return res.json(response, 500);
+            }
+            curl_easy_cleanup(curl);
+            curl = NULL;
+            curl_slist_free_all(headers);
+            headers = NULL;
+        }
+
+        Json::Value response;
+        response["ok"] = true;
+        return res.json(response);
+    }
+};
+}  // namespace runtime
diff --git a/cpp/whatsapp-with-vonage/src/utils.h b/cpp/whatsapp-with-vonage/src/utils.h
new file mode 100644
index 00000000..11eb67b0
--- /dev/null
+++ b/cpp/whatsapp-with-vonage/src/utils.h
@@ -0,0 +1,121 @@
+#ifndef UTILS_H
+#define UTILS_H
+
+#include <curl/curl.h>
+#include <json/json.h>
+#include <jwt-cpp/jwt.h>
+
+#include <cstdlib>
+#include <filesystem>
+#include <fstream>
+#include <iostream>
+
+static std::string base64Encode(const std::string& in) {
+    std::string out;
+    int val = 0, valb = -6;
+    for (unsigned char c : in) {
+        val = (val << 8) + c;
+        valb += 8;
+        while (valb >= 0) {
+            out.push_back(
+                "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345"
+                "6789+/"[(val >> valb) & 0x3F]);
+            valb -= 6;
+        }
+    }
+    if (valb > -6)
+        out.push_back(
+            "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
+            "+/"[((val << 8) >> (valb + 8)) & 0x3F]);
+    while (out.size() % 4) out.push_back('=');
+    return out;
+}
+
+static std::string sha256(const char* string) {
+    char outputBuffer[65];
+    unsigned char hash[SHA256_DIGEST_LENGTH];
+    SHA256_CTX sha256;
+    SHA256_Init(&sha256);
+    SHA256_Update(&sha256, string, strlen(string));
+    SHA256_Final(hash, &sha256);
+    int i = 0;
+    for (i = 0; i < SHA256_DIGEST_LENGTH; i++) {
+        sprintf(outputBuffer + (i * 2), "%02x", hash[i]);
+    }
+    outputBuffer[64] = 0;
+    return std::string(outputBuffer);
+}
+
+static Json::Value stringToJson(const std::string& jsonStr) {
+    Json::Value res;
+    Json::Reader reader;
+    bool ok = reader.parse(jsonStr, res, false);
+    if (!ok) {
+        throw std::runtime_error("Failed to parse JSON string.");
+    }
+    return res;
+}
+
+static const char* getStaticFile(std::string filename) {
+    // Serving string directly because of the issue with serving static assets
+    // in cpp template
+    const char* content = R"(
+<!doctype html>
+<html lang="en">
+  <head>
+    <meta charset="UTF-8" />
+    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+    <title>WhatsApp Bot with Vonage</title>
+
+    <link rel="stylesheet" href="https://unpkg.com/@appwrite.io/pink" />
+    <link rel="stylesheet" href="https://unpkg.com/@appwrite.io/pink-icons" />
+  </head>
+  <body>
+    <main class="main-content">
+      <div class="top-cover u-padding-block-end-56">
+        <div class="container">
+          <div
+            class="u-flex u-gap-16 u-flex-justify-center u-margin-block-start-16"
+          >
+            <h1 class="heading-level-1">WhatsApp Bot with Vonage</h1>
+            <code class="u-un-break-text"></code>
+          </div>
+          <p
+            class="body-text-1 u-normal u-margin-block-start-8"
+            style="max-width: 50rem"
+          >
+            This function listens to incoming webhooks from Vonage regarding
+            WhatsApp messages, and responds to them. To use the function, send
+            message to the WhatsApp user provided by Vonage.
+          </p>
+        </div>
+      </div>
+    </main>
+  </body>
+</html>
+    )";
+    return content;
+}
+
+static std::string checkEnvVars(const std::vector<std::string>& envVarNames) {
+    std::vector<std::string> missingVars;
+    for (const std::string& varName : envVarNames) {
+        const char* varValue = std::getenv(varName.c_str());
+        if (varValue == nullptr) {
+            missingVars.push_back(varName);
+        }
+    }
+    if (!missingVars.empty()) {
+        std::string error = "Missing environment variables: ";
+        for (const std::string& missingVar : missingVars) {
+            error += missingVar;
+            error += ", ";
+        }
+        error = error.substr(0, error.length() - 2);
+        return error;
+    }
+    return "";
+}
+
+#endif
\ No newline at end of file
diff --git a/cpp/whatsapp-with-vonage/static/index.html b/cpp/whatsapp-with-vonage/static/index.html
new file mode 100644
index 00000000..3852090f
--- /dev/null
+++ b/cpp/whatsapp-with-vonage/static/index.html
@@ -0,0 +1,34 @@
+<!doctype html>
+<html lang="en">
+  <head>
+    <meta charset="UTF-8" />
+    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+    <title>WhatsApp Bot with Vonage</title>
+
+    <link rel="stylesheet" href="https://unpkg.com/@appwrite.io/pink" />
+    <link rel="stylesheet" href="https://unpkg.com/@appwrite.io/pink-icons" />
+  </head>
+  <body>
+    <main class="main-content">
+      <div class="top-cover u-padding-block-end-56">
+        <div class="container">
+          <div
+            class="u-flex u-gap-16 u-flex-justify-center u-margin-block-start-16"
+          >
+            <h1 class="heading-level-1">WhatsApp Bot with Vonage</h1>
+            <code class="u-un-break-text"></code>
+          </div>
+          <p
+            class="body-text-1 u-normal u-margin-block-start-8"
+            style="max-width: 50rem"
+          >
+            This function listens to incoming webhooks from Vonage regarding
+            WhatsApp messages, and responds to them. To use the function, send
+            message to the WhatsApp user provided by Vonage.
+          </p>
+        </div>
+      </div>
+    </main>
+  </body>
+</html>
