diff --git a/CHANGES b/CHANGES
index e42cfcb8b37cecccb73a33990b001c0c5b5c92b7..dc5f0584c4de5c2324c0cd24a373087094bfc896 100644
--- a/CHANGES
+++ b/CHANGES
@@ -50,6 +50,14 @@ res_pjsip_endpoint_identifier_ip
    source IP addresses for requests. This is configurable using the
    "srv_lookups" option on the identify and defaults to "yes".
 
+ARI
+------------------
+ * The 'ari set debug' command has been enhanced to accept 'all' as an
+   application name.  This allows dumping of all apps even if an app
+   hasn't registered yet.
+
+ * 'ari set debug' now displays requests and responses as well as events.
+ 
 ------------------------------------------------------------------------------
 --- Functionality changes from Asterisk 13.12.0 to Asterisk 13.13.0 ----------
 ------------------------------------------------------------------------------
diff --git a/include/asterisk/ari.h b/include/asterisk/ari.h
index 1c54a694b538af1ad513a19c5f472f50a21afe1e..cad9b32c5cecdc25ffd360d2016f39d901c0f656 100644
--- a/include/asterisk/ari.h
+++ b/include/asterisk/ari.h
@@ -59,7 +59,8 @@ struct ast_ari_response;
 typedef void (*stasis_rest_callback)(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response);
+	struct ast_variable *headers, struct ast_json *body,
+	struct ast_ari_response *response);
 
 /*!
  * \brief Handler for a single RESTful path segment.
@@ -134,7 +135,7 @@ int ast_ari_remove_handler(struct stasis_rest_handlers *handler);
 void ast_ari_invoke(struct ast_tcptls_session_instance *ser,
 	const char *uri, enum ast_http_method method,
 	struct ast_variable *get_params, struct ast_variable *headers,
-	struct ast_ari_response *response);
+	struct ast_json *body, struct ast_ari_response *response);
 
 /*!
  * \internal
@@ -188,6 +189,25 @@ struct ast_json *ast_ari_websocket_session_read(
 int ast_ari_websocket_session_write(struct ast_ari_websocket_session *session,
 	struct ast_json *message);
 
+/*!
+ * \brief Get the Session ID for an ARI WebSocket.
+ *
+ * \param session Session to query.
+ * \return Session ID.
+ * \return \c NULL on error.
+ */
+const char *ast_ari_websocket_session_id(
+	const struct ast_ari_websocket_session *session);
+
+/*!
+ * \brief Get the remote address from an ARI WebSocket.
+ *
+ * \param session Session to write to.
+ * \return ast_sockaddr (does not have to be freed)
+ */
+struct ast_sockaddr *ast_ari_websocket_session_get_remote_addr(
+	struct ast_ari_websocket_session *session);
+
 /*!
  * \brief The stock message to return when out of memory.
  *
diff --git a/include/asterisk/stasis_app.h b/include/asterisk/stasis_app.h
index 53ce116a9e4985acfa275e2f6dee91faf224ef0c..6f9897c09e85e89689709f72c558d31a5bfda874 100644
--- a/include/asterisk/stasis_app.h
+++ b/include/asterisk/stasis_app.h
@@ -891,6 +891,55 @@ int stasis_app_channel_unreal_set_internal(struct ast_channel *chan);
  */
 int stasis_app_channel_set_internal(struct ast_channel *chan);
 
+/*!
+ * \brief Enable/disable request/response and event logging on an application
+ *
+ * \param app The app to debug
+ * \param debug If non-zero, enable debugging. If zero, disable.
+ */
+void stasis_app_set_debug(struct stasis_app *app, int debug);
+
+/*!
+ * \brief Enable/disable request/response and event logging on an application
+ *
+ * \param app_name The app name to debug
+ * \param debug If non-zero, enable debugging. If zero, disable.
+ */
+void stasis_app_set_debug_by_name(const char *app_name, int debug);
+
+/*!
+ * \brief Get debug status of an application
+ *
+ * \param app The app to check
+ * \return The debug flag for the app || the global debug flag
+ */
+int stasis_app_get_debug(struct stasis_app *app);
+
+/*!
+ * \brief Get debug status of an application
+ *
+ * \param app_name The app_name to check
+ * \return The debug flag for the app || the global debug flag
+ */
+int stasis_app_get_debug_by_name(const char *app_name);
+
+/*!
+ * \brief Enable/disable request/response and event logging on all applications
+ *
+ * \param debug If non-zero, enable debugging. If zero, disable.
+ */
+void stasis_app_set_global_debug(int debug);
+
+struct ast_cli_args;
+
+/*!
+ * \brief Dump properties of a \c stasis_app to the CLI
+ *
+ * \param app The application
+ * \param a The CLI arguments
+ */
+void stasis_app_to_cli(const struct stasis_app *app, struct ast_cli_args *a);
+
 /*! @} */
 
 #endif /* _ASTERISK_STASIS_APP_H */
diff --git a/main/strings.c b/main/strings.c
index 7cb55def0d922194e53efbe74ade2882b864b219..7f2025abe46ded9177120abf477dc5c5b064ce66 100644
--- a/main/strings.c
+++ b/main/strings.c
@@ -186,15 +186,32 @@ static int str_hash(const void *obj, const int flags)
 	return ast_str_hash(obj);
 }
 
+static int str_sort(const void *lhs, const void *rhs, int flags)
+{
+	if ((flags & OBJ_SEARCH_MASK) == OBJ_SEARCH_PARTIAL_KEY) {
+		return strncmp(lhs, rhs, strlen(rhs));
+	} else {
+		return strcmp(lhs, rhs);
+	}
+}
+
 static int str_cmp(void *lhs, void *rhs, int flags)
 {
-	return strcmp(lhs, rhs) ? 0 : CMP_MATCH;
+	int cmp = 0;
+
+	if ((flags & OBJ_SEARCH_MASK) == OBJ_SEARCH_PARTIAL_KEY) {
+		cmp = strncmp(lhs, rhs, strlen(rhs));
+	} else {
+		cmp = strcmp(lhs, rhs);
+	}
+
+	return cmp ? 0 : CMP_MATCH;
 }
 
 //struct ao2_container *ast_str_container_alloc_options(enum ao2_container_opts opts, int buckets)
 struct ao2_container *ast_str_container_alloc_options(enum ao2_alloc_opts opts, int buckets)
 {
-	return ao2_container_alloc_options(opts, buckets, str_hash, str_cmp);
+	return ao2_container_alloc_hash(opts, 0, buckets, str_hash, str_sort, str_cmp);
 }
 
 int ast_str_container_add(struct ao2_container *str_container, const char *add)
diff --git a/res/ari/ari_websockets.c b/res/ari/ari_websockets.c
index f06a6675088ce9dd5b318e4827d24398f7eca235..6a296dcf66fb84404a4ab6e37b995c8fd7aedff8 100644
--- a/res/ari/ari_websockets.c
+++ b/res/ari/ari_websockets.c
@@ -23,6 +23,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/ari.h"
 #include "asterisk/astobj2.h"
 #include "asterisk/http_websocket.h"
+#include "asterisk/stasis_app.h"
 #include "internal.h"
 
 /*! \file
@@ -139,6 +140,7 @@ struct ast_json *ast_ari_websocket_session_read(
 				ast_log(LOG_WARNING,
 					"WebSocket input failed to parse\n");
 			}
+
 			break;
 		default:
 			/* Ignore all other message types */
@@ -174,16 +176,20 @@ int ast_ari_websocket_session_write(struct ast_ari_websocket_session *session,
 		return -1;
 	}
 
-#ifdef AST_DEVMODE
-	ast_debug(3, "Examining ARI event (length %u): \n%s\n", (unsigned int) strlen(str), str);
-#endif
 	if (ast_websocket_write_string(session->ws_session, str)) {
-		ast_log(LOG_NOTICE, "Problem occurred during websocket write, websocket closed\n");
+		ast_log(LOG_NOTICE, "Problem occurred during websocket write to %s, websocket closed\n",
+			ast_sockaddr_stringify(ast_ari_websocket_session_get_remote_addr(session)));
 		return -1;
 	}
 	return 0;
 }
 
+struct ast_sockaddr *ast_ari_websocket_session_get_remote_addr(
+	struct ast_ari_websocket_session *session)
+{
+	return ast_websocket_remote_address(session->ws_session);
+}
+
 void ari_handle_websocket(struct ast_websocket_server *ws_server,
 	struct ast_tcptls_session_instance *ser, const char *uri,
 	enum ast_http_method method, struct ast_variable *get_params,
diff --git a/res/ari/cli.c b/res/ari/cli.c
index 819407997f9a90e5f6429345ea1f0fceedd6734c..90c1773060334a80b23632e7634447102dba001e 100644
--- a/res/ari/cli.c
+++ b/res/ari/cli.c
@@ -28,6 +28,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 
 #include "asterisk/astobj2.h"
 #include "asterisk/cli.h"
+#include "asterisk/stasis_app.h"
 #include "internal.h"
 
 static char *ari_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
@@ -251,11 +252,185 @@ static char *ari_mkpasswd(struct ast_cli_entry *e, int cmd, struct ast_cli_args
 	return CLI_SUCCESS;
 }
 
+static char *ari_show_apps(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+	struct ao2_container *apps;
+	struct ao2_iterator it_apps;
+	char *app;
+
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "ari show apps";
+		e->usage =
+			"Usage: ari show apps\n"
+			"       Lists all registered applications.\n"
+			;
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	default:
+		break;
+	}
+
+	if (a->argc != 3) {
+		return CLI_SHOWUSAGE;
+	}
+
+	apps = stasis_app_get_all();
+	if (!apps) {
+		ast_cli(a->fd, "Unable to retrieve registered applications!\n");
+		return CLI_FAILURE;
+	}
+
+	ast_cli(a->fd, "Application Name         \n");
+	ast_cli(a->fd, "=========================\n");
+	it_apps = ao2_iterator_init(apps, 0);
+	while ((app = ao2_iterator_next(&it_apps))) {
+		ast_cli(a->fd, "%-25.25s\n", app);
+		ao2_ref(app, -1);
+	}
+
+	ao2_iterator_destroy(&it_apps);
+	ao2_ref(apps, -1);
+
+	return CLI_SUCCESS;
+}
+
+struct app_complete {
+	/*! Nth app to search for */
+	int state;
+	/*! Which app currently on */
+	int which;
+};
+
+static int complete_ari_app_search(void *obj, void *arg, void *data, int flags)
+{
+	struct app_complete *search = data;
+
+	if (++search->which > search->state) {
+		return CMP_MATCH;
+	}
+	return 0;
+}
+
+static char *complete_ari_app(struct ast_cli_args *a, int include_all)
+{
+	RAII_VAR(struct ao2_container *, apps, stasis_app_get_all(), ao2_cleanup);
+	RAII_VAR(char *, app, NULL, ao2_cleanup);
+
+	struct app_complete search = {
+		.state = a->n,
+	};
+
+	if (a->pos != 3) {
+		return NULL;
+	}
+
+	if (!apps) {
+		ast_cli(a->fd, "Error getting ARI applications\n");
+		return CLI_FAILURE;
+	}
+
+	if (include_all && ast_strlen_zero(a->word)) {
+		ast_str_container_add(apps, " all");
+	}
+
+	app = ao2_callback_data(apps,
+		ast_strlen_zero(a->word) ? 0 : OBJ_SEARCH_PARTIAL_KEY,
+		complete_ari_app_search, (char*)a->word, &search);
+
+	return app ? ast_strdup(app) : NULL;
+}
+
+static char *ari_show_app(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+	void *app;
+
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "ari show app";
+		e->usage =
+			"Usage: ari show app <application>\n"
+			"       Provide detailed information about a registered application.\n"
+			;
+		return NULL;
+	case CLI_GENERATE:
+		return complete_ari_app(a, 0);
+	default:
+		break;
+	}
+
+	if (a->argc != 4) {
+		return CLI_SHOWUSAGE;
+	}
+
+	app = stasis_app_get_by_name(a->argv[3]);
+	if (!app) {
+		return CLI_FAILURE;
+	}
+
+	stasis_app_to_cli(app, a);
+
+	ao2_ref(app, -1);
+
+	return CLI_SUCCESS;
+}
+
+static char *ari_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+	void *app;
+	int debug;
+
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "ari set debug";
+		e->usage =
+			"Usage: ari set debug <application|all> <on|off>\n"
+			"       Enable or disable debugging on a specific application.\n"
+			;
+		return NULL;
+	case CLI_GENERATE:
+		return complete_ari_app(a, 1);
+	default:
+		break;
+	}
+
+	if (a->argc != 5) {
+		return CLI_SHOWUSAGE;
+	}
+
+	debug = !strcmp(a->argv[4], "on");
+
+	if (!strcmp(a->argv[3], "all")) {
+		stasis_app_set_global_debug(debug);
+		ast_cli(a->fd, "Debugging on all applications %s\n",
+			debug ? "enabled" : "disabled");
+		return CLI_SUCCESS;
+	}
+
+	app = stasis_app_get_by_name(a->argv[3]);
+	if (!app) {
+		return CLI_FAILURE;
+	}
+
+	stasis_app_set_debug(app, debug);
+	ast_cli(a->fd, "Debugging on '%s' %s\n",
+		stasis_app_name(app),
+		debug ? "enabled" : "disabled");
+
+	ao2_ref(app, -1);
+
+	return CLI_SUCCESS;
+}
+
 static struct ast_cli_entry cli_ari[] = {
 	AST_CLI_DEFINE(ari_show, "Show ARI settings"),
 	AST_CLI_DEFINE(ari_show_users, "List ARI users"),
 	AST_CLI_DEFINE(ari_show_user, "List single ARI user"),
 	AST_CLI_DEFINE(ari_mkpasswd, "Encrypts a password"),
+	AST_CLI_DEFINE(ari_show_apps, "List registered ARI applications"),
+	AST_CLI_DEFINE(ari_show_app, "Display details of a registered ARI application"),
+	AST_CLI_DEFINE(ari_set_debug, "Enable/disable debugging of an ARI application"),
 };
 
 int ast_ari_cli_register(void) {
diff --git a/res/ari/resource_events.c b/res/ari/resource_events.c
index 71d54b49469aa1e0c05ebca62f1a2450c2e70ea1..535ce70eea363c7bd6dd05355cca76c2d8179848 100644
--- a/res/ari/resource_events.c
+++ b/res/ari/resource_events.c
@@ -139,6 +139,15 @@ static void app_handler(void *data, const char *app_name,
 
 	ao2_lock(session);
 	if (session->ws_session) {
+		if (stasis_app_get_debug_by_name(app_name)) {
+			char *str = ast_json_dump_string_format(message, ast_ari_json_format());
+
+			ast_verbose("<--- Sending ARI event to %s --->\n%s\n",
+				ast_sockaddr_stringify(ast_ari_websocket_session_get_remote_addr(session->ws_session)),
+				str);
+			ast_json_free(str);
+		}
+
 		ast_ari_websocket_session_write(session->ws_session, message);
 	}
 	ao2_unlock(session);
diff --git a/res/res_ari.c b/res/res_ari.c
index 4ff98ce962a04252a37fa09917ba44ff762530ac..c6f81dcefa42011af6ea25d75ad97098018cc495 100644
--- a/res/res_ari.c
+++ b/res/res_ari.c
@@ -147,6 +147,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/astobj2.h"
 #include "asterisk/module.h"
 #include "asterisk/paths.h"
+#include "asterisk/stasis_app.h"
 
 #include <string.h>
 #include <sys/stat.h>
@@ -490,7 +491,7 @@ static void handle_options(struct stasis_rest_handlers *handler,
 void ast_ari_invoke(struct ast_tcptls_session_instance *ser,
 	const char *uri, enum ast_http_method method,
 	struct ast_variable *get_params, struct ast_variable *headers,
-	struct ast_ari_response *response)
+	struct ast_json *body, struct ast_ari_response *response)
 {
 	RAII_VAR(struct stasis_rest_handlers *, root, NULL, ao2_cleanup);
 	struct stasis_rest_handlers *handler;
@@ -505,8 +506,10 @@ void ast_ari_invoke(struct ast_tcptls_session_instance *ser,
 	while ((path_segment = strsep(&path, "/")) && (strlen(path_segment) > 0)) {
 		struct stasis_rest_handlers *found_handler = NULL;
 		int i;
+
 		ast_uri_decode(path_segment, ast_uri_http_legacy);
 		ast_debug(3, "Finding handler for %s\n", path_segment);
+
 		for (i = 0; found_handler == NULL && i < handler->num_children; ++i) {
 			struct stasis_rest_handlers *child = handler->children[i];
 
@@ -568,7 +571,7 @@ void ast_ari_invoke(struct ast_tcptls_session_instance *ser,
 		return;
 	}
 
-	callback(ser, get_params, path_vars, headers, response);
+	callback(ser, get_params, path_vars, headers, body, response);
 	if (response->message == NULL && response->response_code == 0) {
 		/* Really should not happen */
 		ast_log(LOG_ERROR, "ARI %s %s not implemented\n",
@@ -878,6 +881,10 @@ static int ast_ari_callback(struct ast_tcptls_session_instance *ser,
 	RAII_VAR(struct ast_ari_conf_user *, user, NULL, ao2_cleanup);
 	struct ast_ari_response response = {};
 	RAII_VAR(struct ast_variable *, post_vars, NULL, ast_variables_destroy);
+	struct ast_variable *var;
+	const char *app_name = NULL;
+	RAII_VAR(struct ast_json *, body, ast_json_null(), ast_json_free);
+	int debug_app = 0;
 
 	if (!response_body) {
 		ast_http_request_close_on_completion(ser);
@@ -925,6 +932,25 @@ static int ast_ari_callback(struct ast_tcptls_session_instance *ser,
 				"Bad Request", "Error parsing request body");
 			goto request_failed;
 		}
+
+		/* Look for a JSON request entity only if there were no post_vars.
+		 * If there were post_vars, then the request body would already have
+		 * been consumed and can not be read again.
+		 */
+		body = ast_http_get_json(ser, headers);
+		if (!body) {
+			switch (errno) {
+			case EFBIG:
+				ast_ari_response_error(&response, 413, "Request Entity Too Large", "Request body too large");
+				goto request_failed;
+			case ENOMEM:
+				ast_ari_response_error(&response, 500, "Internal Server Error", "Error processing request");
+				goto request_failed;
+			case EIO:
+				ast_ari_response_error(&response, 400, "Bad Request", "Error parsing request body");
+				goto request_failed;
+			}
+		}
 	}
 	if (get_params == NULL) {
 		get_params = post_vars;
@@ -941,6 +967,41 @@ static int ast_ari_callback(struct ast_tcptls_session_instance *ser,
 		get_params = post_vars;
 	}
 
+	/* At this point, get_params will contain post_vars (if any) */
+	app_name = ast_variable_find_in_list(get_params, "app");
+	if (!app_name) {
+		struct ast_json *app = ast_json_object_get(body, "app");
+
+		app_name = (app ? ast_json_string_get(app) : NULL);
+	}
+
+	/* stasis_app_get_debug_by_name returns an "||" of the app's debug flag
+	 * and the global debug flag.
+	 */
+	debug_app = stasis_app_get_debug_by_name(app_name);
+	if (debug_app) {
+		struct ast_str *buf = ast_str_create(512);
+		char *str = ast_json_dump_string_format(body, ast_ari_json_format());
+
+		if (!buf) {
+			ast_http_request_close_on_completion(ser);
+			ast_http_error(ser, 500, "Server Error", "Out of memory");
+			goto request_failed;
+		}
+
+		ast_str_append(&buf, 0, "<--- ARI request received from: %s --->\n",
+			ast_sockaddr_stringify(&ser->remote_address));
+		for (var = headers; var; var = var->next) {
+			ast_str_append(&buf, 0, "%s: %s\n", var->name, var->value);
+		}
+		for (var = get_params; var; var = var->next) {
+			ast_str_append(&buf, 0, "%s: %s\n", var->name, var->value);
+		}
+		ast_verbose("%sbody:\n%s\n\n", ast_str_buffer(buf), str);
+		ast_json_free(str);
+		ast_free(buf);
+	}
+
 	user = authenticate_user(get_params, headers);
 	if (response.response_code > 0) {
 		/* POST parameter processing error. Do nothing. */
@@ -979,7 +1040,7 @@ static int ast_ari_callback(struct ast_tcptls_session_instance *ser,
 		}
 	} else {
 		/* Other RESTful resources */
-		ast_ari_invoke(ser, uri, method, get_params, headers,
+		ast_ari_invoke(ser, uri, method, get_params, headers, body,
 			&response);
 	}
 
@@ -991,6 +1052,7 @@ static int ast_ari_callback(struct ast_tcptls_session_instance *ser,
 	}
 
 request_failed:
+
 	/* If you explicitly want to have no content, set message to
 	 * ast_json_null().
 	 */
@@ -1013,8 +1075,13 @@ request_failed:
 		}
 	}
 
-	ast_debug(3, "Examining ARI response:\n%d %s\n%s\n%s\n", response.response_code,
-		response.response_text, ast_str_buffer(response.headers), ast_str_buffer(response_body));
+	if (debug_app) {
+		ast_verbose("<--- Sending ARI response to %s --->\n%d %s\n%s%s\n\n",
+			ast_sockaddr_stringify(&ser->remote_address), response.response_code,
+			response.response_text, ast_str_buffer(response.headers),
+			ast_str_buffer(response_body));
+	}
+
 	ast_http_send(ser, method, response.response_code,
 		      response.response_text, response.headers, response_body,
 		      0, 0);
diff --git a/res/res_ari_applications.c b/res/res_ari_applications.c
index dd868a602f2cd78c64859a794d792bcf2ec9260c..ac2c3ba426bb35b9fda4713f3ac1f783e322697c 100644
--- a/res/res_ari_applications.c
+++ b/res/res_ari_applications.c
@@ -62,10 +62,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 static void ast_ari_applications_list_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_applications_list_args args = {};
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -113,11 +112,10 @@ fin: __attribute__((unused))
 static void ast_ari_applications_get_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_applications_get_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -210,11 +208,10 @@ int ast_ari_applications_subscribe_parse_body(
 static void ast_ari_applications_subscribe_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_applications_subscribe_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -272,21 +269,6 @@ static void ast_ari_applications_subscribe_cb(
 		} else
 		{}
 	}
-	/* Look for a JSON request entity */
-	body = ast_http_get_json(ser, headers);
-	if (!body) {
-		switch (errno) {
-		case EFBIG:
-			ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-			goto fin;
-		case ENOMEM:
-			ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-			goto fin;
-		case EIO:
-			ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-			goto fin;
-		}
-	}
 	if (ast_ari_applications_subscribe_parse_body(body, &args)) {
 		ast_ari_response_alloc_failed(response);
 		goto fin;
@@ -376,11 +358,10 @@ int ast_ari_applications_unsubscribe_parse_body(
 static void ast_ari_applications_unsubscribe_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_applications_unsubscribe_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -438,21 +419,6 @@ static void ast_ari_applications_unsubscribe_cb(
 		} else
 		{}
 	}
-	/* Look for a JSON request entity */
-	body = ast_http_get_json(ser, headers);
-	if (!body) {
-		switch (errno) {
-		case EFBIG:
-			ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-			goto fin;
-		case ENOMEM:
-			ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-			goto fin;
-		case EIO:
-			ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-			goto fin;
-		}
-	}
 	if (ast_ari_applications_unsubscribe_parse_body(body, &args)) {
 		ast_ari_response_alloc_failed(response);
 		goto fin;
diff --git a/res/res_ari_asterisk.c b/res/res_ari_asterisk.c
index b52a2a72236d58706b419cc14bff63950758499f..b1680e300a8a1b02d845e214e683d6e6ba5d43c9 100644
--- a/res/res_ari_asterisk.c
+++ b/res/res_ari_asterisk.c
@@ -62,11 +62,10 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 static void ast_ari_asterisk_get_object_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_asterisk_get_object_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -135,11 +134,10 @@ int ast_ari_asterisk_update_object_parse_body(
 static void ast_ari_asterisk_update_object_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_asterisk_update_object_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -157,21 +155,6 @@ static void ast_ari_asterisk_update_object_cb(
 		} else
 		{}
 	}
-	/* Look for a JSON request entity */
-	body = ast_http_get_json(ser, headers);
-	if (!body) {
-		switch (errno) {
-		case EFBIG:
-			ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-			goto fin;
-		case ENOMEM:
-			ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-			goto fin;
-		case EIO:
-			ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-			goto fin;
-		}
-	}
 	args.fields = body;
 	ast_ari_asterisk_update_object(headers, &args, response);
 #if defined(AST_DEVMODE)
@@ -218,11 +201,10 @@ fin: __attribute__((unused))
 static void ast_ari_asterisk_delete_object_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_asterisk_delete_object_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -322,11 +304,10 @@ int ast_ari_asterisk_get_info_parse_body(
 static void ast_ari_asterisk_get_info_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_asterisk_get_info_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -378,21 +359,6 @@ static void ast_ari_asterisk_get_info_cb(
 		} else
 		{}
 	}
-	/* Look for a JSON request entity */
-	body = ast_http_get_json(ser, headers);
-	if (!body) {
-		switch (errno) {
-		case EFBIG:
-			ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-			goto fin;
-		case ENOMEM:
-			ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-			goto fin;
-		case EIO:
-			ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-			goto fin;
-		}
-	}
 	if (ast_ari_asterisk_get_info_parse_body(body, &args)) {
 		ast_ari_response_alloc_failed(response);
 		goto fin;
@@ -441,10 +407,9 @@ fin: __attribute__((unused))
 static void ast_ari_asterisk_list_modules_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_asterisk_list_modules_args args = {};
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -492,11 +457,10 @@ fin: __attribute__((unused))
 static void ast_ari_asterisk_get_module_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_asterisk_get_module_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -552,11 +516,10 @@ fin: __attribute__((unused))
 static void ast_ari_asterisk_load_module_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_asterisk_load_module_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -611,11 +574,10 @@ fin: __attribute__((unused))
 static void ast_ari_asterisk_unload_module_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_asterisk_unload_module_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -671,11 +633,10 @@ fin: __attribute__((unused))
 static void ast_ari_asterisk_reload_module_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_asterisk_reload_module_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -731,10 +692,9 @@ fin: __attribute__((unused))
 static void ast_ari_asterisk_list_log_channels_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_asterisk_list_log_channels_args args = {};
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -795,11 +755,10 @@ int ast_ari_asterisk_add_log_parse_body(
 static void ast_ari_asterisk_add_log_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_asterisk_add_log_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -817,21 +776,6 @@ static void ast_ari_asterisk_add_log_cb(
 		} else
 		{}
 	}
-	/* Look for a JSON request entity */
-	body = ast_http_get_json(ser, headers);
-	if (!body) {
-		switch (errno) {
-		case EFBIG:
-			ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-			goto fin;
-		case ENOMEM:
-			ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-			goto fin;
-		case EIO:
-			ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-			goto fin;
-		}
-	}
 	if (ast_ari_asterisk_add_log_parse_body(body, &args)) {
 		ast_ari_response_alloc_failed(response);
 		goto fin;
@@ -880,11 +824,10 @@ fin: __attribute__((unused))
 static void ast_ari_asterisk_delete_log_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_asterisk_delete_log_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -939,11 +882,10 @@ fin: __attribute__((unused))
 static void ast_ari_asterisk_rotate_log_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_asterisk_rotate_log_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -1011,11 +953,10 @@ int ast_ari_asterisk_get_global_var_parse_body(
 static void ast_ari_asterisk_get_global_var_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_asterisk_get_global_var_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -1027,21 +968,6 @@ static void ast_ari_asterisk_get_global_var_cb(
 		} else
 		{}
 	}
-	/* Look for a JSON request entity */
-	body = ast_http_get_json(ser, headers);
-	if (!body) {
-		switch (errno) {
-		case EFBIG:
-			ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-			goto fin;
-		case ENOMEM:
-			ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-			goto fin;
-		case EIO:
-			ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-			goto fin;
-		}
-	}
 	if (ast_ari_asterisk_get_global_var_parse_body(body, &args)) {
 		ast_ari_response_alloc_failed(response);
 		goto fin;
@@ -1106,11 +1032,10 @@ int ast_ari_asterisk_set_global_var_parse_body(
 static void ast_ari_asterisk_set_global_var_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_asterisk_set_global_var_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -1125,21 +1050,6 @@ static void ast_ari_asterisk_set_global_var_cb(
 		} else
 		{}
 	}
-	/* Look for a JSON request entity */
-	body = ast_http_get_json(ser, headers);
-	if (!body) {
-		switch (errno) {
-		case EFBIG:
-			ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-			goto fin;
-		case ENOMEM:
-			ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-			goto fin;
-		case EIO:
-			ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-			goto fin;
-		}
-	}
 	if (ast_ari_asterisk_set_global_var_parse_body(body, &args)) {
 		ast_ari_response_alloc_failed(response);
 		goto fin;
diff --git a/res/res_ari_bridges.c b/res/res_ari_bridges.c
index 458192d882530debb81b28c383a4c62ba54ff074..2889c15152ab8f5419eea659ee7c7358ed47b701 100644
--- a/res/res_ari_bridges.c
+++ b/res/res_ari_bridges.c
@@ -62,10 +62,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 static void ast_ari_bridges_list_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_bridges_list_args args = {};
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -134,11 +133,10 @@ int ast_ari_bridges_create_parse_body(
 static void ast_ari_bridges_create_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_bridges_create_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -156,21 +154,6 @@ static void ast_ari_bridges_create_cb(
 		} else
 		{}
 	}
-	/* Look for a JSON request entity */
-	body = ast_http_get_json(ser, headers);
-	if (!body) {
-		switch (errno) {
-		case EFBIG:
-			ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-			goto fin;
-		case ENOMEM:
-			ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-			goto fin;
-		case EIO:
-			ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-			goto fin;
-		}
-	}
 	if (ast_ari_bridges_create_parse_body(body, &args)) {
 		ast_ari_response_alloc_failed(response);
 		goto fin;
@@ -234,11 +217,10 @@ int ast_ari_bridges_create_with_id_parse_body(
 static void ast_ari_bridges_create_with_id_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_bridges_create_with_id_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -259,21 +241,6 @@ static void ast_ari_bridges_create_with_id_cb(
 		} else
 		{}
 	}
-	/* Look for a JSON request entity */
-	body = ast_http_get_json(ser, headers);
-	if (!body) {
-		switch (errno) {
-		case EFBIG:
-			ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-			goto fin;
-		case ENOMEM:
-			ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-			goto fin;
-		case EIO:
-			ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-			goto fin;
-		}
-	}
 	if (ast_ari_bridges_create_with_id_parse_body(body, &args)) {
 		ast_ari_response_alloc_failed(response);
 		goto fin;
@@ -320,11 +287,10 @@ fin: __attribute__((unused))
 static void ast_ari_bridges_get_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_bridges_get_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -379,11 +345,10 @@ fin: __attribute__((unused))
 static void ast_ari_bridges_destroy_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_bridges_destroy_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -480,11 +445,10 @@ int ast_ari_bridges_add_channel_parse_body(
 static void ast_ari_bridges_add_channel_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_bridges_add_channel_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -545,21 +509,6 @@ static void ast_ari_bridges_add_channel_cb(
 		} else
 		{}
 	}
-	/* Look for a JSON request entity */
-	body = ast_http_get_json(ser, headers);
-	if (!body) {
-		switch (errno) {
-		case EFBIG:
-			ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-			goto fin;
-		case ENOMEM:
-			ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-			goto fin;
-		case EIO:
-			ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-			goto fin;
-		}
-	}
 	if (ast_ari_bridges_add_channel_parse_body(body, &args)) {
 		ast_ari_response_alloc_failed(response);
 		goto fin;
@@ -650,11 +599,10 @@ int ast_ari_bridges_remove_channel_parse_body(
 static void ast_ari_bridges_remove_channel_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_bridges_remove_channel_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -712,21 +660,6 @@ static void ast_ari_bridges_remove_channel_cb(
 		} else
 		{}
 	}
-	/* Look for a JSON request entity */
-	body = ast_http_get_json(ser, headers);
-	if (!body) {
-		switch (errno) {
-		case EFBIG:
-			ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-			goto fin;
-		case ENOMEM:
-			ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-			goto fin;
-		case EIO:
-			ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-			goto fin;
-		}
-	}
 	if (ast_ari_bridges_remove_channel_parse_body(body, &args)) {
 		ast_ari_response_alloc_failed(response);
 		goto fin;
@@ -779,11 +712,10 @@ fin: __attribute__((unused))
 static void ast_ari_bridges_set_video_source_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_bridges_set_video_source_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -843,11 +775,10 @@ fin: __attribute__((unused))
 static void ast_ari_bridges_clear_video_source_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_bridges_clear_video_source_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -915,11 +846,10 @@ int ast_ari_bridges_start_moh_parse_body(
 static void ast_ari_bridges_start_moh_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_bridges_start_moh_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -937,21 +867,6 @@ static void ast_ari_bridges_start_moh_cb(
 		} else
 		{}
 	}
-	/* Look for a JSON request entity */
-	body = ast_http_get_json(ser, headers);
-	if (!body) {
-		switch (errno) {
-		case EFBIG:
-			ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-			goto fin;
-		case ENOMEM:
-			ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-			goto fin;
-		case EIO:
-			ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-			goto fin;
-		}
-	}
 	if (ast_ari_bridges_start_moh_parse_body(body, &args)) {
 		ast_ari_response_alloc_failed(response);
 		goto fin;
@@ -1000,11 +915,10 @@ fin: __attribute__((unused))
 static void ast_ari_bridges_stop_moh_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_bridges_stop_moh_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -1089,11 +1003,10 @@ int ast_ari_bridges_play_parse_body(
 static void ast_ari_bridges_play_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_bridges_play_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -1123,21 +1036,6 @@ static void ast_ari_bridges_play_cb(
 		} else
 		{}
 	}
-	/* Look for a JSON request entity */
-	body = ast_http_get_json(ser, headers);
-	if (!body) {
-		switch (errno) {
-		case EFBIG:
-			ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-			goto fin;
-		case ENOMEM:
-			ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-			goto fin;
-		case EIO:
-			ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-			goto fin;
-		}
-	}
 	if (ast_ari_bridges_play_parse_body(body, &args)) {
 		ast_ari_response_alloc_failed(response);
 		goto fin;
@@ -1211,11 +1109,10 @@ int ast_ari_bridges_play_with_id_parse_body(
 static void ast_ari_bridges_play_with_id_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_bridges_play_with_id_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -1245,21 +1142,6 @@ static void ast_ari_bridges_play_with_id_cb(
 		} else
 		{}
 	}
-	/* Look for a JSON request entity */
-	body = ast_http_get_json(ser, headers);
-	if (!body) {
-		switch (errno) {
-		case EFBIG:
-			ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-			goto fin;
-		case ENOMEM:
-			ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-			goto fin;
-		case EIO:
-			ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-			goto fin;
-		}
-	}
 	if (ast_ari_bridges_play_with_id_parse_body(body, &args)) {
 		ast_ari_response_alloc_failed(response);
 		goto fin;
@@ -1345,11 +1227,10 @@ int ast_ari_bridges_record_parse_body(
 static void ast_ari_bridges_record_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_bridges_record_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -1385,21 +1266,6 @@ static void ast_ari_bridges_record_cb(
 		} else
 		{}
 	}
-	/* Look for a JSON request entity */
-	body = ast_http_get_json(ser, headers);
-	if (!body) {
-		switch (errno) {
-		case EFBIG:
-			ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-			goto fin;
-		case ENOMEM:
-			ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-			goto fin;
-		case EIO:
-			ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-			goto fin;
-		}
-	}
 	if (ast_ari_bridges_record_parse_body(body, &args)) {
 		ast_ari_response_alloc_failed(response);
 		goto fin;
diff --git a/res/res_ari_channels.c b/res/res_ari_channels.c
index 8cb3388fe654e3de5e0fa844269ea5505543780f..fca0cef05d48f99870b9ba8f75a757812fdb5953 100644
--- a/res/res_ari_channels.c
+++ b/res/res_ari_channels.c
@@ -62,10 +62,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 static void ast_ari_channels_list_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_channels_list_args args = {};
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -174,11 +173,10 @@ int ast_ari_channels_originate_parse_body(
 static void ast_ari_channels_originate_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_channels_originate_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -226,21 +224,6 @@ static void ast_ari_channels_originate_cb(
 		} else
 		{}
 	}
-	/* Look for a JSON request entity */
-	body = ast_http_get_json(ser, headers);
-	if (!body) {
-		switch (errno) {
-		case EFBIG:
-			ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-			goto fin;
-		case ENOMEM:
-			ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-			goto fin;
-		case EIO:
-			ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-			goto fin;
-		}
-	}
 	args.variables = body;
 	ast_ari_channels_originate(headers, &args, response);
 #if defined(AST_DEVMODE)
@@ -286,11 +269,10 @@ fin: __attribute__((unused))
 static void ast_ari_channels_get_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_channels_get_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -402,11 +384,10 @@ int ast_ari_channels_originate_with_id_parse_body(
 static void ast_ari_channels_originate_with_id_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_channels_originate_with_id_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -457,21 +438,6 @@ static void ast_ari_channels_originate_with_id_cb(
 		} else
 		{}
 	}
-	/* Look for a JSON request entity */
-	body = ast_http_get_json(ser, headers);
-	if (!body) {
-		switch (errno) {
-		case EFBIG:
-			ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-			goto fin;
-		case ENOMEM:
-			ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-			goto fin;
-		case EIO:
-			ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-			goto fin;
-		}
-	}
 	args.variables = body;
 	ast_ari_channels_originate_with_id(headers, &args, response);
 #if defined(AST_DEVMODE)
@@ -530,11 +496,10 @@ int ast_ari_channels_hangup_parse_body(
 static void ast_ari_channels_hangup_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_channels_hangup_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -552,21 +517,6 @@ static void ast_ari_channels_hangup_cb(
 		} else
 		{}
 	}
-	/* Look for a JSON request entity */
-	body = ast_http_get_json(ser, headers);
-	if (!body) {
-		switch (errno) {
-		case EFBIG:
-			ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-			goto fin;
-		case ENOMEM:
-			ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-			goto fin;
-		case EIO:
-			ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-			goto fin;
-		}
-	}
 	if (ast_ari_channels_hangup_parse_body(body, &args)) {
 		ast_ari_response_alloc_failed(response);
 		goto fin;
@@ -640,11 +590,10 @@ int ast_ari_channels_continue_in_dialplan_parse_body(
 static void ast_ari_channels_continue_in_dialplan_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_channels_continue_in_dialplan_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -671,21 +620,6 @@ static void ast_ari_channels_continue_in_dialplan_cb(
 		} else
 		{}
 	}
-	/* Look for a JSON request entity */
-	body = ast_http_get_json(ser, headers);
-	if (!body) {
-		switch (errno) {
-		case EFBIG:
-			ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-			goto fin;
-		case ENOMEM:
-			ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-			goto fin;
-		case EIO:
-			ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-			goto fin;
-		}
-	}
 	if (ast_ari_channels_continue_in_dialplan_parse_body(body, &args)) {
 		ast_ari_response_alloc_failed(response);
 		goto fin;
@@ -747,11 +681,10 @@ int ast_ari_channels_redirect_parse_body(
 static void ast_ari_channels_redirect_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_channels_redirect_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -769,21 +702,6 @@ static void ast_ari_channels_redirect_cb(
 		} else
 		{}
 	}
-	/* Look for a JSON request entity */
-	body = ast_http_get_json(ser, headers);
-	if (!body) {
-		switch (errno) {
-		case EFBIG:
-			ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-			goto fin;
-		case ENOMEM:
-			ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-			goto fin;
-		case EIO:
-			ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-			goto fin;
-		}
-	}
 	if (ast_ari_channels_redirect_parse_body(body, &args)) {
 		ast_ari_response_alloc_failed(response);
 		goto fin;
@@ -834,11 +752,10 @@ fin: __attribute__((unused))
 static void ast_ari_channels_answer_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_channels_answer_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -894,11 +811,10 @@ fin: __attribute__((unused))
 static void ast_ari_channels_ring_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_channels_ring_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -954,11 +870,10 @@ fin: __attribute__((unused))
 static void ast_ari_channels_ring_stop_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_channels_ring_stop_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -1043,11 +958,10 @@ int ast_ari_channels_send_dtmf_parse_body(
 static void ast_ari_channels_send_dtmf_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_channels_send_dtmf_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -1077,21 +991,6 @@ static void ast_ari_channels_send_dtmf_cb(
 		} else
 		{}
 	}
-	/* Look for a JSON request entity */
-	body = ast_http_get_json(ser, headers);
-	if (!body) {
-		switch (errno) {
-		case EFBIG:
-			ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-			goto fin;
-		case ENOMEM:
-			ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-			goto fin;
-		case EIO:
-			ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-			goto fin;
-		}
-	}
 	if (ast_ari_channels_send_dtmf_parse_body(body, &args)) {
 		ast_ari_response_alloc_failed(response);
 		goto fin;
@@ -1154,11 +1053,10 @@ int ast_ari_channels_mute_parse_body(
 static void ast_ari_channels_mute_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_channels_mute_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -1176,21 +1074,6 @@ static void ast_ari_channels_mute_cb(
 		} else
 		{}
 	}
-	/* Look for a JSON request entity */
-	body = ast_http_get_json(ser, headers);
-	if (!body) {
-		switch (errno) {
-		case EFBIG:
-			ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-			goto fin;
-		case ENOMEM:
-			ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-			goto fin;
-		case EIO:
-			ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-			goto fin;
-		}
-	}
 	if (ast_ari_channels_mute_parse_body(body, &args)) {
 		ast_ari_response_alloc_failed(response);
 		goto fin;
@@ -1252,11 +1135,10 @@ int ast_ari_channels_unmute_parse_body(
 static void ast_ari_channels_unmute_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_channels_unmute_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -1274,21 +1156,6 @@ static void ast_ari_channels_unmute_cb(
 		} else
 		{}
 	}
-	/* Look for a JSON request entity */
-	body = ast_http_get_json(ser, headers);
-	if (!body) {
-		switch (errno) {
-		case EFBIG:
-			ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-			goto fin;
-		case ENOMEM:
-			ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-			goto fin;
-		case EIO:
-			ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-			goto fin;
-		}
-	}
 	if (ast_ari_channels_unmute_parse_body(body, &args)) {
 		ast_ari_response_alloc_failed(response);
 		goto fin;
@@ -1337,11 +1204,10 @@ fin: __attribute__((unused))
 static void ast_ari_channels_hold_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_channels_hold_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -1397,11 +1263,10 @@ fin: __attribute__((unused))
 static void ast_ari_channels_unhold_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_channels_unhold_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -1470,11 +1335,10 @@ int ast_ari_channels_start_moh_parse_body(
 static void ast_ari_channels_start_moh_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_channels_start_moh_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -1492,21 +1356,6 @@ static void ast_ari_channels_start_moh_cb(
 		} else
 		{}
 	}
-	/* Look for a JSON request entity */
-	body = ast_http_get_json(ser, headers);
-	if (!body) {
-		switch (errno) {
-		case EFBIG:
-			ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-			goto fin;
-		case ENOMEM:
-			ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-			goto fin;
-		case EIO:
-			ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-			goto fin;
-		}
-	}
 	if (ast_ari_channels_start_moh_parse_body(body, &args)) {
 		ast_ari_response_alloc_failed(response);
 		goto fin;
@@ -1555,11 +1404,10 @@ fin: __attribute__((unused))
 static void ast_ari_channels_stop_moh_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_channels_stop_moh_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -1615,11 +1463,10 @@ fin: __attribute__((unused))
 static void ast_ari_channels_start_silence_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_channels_start_silence_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -1675,11 +1522,10 @@ fin: __attribute__((unused))
 static void ast_ari_channels_stop_silence_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_channels_stop_silence_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -1764,11 +1610,10 @@ int ast_ari_channels_play_parse_body(
 static void ast_ari_channels_play_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_channels_play_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -1798,21 +1643,6 @@ static void ast_ari_channels_play_cb(
 		} else
 		{}
 	}
-	/* Look for a JSON request entity */
-	body = ast_http_get_json(ser, headers);
-	if (!body) {
-		switch (errno) {
-		case EFBIG:
-			ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-			goto fin;
-		case ENOMEM:
-			ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-			goto fin;
-		case EIO:
-			ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-			goto fin;
-		}
-	}
 	if (ast_ari_channels_play_parse_body(body, &args)) {
 		ast_ari_response_alloc_failed(response);
 		goto fin;
@@ -1886,11 +1716,10 @@ int ast_ari_channels_play_with_id_parse_body(
 static void ast_ari_channels_play_with_id_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_channels_play_with_id_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -1920,21 +1749,6 @@ static void ast_ari_channels_play_with_id_cb(
 		} else
 		{}
 	}
-	/* Look for a JSON request entity */
-	body = ast_http_get_json(ser, headers);
-	if (!body) {
-		switch (errno) {
-		case EFBIG:
-			ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-			goto fin;
-		case ENOMEM:
-			ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-			goto fin;
-		case EIO:
-			ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-			goto fin;
-		}
-	}
 	if (ast_ari_channels_play_with_id_parse_body(body, &args)) {
 		ast_ari_response_alloc_failed(response);
 		goto fin;
@@ -2020,11 +1834,10 @@ int ast_ari_channels_record_parse_body(
 static void ast_ari_channels_record_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_channels_record_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -2060,21 +1873,6 @@ static void ast_ari_channels_record_cb(
 		} else
 		{}
 	}
-	/* Look for a JSON request entity */
-	body = ast_http_get_json(ser, headers);
-	if (!body) {
-		switch (errno) {
-		case EFBIG:
-			ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-			goto fin;
-		case ENOMEM:
-			ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-			goto fin;
-		case EIO:
-			ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-			goto fin;
-		}
-	}
 	if (ast_ari_channels_record_parse_body(body, &args)) {
 		ast_ari_response_alloc_failed(response);
 		goto fin;
@@ -2138,11 +1936,10 @@ int ast_ari_channels_get_channel_var_parse_body(
 static void ast_ari_channels_get_channel_var_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_channels_get_channel_var_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -2160,21 +1957,6 @@ static void ast_ari_channels_get_channel_var_cb(
 		} else
 		{}
 	}
-	/* Look for a JSON request entity */
-	body = ast_http_get_json(ser, headers);
-	if (!body) {
-		switch (errno) {
-		case EFBIG:
-			ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-			goto fin;
-		case ENOMEM:
-			ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-			goto fin;
-		case EIO:
-			ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-			goto fin;
-		}
-	}
 	if (ast_ari_channels_get_channel_var_parse_body(body, &args)) {
 		ast_ari_response_alloc_failed(response);
 		goto fin;
@@ -2241,11 +2023,10 @@ int ast_ari_channels_set_channel_var_parse_body(
 static void ast_ari_channels_set_channel_var_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_channels_set_channel_var_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -2266,21 +2047,6 @@ static void ast_ari_channels_set_channel_var_cb(
 		} else
 		{}
 	}
-	/* Look for a JSON request entity */
-	body = ast_http_get_json(ser, headers);
-	if (!body) {
-		switch (errno) {
-		case EFBIG:
-			ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-			goto fin;
-		case ENOMEM:
-			ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-			goto fin;
-		case EIO:
-			ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-			goto fin;
-		}
-	}
 	if (ast_ari_channels_set_channel_var_parse_body(body, &args)) {
 		ast_ari_response_alloc_failed(response);
 		goto fin;
@@ -2359,11 +2125,10 @@ int ast_ari_channels_snoop_channel_parse_body(
 static void ast_ari_channels_snoop_channel_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_channels_snoop_channel_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -2393,21 +2158,6 @@ static void ast_ari_channels_snoop_channel_cb(
 		} else
 		{}
 	}
-	/* Look for a JSON request entity */
-	body = ast_http_get_json(ser, headers);
-	if (!body) {
-		switch (errno) {
-		case EFBIG:
-			ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-			goto fin;
-		case ENOMEM:
-			ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-			goto fin;
-		case EIO:
-			ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-			goto fin;
-		}
-	}
 	if (ast_ari_channels_snoop_channel_parse_body(body, &args)) {
 		ast_ari_response_alloc_failed(response);
 		goto fin;
@@ -2481,11 +2231,10 @@ int ast_ari_channels_snoop_channel_with_id_parse_body(
 static void ast_ari_channels_snoop_channel_with_id_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_channels_snoop_channel_with_id_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -2515,21 +2264,6 @@ static void ast_ari_channels_snoop_channel_with_id_cb(
 		} else
 		{}
 	}
-	/* Look for a JSON request entity */
-	body = ast_http_get_json(ser, headers);
-	if (!body) {
-		switch (errno) {
-		case EFBIG:
-			ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-			goto fin;
-		case ENOMEM:
-			ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-			goto fin;
-		case EIO:
-			ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-			goto fin;
-		}
-	}
 	if (ast_ari_channels_snoop_channel_with_id_parse_body(body, &args)) {
 		ast_ari_response_alloc_failed(response);
 		goto fin;
diff --git a/res/res_ari_device_states.c b/res/res_ari_device_states.c
index 6d5d19f58e3c5ab650b2e4e07b0664a33c824a61..cf0b7a9896541c81d08d373e9c064633fea10b83 100644
--- a/res/res_ari_device_states.c
+++ b/res/res_ari_device_states.c
@@ -62,10 +62,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 static void ast_ari_device_states_list_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_device_states_list_args args = {};
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -113,11 +112,10 @@ fin: __attribute__((unused))
 static void ast_ari_device_states_get_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_device_states_get_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -184,11 +182,10 @@ int ast_ari_device_states_update_parse_body(
 static void ast_ari_device_states_update_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_device_states_update_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -206,21 +203,6 @@ static void ast_ari_device_states_update_cb(
 		} else
 		{}
 	}
-	/* Look for a JSON request entity */
-	body = ast_http_get_json(ser, headers);
-	if (!body) {
-		switch (errno) {
-		case EFBIG:
-			ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-			goto fin;
-		case ENOMEM:
-			ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-			goto fin;
-		case EIO:
-			ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-			goto fin;
-		}
-	}
 	if (ast_ari_device_states_update_parse_body(body, &args)) {
 		ast_ari_response_alloc_failed(response);
 		goto fin;
@@ -269,11 +251,10 @@ fin: __attribute__((unused))
 static void ast_ari_device_states_delete_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_device_states_delete_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
diff --git a/res/res_ari_endpoints.c b/res/res_ari_endpoints.c
index e3ade435d1d5cac2faae655308d41e884d2dc74a..4a5ddd9e2c0f9c5284e46b72e405d505842bdcd4 100644
--- a/res/res_ari_endpoints.c
+++ b/res/res_ari_endpoints.c
@@ -62,10 +62,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 static void ast_ari_endpoints_list_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_endpoints_list_args args = {};
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -134,11 +133,10 @@ int ast_ari_endpoints_send_message_parse_body(
 static void ast_ari_endpoints_send_message_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_endpoints_send_message_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -156,21 +154,6 @@ static void ast_ari_endpoints_send_message_cb(
 		} else
 		{}
 	}
-	/* Look for a JSON request entity */
-	body = ast_http_get_json(ser, headers);
-	if (!body) {
-		switch (errno) {
-		case EFBIG:
-			ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-			goto fin;
-		case ENOMEM:
-			ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-			goto fin;
-		case EIO:
-			ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-			goto fin;
-		}
-	}
 	args.variables = body;
 	ast_ari_endpoints_send_message(headers, &args, response);
 #if defined(AST_DEVMODE)
@@ -216,11 +199,10 @@ fin: __attribute__((unused))
 static void ast_ari_endpoints_list_by_tech_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_endpoints_list_by_tech_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -275,11 +257,10 @@ fin: __attribute__((unused))
 static void ast_ari_endpoints_get_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_endpoints_get_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -355,11 +336,10 @@ int ast_ari_endpoints_send_message_to_endpoint_parse_body(
 static void ast_ari_endpoints_send_message_to_endpoint_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_endpoints_send_message_to_endpoint_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -383,21 +363,6 @@ static void ast_ari_endpoints_send_message_to_endpoint_cb(
 		} else
 		{}
 	}
-	/* Look for a JSON request entity */
-	body = ast_http_get_json(ser, headers);
-	if (!body) {
-		switch (errno) {
-		case EFBIG:
-			ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-			goto fin;
-		case ENOMEM:
-			ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-			goto fin;
-		case EIO:
-			ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-			goto fin;
-		}
-	}
 	args.variables = body;
 	ast_ari_endpoints_send_message_to_endpoint(headers, &args, response);
 #if defined(AST_DEVMODE)
diff --git a/res/res_ari_events.c b/res/res_ari_events.c
index e85db4c4510e20f8ac843b44514270893b11ef24..d102428bbeaacfde14d2ad966434a977e8944743 100644
--- a/res/res_ari_events.c
+++ b/res/res_ari_events.c
@@ -288,11 +288,10 @@ int ast_ari_events_user_event_parse_body(
 static void ast_ari_events_user_event_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_events_user_event_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -353,21 +352,6 @@ static void ast_ari_events_user_event_cb(
 		} else
 		{}
 	}
-	/* Look for a JSON request entity */
-	body = ast_http_get_json(ser, headers);
-	if (!body) {
-		switch (errno) {
-		case EFBIG:
-			ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-			goto fin;
-		case ENOMEM:
-			ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-			goto fin;
-		case EIO:
-			ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-			goto fin;
-		}
-	}
 	args.variables = body;
 	ast_ari_events_user_event(headers, &args, response);
 #if defined(AST_DEVMODE)
diff --git a/res/res_ari_mailboxes.c b/res/res_ari_mailboxes.c
index 6ed16a84e61e4d7158084fca49aaf1a3093b00bf..8e0648b8ab266872e855b1e4f9122d45b90057a1 100644
--- a/res/res_ari_mailboxes.c
+++ b/res/res_ari_mailboxes.c
@@ -62,10 +62,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 static void ast_ari_mailboxes_list_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_mailboxes_list_args args = {};
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -113,11 +112,10 @@ fin: __attribute__((unused))
 static void ast_ari_mailboxes_get_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_mailboxes_get_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -189,11 +187,10 @@ int ast_ari_mailboxes_update_parse_body(
 static void ast_ari_mailboxes_update_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_mailboxes_update_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -214,21 +211,6 @@ static void ast_ari_mailboxes_update_cb(
 		} else
 		{}
 	}
-	/* Look for a JSON request entity */
-	body = ast_http_get_json(ser, headers);
-	if (!body) {
-		switch (errno) {
-		case EFBIG:
-			ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-			goto fin;
-		case ENOMEM:
-			ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-			goto fin;
-		case EIO:
-			ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-			goto fin;
-		}
-	}
 	if (ast_ari_mailboxes_update_parse_body(body, &args)) {
 		ast_ari_response_alloc_failed(response);
 		goto fin;
@@ -276,11 +258,10 @@ fin: __attribute__((unused))
 static void ast_ari_mailboxes_delete_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_mailboxes_delete_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
diff --git a/res/res_ari_playbacks.c b/res/res_ari_playbacks.c
index 2336033035e866c36fb7cb057511b55d3d8a1e9c..a0ebd66a3817f1d9533331fe9b8eee11499729b0 100644
--- a/res/res_ari_playbacks.c
+++ b/res/res_ari_playbacks.c
@@ -62,11 +62,10 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 static void ast_ari_playbacks_get_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_playbacks_get_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -121,11 +120,10 @@ fin: __attribute__((unused))
 static void ast_ari_playbacks_stop_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_playbacks_stop_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -193,11 +191,10 @@ int ast_ari_playbacks_control_parse_body(
 static void ast_ari_playbacks_control_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_playbacks_control_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -215,21 +212,6 @@ static void ast_ari_playbacks_control_cb(
 		} else
 		{}
 	}
-	/* Look for a JSON request entity */
-	body = ast_http_get_json(ser, headers);
-	if (!body) {
-		switch (errno) {
-		case EFBIG:
-			ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-			goto fin;
-		case ENOMEM:
-			ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-			goto fin;
-		case EIO:
-			ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-			goto fin;
-		}
-	}
 	if (ast_ari_playbacks_control_parse_body(body, &args)) {
 		ast_ari_response_alloc_failed(response);
 		goto fin;
diff --git a/res/res_ari_recordings.c b/res/res_ari_recordings.c
index 04ce0ac9757d25edce21e6046b114bd65c5a9fd7..bdcf676811377f270b988103a17d4150d3b8c98b 100644
--- a/res/res_ari_recordings.c
+++ b/res/res_ari_recordings.c
@@ -62,10 +62,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 static void ast_ari_recordings_list_stored_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_recordings_list_stored_args args = {};
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -113,11 +112,10 @@ fin: __attribute__((unused))
 static void ast_ari_recordings_get_stored_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_recordings_get_stored_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -172,11 +170,10 @@ fin: __attribute__((unused))
 static void ast_ari_recordings_delete_stored_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_recordings_delete_stored_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -244,11 +241,10 @@ int ast_ari_recordings_copy_stored_parse_body(
 static void ast_ari_recordings_copy_stored_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_recordings_copy_stored_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -266,21 +262,6 @@ static void ast_ari_recordings_copy_stored_cb(
 		} else
 		{}
 	}
-	/* Look for a JSON request entity */
-	body = ast_http_get_json(ser, headers);
-	if (!body) {
-		switch (errno) {
-		case EFBIG:
-			ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-			goto fin;
-		case ENOMEM:
-			ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-			goto fin;
-		case EIO:
-			ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-			goto fin;
-		}
-	}
 	if (ast_ari_recordings_copy_stored_parse_body(body, &args)) {
 		ast_ari_response_alloc_failed(response);
 		goto fin;
@@ -329,11 +310,10 @@ fin: __attribute__((unused))
 static void ast_ari_recordings_get_live_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_recordings_get_live_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -388,11 +368,10 @@ fin: __attribute__((unused))
 static void ast_ari_recordings_cancel_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_recordings_cancel_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -447,11 +426,10 @@ fin: __attribute__((unused))
 static void ast_ari_recordings_stop_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_recordings_stop_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -506,11 +484,10 @@ fin: __attribute__((unused))
 static void ast_ari_recordings_pause_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_recordings_pause_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -566,11 +543,10 @@ fin: __attribute__((unused))
 static void ast_ari_recordings_unpause_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_recordings_unpause_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -626,11 +602,10 @@ fin: __attribute__((unused))
 static void ast_ari_recordings_mute_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_recordings_mute_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -686,11 +661,10 @@ fin: __attribute__((unused))
 static void ast_ari_recordings_unmute_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_recordings_unmute_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
diff --git a/res/res_ari_sounds.c b/res/res_ari_sounds.c
index 935025dec2d8783028406313f74677e92ce80f33..48fa204c5287fdd534926c2133740a7b9bbbdc7d 100644
--- a/res/res_ari_sounds.c
+++ b/res/res_ari_sounds.c
@@ -79,11 +79,10 @@ int ast_ari_sounds_list_parse_body(
 static void ast_ari_sounds_list_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_sounds_list_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
@@ -98,21 +97,6 @@ static void ast_ari_sounds_list_cb(
 		} else
 		{}
 	}
-	/* Look for a JSON request entity */
-	body = ast_http_get_json(ser, headers);
-	if (!body) {
-		switch (errno) {
-		case EFBIG:
-			ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-			goto fin;
-		case ENOMEM:
-			ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-			goto fin;
-		case EIO:
-			ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-			goto fin;
-		}
-	}
 	if (ast_ari_sounds_list_parse_body(body, &args)) {
 		ast_ari_response_alloc_failed(response);
 		goto fin;
@@ -159,11 +143,10 @@ fin: __attribute__((unused))
 static void ast_ari_sounds_get_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_sounds_get_args args = {};
 	struct ast_variable *i;
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
diff --git a/res/res_stasis.c b/res/res_stasis.c
index 72b536b52bb819c4e7c9d80a11398e6ddae50a1e..55240bacc10432aeaa5136364e6b546adcc41bd4 100644
--- a/res/res_stasis.c
+++ b/res/res_stasis.c
@@ -67,7 +67,6 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "stasis/app.h"
 #include "stasis/control.h"
 #include "stasis/messaging.h"
-#include "stasis/cli.h"
 #include "stasis/stasis_bridge.h"
 #include "asterisk/core_unreal.h"
 #include "asterisk/musiconhold.h"
@@ -178,11 +177,6 @@ static struct ast_json *stasis_start_to_json(struct stasis_message *message,
 STASIS_MESSAGE_TYPE_DEFN_LOCAL(start_message_type,
 	.to_json = stasis_start_to_json);
 
-const char *stasis_app_name(const struct stasis_app *app)
-{
-	return app_name(app);
-}
-
 /*! AO2 hash function for \ref app */
 static int app_hash(const void *obj, const int flags)
 {
@@ -944,7 +938,7 @@ static int send_start_msg_snapshots(struct ast_channel *chan, struct stasis_app
 
 	if (app_subscribe_channel(app, chan)) {
 		ast_log(LOG_ERROR, "Error subscribing app '%s' to channel '%s'\n",
-			app_name(app), ast_channel_name(chan));
+			stasis_app_name(app), ast_channel_name(chan));
 		return -1;
 	}
 
@@ -958,7 +952,7 @@ static int send_start_msg_snapshots(struct ast_channel *chan, struct stasis_app
 	payload->replace_channel = ao2_bump(replace_channel_snapshot);
 
 	json_blob = ast_json_pack("{s: s, s: o, s: []}",
-		"app", app_name(app),
+		"app", stasis_app_name(app),
 		"timestamp", ast_json_timeval(ast_tvnow(), NULL),
 		"args");
 	if (!json_blob) {
@@ -1028,7 +1022,7 @@ int app_send_end_msg(struct stasis_app *app, struct ast_channel *chan)
 		return 0;
 	}
 
-	blob = ast_json_pack("{s: s}", "app", app_name(app));
+	blob = ast_json_pack("{s: s}", "app", stasis_app_name(app));
 	if (!blob) {
 		ast_log(LOG_ERROR, "Error packing JSON for StasisEnd message\n");
 		return -1;
@@ -1474,10 +1468,6 @@ static struct stasis_app *find_app_by_name(const char *app_name)
 		res = ao2_find(apps_registry, app_name, OBJ_SEARCH_KEY);
 	}
 
-	if (!res) {
-		ast_log(LOG_WARNING, "Could not find app '%s'\n",
-			app_name ? : "(null)");
-	}
 	return res;
 }
 
@@ -1958,8 +1948,6 @@ static int unload_module(void)
 {
 	stasis_app_unregister_event_sources();
 
-	cli_cleanup();
-
 	messaging_cleanup();
 
 	cleanup();
@@ -2117,11 +2105,6 @@ static int load_module(void)
 		return AST_MODULE_LOAD_FAILURE;
 	}
 
-	if (cli_init()) {
-		unload_module();
-		return AST_MODULE_LOAD_FAILURE;
-	}
-
 	bridge_stasis_init();
 
 	stasis_app_register_event_sources();
diff --git a/res/stasis/app.c b/res/stasis/app.c
index 0bef0ee5758ad8ff1fbe7f17e553b8909879f100..e122f34a49d98e80dbe9505cb31cd8c78754bb42 100644
--- a/res/stasis/app.c
+++ b/res/stasis/app.c
@@ -43,6 +43,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #define CHANNEL_ALL "__AST_CHANNEL_ALL_TOPIC"
 #define ENDPOINT_ALL "__AST_ENDPOINT_ALL_TOPIC"
 
+/*! Global debug flag.  No need for locking */
+int global_debug;
+
 static int unsubscribe(struct stasis_app *app, const char *kind, const char *id, int terminate);
 
 struct stasis_app {
@@ -843,15 +846,64 @@ static void bridge_default_handler(void *data, struct stasis_subscription *sub,
 	}
 }
 
-void app_set_debug(struct stasis_app *app, int debug)
+void stasis_app_set_debug(struct stasis_app *app, int debug)
 {
 	if (!app) {
 		return;
 	}
 
-	{
-		SCOPED_AO2LOCK(lock, app);
-		app->debug = debug;
+	app->debug = debug;
+}
+
+void stasis_app_set_debug_by_name(const char *app_name, int debug)
+{
+	struct stasis_app *app = stasis_app_get_by_name(app_name);
+
+	if (!app) {
+		return;
+	}
+
+	app->debug = debug;
+	ao2_cleanup(app);
+}
+
+int stasis_app_get_debug(struct stasis_app *app)
+{
+	return (app ? app->debug : 0) || global_debug;
+}
+
+int stasis_app_get_debug_by_name(const char *app_name)
+{
+	RAII_VAR(struct stasis_app *, app, stasis_app_get_by_name(app_name), ao2_cleanup);
+
+	return (app ? app->debug : 0) || global_debug;
+}
+
+void stasis_app_set_global_debug(int debug)
+{
+	global_debug = debug;
+	if (!global_debug) {
+		struct ao2_container *app_names = stasis_app_get_all();
+		struct ao2_iterator it_app_names;
+		char *app_name;
+		struct stasis_app *app;
+
+		if (!app_names || !ao2_container_count(app_names)) {
+			ao2_cleanup(app_names);
+			return;
+		}
+
+		it_app_names = ao2_iterator_init(app_names, 0);
+		while ((app_name = ao2_iterator_next(&it_app_names))) {
+			if ((app = stasis_app_get_by_name(app_name))) {
+				stasis_app_set_debug(app, 0);
+			}
+
+			ao2_cleanup(app_name);
+			ao2_cleanup(app);
+		}
+		ao2_iterator_cleanup(&it_app_names);
+		ao2_cleanup(app_names);
 	}
 }
 
@@ -952,7 +1004,6 @@ struct stasis_topic *ast_app_get_topic(struct stasis_app *app)
 void app_send(struct stasis_app *app, struct ast_json *message)
 {
 	stasis_app_cb handler;
-	int debug;
 	char eid[20];
 	RAII_VAR(void *, data, NULL, ao2_cleanup);
 
@@ -965,7 +1016,6 @@ void app_send(struct stasis_app *app, struct ast_json *message)
 	/* Copy off mutable state with lock held */
 	{
 		SCOPED_AO2LOCK(lock, app);
-		debug = app->debug;
 		handler = app->handler;
 		if (app->data) {
 			ao2_ref(app->data, +1);
@@ -974,13 +1024,6 @@ void app_send(struct stasis_app *app, struct ast_json *message)
 		/* Name is immutable; no need to copy */
 	}
 
-	if (debug) {
-		char *dump = ast_json_dump_string_format(message, AST_JSON_PRETTY);
-		ast_verb(0, "Dispatching message to Stasis app '%s':\n%s\n",
-			app->name, dump);
-		ast_json_free(dump);
-	}
-
 	if (!handler) {
 		ast_verb(3,
 			"Inactive Stasis app '%s' missed message\n", app->name);
@@ -1053,7 +1096,7 @@ void app_update(struct stasis_app *app, stasis_app_cb handler, void *data)
 	app->data = data;
 }
 
-const char *app_name(const struct stasis_app *app)
+const char *stasis_app_name(const struct stasis_app *app)
 {
 	return app->name;
 }
@@ -1070,7 +1113,7 @@ static int forwards_filter_by_type(void *obj, void *arg, int flags)
 	return 0;
 }
 
-void app_to_cli(const struct stasis_app *app, struct ast_cli_args *a)
+void stasis_app_to_cli(const struct stasis_app *app, struct ast_cli_args *a)
 {
 	struct ao2_iterator *channels;
 	struct ao2_iterator *endpoints;
diff --git a/res/stasis/app.h b/res/stasis/app.h
index 6ed6a295b87d95c27a0a20c5d68e6ae1b2cb670f..ac4ac59fbd6932c4facb8270441dea97ab53f08b 100644
--- a/res/stasis/app.h
+++ b/res/stasis/app.h
@@ -108,15 +108,6 @@ int app_is_finished(struct stasis_app *app);
  */
 void app_update(struct stasis_app *app, stasis_app_cb handler, void *data);
 
-/*!
- * \brief Return an application's name.
- *
- * \param app Application.
- * \return Name of the application.
- * \return \c NULL is \a app is \c NULL.
- */
-const char *app_name(const struct stasis_app *app);
-
 /*!
  * \brief Send a message to an application.
  *
@@ -137,16 +128,6 @@ struct app_forwards;
  */
 struct ast_json *app_to_json(const struct stasis_app *app);
 
-struct ast_cli_args;
-
-/*!
- * \brief Dump properties of a \c stasis_app to the CLI
- *
- * \param app The application
- * \param a The CLI arguments
- */
-void app_to_cli(const struct stasis_app *app, struct ast_cli_args *a);
-
 /*!
  * \brief Subscribes an application to a channel.
  *
@@ -300,12 +281,4 @@ char *app_get_replace_channel_app(struct ast_channel *chan);
  */
 int app_send_end_msg(struct stasis_app *app, struct ast_channel *chan);
 
-/*!
- * \brief Enable/disable debugging on an application
- *
- * \param app The app to debug
- * \param debug If non-zero, enable debugging. If zero, disable.
- */
-void app_set_debug(struct stasis_app *app, int debug);
-
 #endif /* _ASTERISK_RES_STASIS_APP_H */
diff --git a/res/stasis/cli.c b/res/stasis/cli.c
deleted file mode 100644
index f1dee55212116d849a5d502007efdcbb19a39a50..0000000000000000000000000000000000000000
--- a/res/stasis/cli.c
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 2016, Digium, Inc.
- *
- * Matt Jordan <mjordan@digium.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief Stasis CLI commands.
- *
- * \author Matt Jordan <mjordan@digium.com>
- */
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include "asterisk/cli.h"
-#include "asterisk/astobj2.h"
-
-#include "cli.h"
-#include "app.h"
-
-
-static char *ari_show_apps(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
-{
-	struct ao2_container *apps;
-	struct ao2_iterator it_apps;
-	char *app;
-
-	switch (cmd) {
-	case CLI_INIT:
-		e->command = "ari show apps";
-		e->usage =
-			"Usage: ari show apps\n"
-			"       Lists all registered applications.\n"
-			;
-		return NULL;
-	case CLI_GENERATE:
-		return NULL;
-	default:
-		break;
-	}
-
-	if (a->argc != 3) {
-		return CLI_SHOWUSAGE;
-	}
-
-	apps = stasis_app_get_all();
-	if (!apps) {
-		ast_cli(a->fd, "Unable to retrieve registered applications!\n");
-		return CLI_FAILURE;
-	}
-
-	ast_cli(a->fd, "Application Name         \n");
-	ast_cli(a->fd, "=========================\n");
-	it_apps = ao2_iterator_init(apps, 0);
-	while ((app = ao2_iterator_next(&it_apps))) {
-		ast_cli(a->fd, "%-25.25s\n", app);
-		ao2_ref(app, -1);
-	}
-
-	ao2_iterator_destroy(&it_apps);
-	ao2_ref(apps, -1);
-
-	return CLI_SUCCESS;
-}
-
-struct app_complete {
-	/*! Nth app to search for */
-	int state;
-	/*! Which app currently on */
-	int which;
-};
-
-static int complete_ari_app_search(void *obj, void *arg, void *data, int flags)
-{
-	struct app_complete *search = data;
-
-	if (++search->which > search->state) {
-		return CMP_MATCH;
-	}
-	return 0;
-}
-
-static char *complete_ari_app(struct ast_cli_args *a)
-{
-	RAII_VAR(struct ao2_container *, apps, stasis_app_get_all(), ao2_cleanup);
-	RAII_VAR(char *, app, NULL, ao2_cleanup);
-
-	struct app_complete search = {
-		.state = a->n,
-	};
-
-	if (!apps) {
-		ast_cli(a->fd, "Error getting ARI applications\n");
-		return CLI_FAILURE;
-	}
-
-	app = ao2_callback_data(apps,
-		ast_strlen_zero(a->word) ? 0 : OBJ_PARTIAL_KEY,
-		complete_ari_app_search, (char*)a->word, &search);
-
-	return app ? ast_strdup(app) : NULL;
-}
-
-static char *complete_ari_show_app(struct ast_cli_args *a)
-{
-	if (a->pos == 3) {
-		return complete_ari_app(a);
-	}
-
-	return NULL;
-}
-
-static char *ari_show_app(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
-{
-	void *app;
-
-	switch (cmd) {
-	case CLI_INIT:
-		e->command = "ari show app";
-		e->usage =
-			"Usage: ari show app <application>\n"
-			"       Provide detailed information about a registered application.\n"
-			;
-		return NULL;
-	case CLI_GENERATE:
-		return complete_ari_show_app(a);
-	default:
-		break;
-	}
-
-	if (a->argc != 4) {
-		return CLI_SHOWUSAGE;
-	}
-
-	app = stasis_app_get_by_name(a->argv[3]);
-	if (!app) {
-		return CLI_FAILURE;
-	}
-
-	app_to_cli(app, a);
-
-	ao2_ref(app, -1);
-
-	return CLI_SUCCESS;
-}
-
-static char *ari_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
-{
-	void *app;
-	int debug;
-
-	switch (cmd) {
-	case CLI_INIT:
-		e->command = "ari set debug";
-		e->usage =
-			"Usage: ari set debug <application> <on|off>\n"
-			"       Enable or disable debugging on a specific application.\n"
-			;
-		return NULL;
-	case CLI_GENERATE:
-		return complete_ari_show_app(a);
-	default:
-		break;
-	}
-
-	if (a->argc != 5) {
-		return CLI_SHOWUSAGE;
-	}
-
-	app = stasis_app_get_by_name(a->argv[3]);
-	if (!app) {
-		return CLI_FAILURE;
-	}
-
-	debug = !strcmp(a->argv[4], "on");
-	app_set_debug(app, debug);
-	ast_cli(a->fd, "Debugging on '%s' %s\n",
-		app_name(app),
-		debug ? "enabled" : "disabled");
-
-	ao2_ref(app, -1);
-
-	return CLI_SUCCESS;
-}
-
-static struct ast_cli_entry cli_ari[] = {
-	AST_CLI_DEFINE(ari_show_apps, "List registered ARI applications"),
-	AST_CLI_DEFINE(ari_show_app, "Display details of a registered ARI application"),
-	AST_CLI_DEFINE(ari_set_debug, "Enable/disable debugging of an ARI application"),
-};
-
-
-int cli_init(void)
-{
-	return ast_cli_register_multiple(cli_ari, ARRAY_LEN(cli_ari));
-}
-
-void cli_cleanup(void)
-{
-	ast_cli_unregister_multiple(cli_ari, ARRAY_LEN(cli_ari));
-}
diff --git a/res/stasis/cli.h b/res/stasis/cli.h
deleted file mode 100644
index 49235c7b30972ad266475ecb7bc91042f8b9237d..0000000000000000000000000000000000000000
--- a/res/stasis/cli.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 2016, Digium, Inc.
- *
- * Matt Jordan <mjordan@digium.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-#ifndef _ASTERISK_RES_STASIS_CLI_H
-#define _ASTERISK_RES_STASIS_CLI_H
-
-/*! \file
- *
- * \brief Internal API for Stasis application CLI commands
- *
- * \author Matt Jordan <mjordan@digium.com>
- * \since 13.13.0
- */
-
-/*!
- * \brief Initialize the CLI commands
- *
- * \retval 0 on success
- * \retval non-zero on error
- */
-int cli_init(void);
-
-/*!
- * \brief Cleanup the CLI commands
- */
-void cli_cleanup(void);
-
-#endif /* _ASTERISK_RES_STASIS_CLI_H */
diff --git a/res/stasis/stasis_bridge.c b/res/stasis/stasis_bridge.c
index 9ffc2d7be2d83912138623245e41b1d3ddf880ea..06404cdc52d491941d97f2b2c3de8a4f58913ed2 100644
--- a/res/stasis/stasis_bridge.c
+++ b/res/stasis/stasis_bridge.c
@@ -157,13 +157,13 @@ static int bridge_stasis_push_peek(struct ast_bridge *self, struct ast_bridge_ch
 	}
 	to_be_replaced = ast_channel_snapshot_get_latest(ast_channel_uniqueid(swap->chan));
 
-	ast_debug(3, "Copying stasis app name %s from %s to %s\n", app_name(control_app(swap_control)),
+	ast_debug(3, "Copying stasis app name %s from %s to %s\n", stasis_app_name(control_app(swap_control)),
 		ast_channel_name(swap->chan), ast_channel_name(bridge_channel->chan));
 
 	ast_channel_lock(bridge_channel->chan);
 
 	/* copy the app name from the swap channel */
-	app_set_replace_channel_app(bridge_channel->chan, app_name(control_app(swap_control)));
+	app_set_replace_channel_app(bridge_channel->chan, stasis_app_name(control_app(swap_control)));
 
 	/* set the replace channel snapshot */
 	app_set_replace_channel_snapshot(bridge_channel->chan, to_be_replaced);
diff --git a/rest-api-templates/param_parsing.mustache b/rest-api-templates/param_parsing.mustache
index 247c121d9c94cf1ff192a124af9134b95145f239..d156ab79941e8f73ee140b3dfe1acec193d12839 100644
--- a/rest-api-templates/param_parsing.mustache
+++ b/rest-api-templates/param_parsing.mustache
@@ -85,21 +85,6 @@
 {{/has_path_parameters}}
 {{^is_websocket}}
 {{#parse_body}}
-	/* Look for a JSON request entity */
-	body = ast_http_get_json(ser, headers);
-	if (!body) {
-		switch (errno) {
-		case EFBIG:
-			ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
-			goto fin;
-		case ENOMEM:
-			ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
-			goto fin;
-		case EIO:
-			ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
-			goto fin;
-		}
-	}
 {{#body_parameter}}
 	args.{{c_name}} = body;
 {{/body_parameter}}
diff --git a/rest-api-templates/res_ari_resource.c.mustache b/rest-api-templates/res_ari_resource.c.mustache
index 08f6204be2af65925608b04eb25842eaeb5010b1..a59f63df5c7df958410ffab9e8077691cdd20335 100644
--- a/rest-api-templates/res_ari_resource.c.mustache
+++ b/rest-api-templates/res_ari_resource.c.mustache
@@ -78,13 +78,12 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 static void ast_ari_{{c_name}}_{{c_nickname}}_cb(
 	struct ast_tcptls_session_instance *ser,
 	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
+	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 {
 	struct ast_ari_{{c_name}}_{{c_nickname}}_args args = {};
 {{#has_parameters}}
 	struct ast_variable *i;
 {{/has_parameters}}
-	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
 #if defined(AST_DEVMODE)
 	int is_valid;
 	int code;
diff --git a/tests/test_ari.c b/tests/test_ari.c
index a61a1182d7063ec30387669d39063b0980e911c4..e2c36fb3841ed39d543a723ca48599ab7ec2aebc 100644
--- a/tests/test_ari.c
+++ b/tests/test_ari.c
@@ -62,6 +62,7 @@ static void handler(const char *name,
 		    struct ast_variable *get_params,
 		    struct ast_variable *path_vars,
 		    struct ast_variable *headers,
+		    struct ast_json *body,
 		    struct ast_ari_response *response)
 {
 	struct ast_json *message = ast_json_pack("{s: s, s: {}, s: {}, s: {}}",
@@ -99,9 +100,10 @@ static void handler(const char *name,
 		struct ast_variable *get_params,			\
 		struct ast_variable *path_vars,				\
 		struct ast_variable *headers,				\
+		struct ast_json *body,						\
 		struct ast_ari_response *response)			\
 	{								\
-		handler(#name, response_code, get_params, path_vars, headers, response); \
+		handler(#name, response_code, get_params, path_vars, headers, body, response); \
 	}
 
 HANDLER(bang_get, 200)
@@ -344,7 +346,8 @@ AST_TEST_DEFINE(invoke_get)
 				 "head2", "head-two",
 				 "path_vars");
 
-	ast_ari_invoke(NULL, "foo", AST_HTTP_GET, get_params, headers, response);
+	ast_ari_invoke(NULL, "foo", AST_HTTP_GET, get_params, headers,
+		ast_json_null(), response);
 
 	ast_test_validate(test, 1 == invocation_count);
 	ast_test_validate(test, 200 == response->response_code);
@@ -381,7 +384,8 @@ AST_TEST_DEFINE(invoke_wildcard)
 				 "path_vars",
 				 "bam", "foshizzle");
 
-	ast_ari_invoke(NULL, "foo/foshizzle", AST_HTTP_GET, get_params, headers, response);
+	ast_ari_invoke(NULL, "foo/foshizzle", AST_HTTP_GET, get_params, headers,
+		ast_json_null(), response);
 
 	ast_test_validate(test, 1 == invocation_count);
 	ast_test_validate(test, 200 == response->response_code);
@@ -418,7 +422,8 @@ AST_TEST_DEFINE(invoke_delete)
 				 "path_vars",
 				 "bam", "foshizzle");
 
-	ast_ari_invoke(NULL, "foo/foshizzle/bang", AST_HTTP_DELETE, get_params, headers, response);
+	ast_ari_invoke(NULL, "foo/foshizzle/bang", AST_HTTP_DELETE, get_params, headers,
+		ast_json_null(), response);
 
 	ast_test_validate(test, 1 == invocation_count);
 	ast_test_validate(test, 204 == response->response_code);
@@ -468,7 +473,8 @@ AST_TEST_DEFINE(invoke_post)
 				 "head2", "head-two",
 				 "path_vars");
 
-	ast_ari_invoke(NULL, "foo/bar", AST_HTTP_POST, get_params, headers, response);
+	ast_ari_invoke(NULL, "foo/bar", AST_HTTP_POST, get_params, headers,
+		ast_json_null(), response);
 
 	ast_test_validate(test, 1 == invocation_count);
 	ast_test_validate(test, 200 == response->response_code);
@@ -497,7 +503,8 @@ AST_TEST_DEFINE(invoke_bad_post)
 
 	fixture = setup_invocation_test();
 	response = response_alloc();
-	ast_ari_invoke(NULL, "foo", AST_HTTP_POST, get_params, headers, response);
+	ast_ari_invoke(NULL, "foo", AST_HTTP_POST, get_params, headers,
+		ast_json_null(), response);
 
 	ast_test_validate(test, 0 == invocation_count);
 	ast_test_validate(test, 405 == response->response_code);
@@ -525,7 +532,8 @@ AST_TEST_DEFINE(invoke_not_found)
 
 	fixture = setup_invocation_test();
 	response = response_alloc();
-	ast_ari_invoke(NULL, "foo/fizzle/i-am-not-a-resource", AST_HTTP_GET, get_params, headers, response);
+	ast_ari_invoke(NULL, "foo/fizzle/i-am-not-a-resource", AST_HTTP_GET, get_params, headers,
+		ast_json_null(), response);
 
 	ast_test_validate(test, 0 == invocation_count);
 	ast_test_validate(test, 404 == response->response_code);