diff --git a/docs/c-api/http.h/intro.md b/docs/c-api/http.h/intro.md
index f070b4b5a1e837dc2b58703b15724e1a75695e4f..df5df05fb4574862db45f06eeb73bbdb058235e7 100644
--- a/docs/c-api/http.h/intro.md
+++ b/docs/c-api/http.h/intro.md
@@ -15,6 +15,7 @@ items:
   - { name: struct_http_message.md }
   - { name: struct_websocket_message.md }
   - { name: struct_mg_http_multipart_part.md }
+  - { name: struct_mg_ssi_call_ctx.md }
 ---
 
 
diff --git a/docs/c-api/http.h/struct_mg_ssi_call_ctx.md b/docs/c-api/http.h/struct_mg_ssi_call_ctx.md
new file mode 100644
index 0000000000000000000000000000000000000000..2b430fd11968430dbe815ef52d2bdc601d18a609
--- /dev/null
+++ b/docs/c-api/http.h/struct_mg_ssi_call_ctx.md
@@ -0,0 +1,14 @@
+---
+title: "struct mg_ssi_call_ctx"
+decl_name: "struct mg_ssi_call_ctx"
+symbol_kind: "struct"
+signature: |
+  struct mg_ssi_call_ctx {
+    struct http_message *req; /* The request being processed. */
+    struct mg_str file;       /* Filesystem path of the file being processed. */
+    struct mg_str arg; /* The argument passed to the tag: <!-- call arg -->. */
+  };
+---
+
+SSI call context 
+
diff --git a/mongoose.c b/mongoose.c
index 111930bfd2101d4828c90dd28865ae46f55c10d9..24ba9916b86542d7a7ccdeda456f73f5adef569c 100644
--- a/mongoose.c
+++ b/mongoose.c
@@ -5385,8 +5385,9 @@ static void mg_http_send_error(struct mg_connection *nc, int code,
   nc->flags |= MG_F_SEND_AND_CLOSE;
 }
 #ifndef MG_DISABLE_SSI
-static void mg_send_ssi_file(struct mg_connection *, const char *, FILE *, int,
-                             const struct mg_serve_http_opts *);
+static void mg_send_ssi_file(struct mg_connection *nc, struct http_message *hm,
+                             const char *path, FILE *fp, int include_level,
+                             const struct mg_serve_http_opts *opts);
 
 static void mg_send_file_data(struct mg_connection *nc, FILE *fp) {
   char buf[BUFSIZ];
@@ -5396,8 +5397,8 @@ static void mg_send_file_data(struct mg_connection *nc, FILE *fp) {
   }
 }
 
-static void mg_do_ssi_include(struct mg_connection *nc, const char *ssi,
-                              char *tag, int include_level,
+static void mg_do_ssi_include(struct mg_connection *nc, struct http_message *hm,
+                              const char *ssi, char *tag, int include_level,
                               const struct mg_serve_http_opts *opts) {
   char file_name[BUFSIZ], path[MAX_PATH_SIZE], *p;
   FILE *fp;
@@ -5434,7 +5435,7 @@ static void mg_do_ssi_include(struct mg_connection *nc, const char *ssi,
     mg_set_close_on_exec(fileno(fp));
     if (mg_match_prefix(opts->ssi_pattern, strlen(opts->ssi_pattern), path) >
         0) {
-      mg_send_ssi_file(nc, path, fp, include_level + 1, opts);
+      mg_send_ssi_file(nc, hm, path, fp, include_level + 1, opts);
     } else {
       mg_send_file_data(nc, fp);
     }
@@ -5458,16 +5459,12 @@ static void do_ssi_exec(struct mg_connection *nc, char *tag) {
 }
 #endif /* !MG_DISABLE_POPEN */
 
-static void mg_do_ssi_call(struct mg_connection *nc, char *tag) {
-  mg_call(nc, NULL, MG_EV_SSI_CALL, tag);
-}
-
 /*
  * SSI directive has the following format:
  * <!--#directive parameter=value parameter=value -->
  */
-static void mg_send_ssi_file(struct mg_connection *nc, const char *path,
-                             FILE *fp, int include_level,
+static void mg_send_ssi_file(struct mg_connection *nc, struct http_message *hm,
+                             const char *path, FILE *fp, int include_level,
                              const struct mg_serve_http_opts *opts) {
   static const struct mg_str btag = MG_MK_STR("<!--#");
   static const struct mg_str d_include = MG_MK_STR("include");
@@ -5497,9 +5494,17 @@ static void mg_send_ssi_file(struct mg_connection *nc, const char *path,
 
       /* Handle known SSI directives */
       if (memcmp(p, d_include.p, d_include.len) == 0) {
-        mg_do_ssi_include(nc, path, p + d_include.len + 1, include_level, opts);
+        mg_do_ssi_include(nc, hm, path, p + d_include.len + 1, include_level,
+                          opts);
       } else if (memcmp(p, d_call.p, d_call.len) == 0) {
-        mg_do_ssi_call(nc, p + d_call.len + 1);
+        struct mg_ssi_call_ctx cctx;
+        memset(&cctx, 0, sizeof(cctx));
+        cctx.req = hm;
+        cctx.file = mg_mk_str(path);
+        cctx.arg = mg_mk_str(p + d_call.len + 1);
+        mg_call(nc, NULL, MG_EV_SSI_CALL,
+                (void *) cctx.arg.p); /* NUL added above */
+        mg_call(nc, NULL, MG_EV_SSI_CALL_CTX, &cctx);
 #ifndef MG_DISABLE_POPEN
       } else if (memcmp(p, d_exec.p, d_exec.len) == 0) {
         do_ssi_exec(nc, p + d_exec.len + 1);
@@ -5539,7 +5544,8 @@ static void mg_send_ssi_file(struct mg_connection *nc, const char *path,
   }
 }
 
-static void mg_handle_ssi_request(struct mg_connection *nc, const char *path,
+static void mg_handle_ssi_request(struct mg_connection *nc,
+                                  struct http_message *hm, const char *path,
                                   const struct mg_serve_http_opts *opts) {
   FILE *fp;
   struct mg_str mime_type;
@@ -5556,15 +5562,17 @@ static void mg_handle_ssi_request(struct mg_connection *nc, const char *path,
               "Content-Type: %.*s\r\n"
               "Connection: close\r\n\r\n",
               (int) mime_type.len, mime_type.p);
-    mg_send_ssi_file(nc, path, fp, 0, opts);
+    mg_send_ssi_file(nc, hm, path, fp, 0, opts);
     fclose(fp);
     nc->flags |= MG_F_SEND_AND_CLOSE;
   }
 }
 #else
-static void mg_handle_ssi_request(struct mg_connection *nc, const char *path,
+static void mg_handle_ssi_request(struct mg_connection *nc,
+                                  struct http_message *hm, const char *path,
                                   const struct mg_serve_http_opts *opts) {
   (void) path;
+  (void) hm;
   (void) opts;
   mg_http_send_error(nc, 500, "SSI disabled");
 }
@@ -5696,7 +5704,7 @@ static void mg_http_serve_file2(struct mg_connection *nc, const char *path,
                                 struct http_message *hm,
                                 struct mg_serve_http_opts *opts) {
   if (mg_match_prefix(opts->ssi_pattern, strlen(opts->ssi_pattern), path) > 0) {
-    mg_handle_ssi_request(nc, path, opts);
+    mg_handle_ssi_request(nc, hm, path, opts);
     return;
   }
   mg_http_serve_file(nc, hm, path, mg_get_mime_type(path, "text/plain", opts),
diff --git a/mongoose.h b/mongoose.h
index c4a8ce7593106744db48b2e13fa29991b615584d..f24aa6ecddbdb414f0828f703b96ab90b722dbb8 100644
--- a/mongoose.h
+++ b/mongoose.h
@@ -2170,11 +2170,19 @@ struct mg_http_multipart_part {
   void *user_data;
 };
 
+/* SSI call context */
+struct mg_ssi_call_ctx {
+  struct http_message *req; /* The request being processed. */
+  struct mg_str file;       /* Filesystem path of the file being processed. */
+  struct mg_str arg; /* The argument passed to the tag: <!-- call arg -->. */
+};
+
 /* HTTP and websocket events. void *ev_data is described in a comment. */
 #define MG_EV_HTTP_REQUEST 100 /* struct http_message * */
 #define MG_EV_HTTP_REPLY 101   /* struct http_message * */
 #define MG_EV_HTTP_CHUNK 102   /* struct http_message * */
 #define MG_EV_SSI_CALL 105     /* char * */
+#define MG_EV_SSI_CALL_CTX 106 /* struct mg_ssi_call_ctx * */
 
 #ifndef MG_DISABLE_HTTP_WEBSOCKET
 #define MG_EV_WEBSOCKET_HANDSHAKE_REQUEST 111 /* NULL */