diff --git a/CHANGES b/CHANGES
index ae368f10792d1aafa21c4ea9c9cddfc08177ceaf..aa2c8857f66bd4864224d4e9e396e979b159550a 100644
--- a/CHANGES
+++ b/CHANGES
@@ -7,6 +7,17 @@
 === and the other UPGRADE files for older releases.
 ===
 ==============================================================================
+------------------------------------------------------------------------------
+--- Functionality changes from Asterisk 13.1.0 to Asterisk 13.2.0 ------------
+------------------------------------------------------------------------------
+
+ARI
+------------------
+ * The Originate operation now takes in an originator channel. The linked ID of
+   this originator channel is applied to the newly originated outgoing channel.
+   If using CEL this allows an association to be established between the two so
+   it can be recognized that the originator is dialing the originated channel.
+
 ------------------------------------------------------------------------------
 --- Functionality changes from Asterisk 13.0.0 to Asterisk 13.1.0 ------------
 ------------------------------------------------------------------------------
diff --git a/res/ari/resource_channels.c b/res/ari/resource_channels.c
index 112607db6b6ae1da0d7a321a46f91c55e337e4a9..e3ef9eb16e065fc3aa9d15f984d0d650e9463b09 100644
--- a/res/ari/resource_channels.c
+++ b/res/ari/resource_channels.c
@@ -44,6 +44,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/causes.h"
 #include "asterisk/format_cache.h"
 #include "asterisk/core_local.h"
+#include "asterisk/dial.h"
 #include "resource_channels.h"
 
 #include <limits.h>
@@ -723,6 +724,69 @@ void ast_ari_channels_list(struct ast_variable *headers,
 	ast_ari_response_ok(response, ast_json_ref(json));
 }
 
+/*! \brief Structure used for origination */
+struct ari_origination {
+	/*! \brief Dialplan context */
+	char context[AST_MAX_CONTEXT];
+	/*! \brief Dialplan extension */
+	char exten[AST_MAX_EXTENSION];
+	/*! \brief Dialplan priority */
+	int priority;
+	/*! \brief Application data to pass to Stasis application */
+	char appdata[0];
+};
+
+/*! \brief Thread which dials and executes upon answer */
+static void *ari_originate_dial(void *data)
+{
+	struct ast_dial *dial = data;
+	struct ari_origination *origination = ast_dial_get_user_data(dial);
+	enum ast_dial_result res;
+
+	res = ast_dial_run(dial, NULL, 0);
+	if (res != AST_DIAL_RESULT_ANSWERED) {
+		goto end;
+	}
+
+	if (!ast_strlen_zero(origination->appdata)) {
+		struct ast_app *app = pbx_findapp("Stasis");
+
+		if (app) {
+			ast_verb(4, "Launching Stasis(%s) on %s\n", origination->appdata,
+				ast_channel_name(ast_dial_answered(dial)));
+			pbx_exec(ast_dial_answered(dial), app, origination->appdata);
+		} else {
+			ast_log(LOG_WARNING, "No such application 'Stasis'\n");
+		}
+	} else {
+		struct ast_channel *answered = ast_dial_answered(dial);
+
+		if (!ast_strlen_zero(origination->context)) {
+			ast_channel_context_set(answered, origination->context);
+		}
+
+		if (!ast_strlen_zero(origination->exten)) {
+			ast_channel_exten_set(answered, origination->exten);
+		}
+
+		if (origination->priority > 0) {
+			ast_channel_priority_set(answered, origination->priority);
+		}
+
+		if (ast_pbx_run(answered)) {
+			ast_log(LOG_ERROR, "Failed to start PBX on %s\n", ast_channel_name(answered));
+		} else {
+			/* PBX will have taken care of hanging up, so we steal the answered channel so dial doesn't do it */
+			ast_dial_answered_steal(dial);
+		}
+	}
+
+end:
+	ast_dial_destroy(dial);
+	ast_free(origination);
+	return NULL;
+}
+
 static void ari_channels_handle_originate_with_id(const char *args_endpoint,
 	const char *args_extension,
 	const char *args_context,
@@ -734,23 +798,27 @@ static void ari_channels_handle_originate_with_id(const char *args_endpoint,
 	struct ast_variable *variables,
 	const char *args_channel_id,
 	const char *args_other_channel_id,
+	const char *args_originator,
 	struct ast_ari_response *response)
 {
 	char *dialtech;
 	char dialdevice[AST_CHANNEL_NAME];
+	struct ast_dial *dial;
 	char *caller_id = NULL;
 	char *cid_num = NULL;
 	char *cid_name = NULL;
-	int timeout = 30000;
 	RAII_VAR(struct ast_format_cap *, cap,
 		ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT), ao2_cleanup);
 	char *stuff;
+	struct ast_channel *other = NULL;
 	struct ast_channel *chan;
 	RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
 	struct ast_assigned_ids assignedids = {
 		.uniqueid = args_channel_id,
 		.uniqueid2 = args_other_channel_id,
 	};
+	struct ari_origination *origination;
+	pthread_t thread;
 
 	if (!cap) {
 		ast_ari_response_alloc_failed(response);
@@ -783,24 +851,7 @@ static void ari_channels_handle_originate_with_id(const char *args_endpoint,
 		return;
 	}
 
-	if (args_timeout > 0) {
-		timeout = args_timeout * 1000;
-	} else if (args_timeout == -1) {
-		timeout = -1;
-	}
-
-	if (!ast_strlen_zero(args_caller_id)) {
-		caller_id = ast_strdupa(args_caller_id);
-		ast_callerid_parse(caller_id, &cid_name, &cid_num);
-
-		if (ast_is_shrinkable_phonenumber(cid_num)) {
-			ast_shrink_phone_number(cid_num);
-		}
-	}
-
 	if (!ast_strlen_zero(args_app)) {
-		const char *app = "Stasis";
-
 		RAII_VAR(struct ast_str *, appdata, ast_str_create(64), ast_free);
 
 		if (!appdata) {
@@ -813,23 +864,125 @@ static void ari_channels_handle_originate_with_id(const char *args_endpoint,
 			ast_str_append(&appdata, 0, ",%s", args_app_args);
 		}
 
-		/* originate a channel, putting it into an application */
-		if (ast_pbx_outgoing_app(dialtech, cap, dialdevice, timeout, app, ast_str_buffer(appdata), NULL, 0, cid_num, cid_name, variables, NULL, &chan, &assignedids)) {
+		origination = ast_calloc(1, sizeof(*origination) + ast_str_size(appdata) + 1);
+		if (!origination) {
 			ast_ari_response_alloc_failed(response);
 			return;
 		}
+
+		strcpy(origination->appdata, ast_str_buffer(appdata));
 	} else if (!ast_strlen_zero(args_extension)) {
-		/* originate a channel, sending it to an extension */
-		if (ast_pbx_outgoing_exten(dialtech, cap, dialdevice, timeout, S_OR(args_context, "default"), args_extension, args_priority ? args_priority : 1, NULL, 0, cid_num, cid_name, variables, NULL, &chan, 0, &assignedids)) {
+		origination = ast_calloc(1, sizeof(*origination) + 1);
+		if (!origination) {
 			ast_ari_response_alloc_failed(response);
 			return;
 		}
+
+		ast_copy_string(origination->context, S_OR(args_context, "default"), sizeof(origination->context));
+		ast_copy_string(origination->exten, args_extension, sizeof(origination->exten));
+		origination->priority = args_priority ? args_priority : 1;
+		origination->appdata[0] = '\0';
 	} else {
 		ast_ari_response_error(response, 400, "Bad Request",
 			"Application or extension must be specified");
 		return;
 	}
 
+	dial = ast_dial_create();
+	if (!dial) {
+		ast_ari_response_alloc_failed(response);
+		ast_free(origination);
+		return;
+	}
+	ast_dial_set_user_data(dial, origination);
+
+	if (ast_dial_append(dial, dialtech, dialdevice, &assignedids)) {
+		ast_ari_response_alloc_failed(response);
+		ast_dial_destroy(dial);
+		ast_free(origination);
+		return;
+	}
+
+	if (args_timeout > 0) {
+		ast_dial_set_global_timeout(dial, args_timeout * 1000);
+	} else if (args_timeout == -1) {
+		ast_dial_set_global_timeout(dial, -1);
+	} else {
+		ast_dial_set_global_timeout(dial, 30000);
+	}
+
+	if (!ast_strlen_zero(args_caller_id)) {
+		caller_id = ast_strdupa(args_caller_id);
+		ast_callerid_parse(caller_id, &cid_name, &cid_num);
+
+		if (ast_is_shrinkable_phonenumber(cid_num)) {
+			ast_shrink_phone_number(cid_num);
+		}
+	}
+
+	if (!ast_strlen_zero(args_originator)) {
+		other = ast_channel_get_by_name(args_originator);
+		if (!other) {
+			ast_ari_response_error(
+				response, 400, "Bad Request",
+				"Provided originator channel was not found");
+			ast_dial_destroy(dial);
+			ast_free(origination);
+			return;
+		}
+	}
+
+	if (ast_dial_prerun(dial, other, cap)) {
+		ast_ari_response_alloc_failed(response);
+		ast_dial_destroy(dial);
+		ast_free(origination);
+		ast_channel_cleanup(other);
+		return;
+	}
+
+	ast_channel_cleanup(other);
+
+	chan = ast_dial_get_channel(dial, 0);
+	if (!chan) {
+		ast_ari_response_alloc_failed(response);
+		ast_dial_destroy(dial);
+		ast_free(origination);
+		return;
+	}
+
+	if (!ast_strlen_zero(cid_num) || !ast_strlen_zero(cid_name)) {
+		struct ast_party_connected_line connected;
+
+		/*
+		 * It seems strange to set the CallerID on an outgoing call leg
+		 * to whom we are calling, but this function's callers are doing
+		 * various Originate methods.  This call leg goes to the local
+		 * user.  Once the called party answers, the dialplan needs to
+		 * be able to access the CallerID from the CALLERID function as
+		 * if the called party had placed this call.
+		 */
+		ast_set_callerid(chan, cid_num, cid_name, cid_num);
+
+		ast_party_connected_line_set_init(&connected, ast_channel_connected(chan));
+		if (!ast_strlen_zero(cid_num)) {
+			connected.id.number.valid = 1;
+			connected.id.number.str = (char *) cid_num;
+			connected.id.number.presentation = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
+		}
+		if (!ast_strlen_zero(cid_name)) {
+			connected.id.name.valid = 1;
+			connected.id.name.str = (char *) cid_name;
+			connected.id.name.presentation = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
+		}
+		ast_channel_set_connected_line(chan, &connected, NULL);
+	}
+
+	ast_channel_lock(chan);
+	if (variables) {
+		ast_set_variables(chan, variables);
+	}
+	ast_set_flag(ast_channel_flags(chan), AST_FLAG_ORIGINATED);
+
 	if (!ast_strlen_zero(args_app)) {
 		struct ast_channel *local_peer;
 
@@ -846,8 +999,21 @@ static void ari_channels_handle_originate_with_id(const char *args_endpoint,
 	snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(chan));
 	ast_channel_unlock(chan);
 
-	ast_ari_response_ok(response, ast_channel_snapshot_to_json(snapshot, NULL));
+	/* Before starting the async dial bump the ref in case the dial quickly goes away and takes
+	 * the reference with it
+	 */
+	ast_channel_ref(chan);
+
+	if (ast_pthread_create_detached(&thread, NULL, ari_originate_dial, dial)) {
+		ast_ari_response_alloc_failed(response);
+		ast_dial_destroy(dial);
+		ast_free(origination);
+	} else {
+		ast_ari_response_ok(response, ast_channel_snapshot_to_json(snapshot, NULL));
+	}
+
 	ast_channel_unref(chan);
+	return;
 }
 
 void ast_ari_channels_originate_with_id(struct ast_variable *headers,
@@ -883,6 +1049,7 @@ void ast_ari_channels_originate_with_id(struct ast_variable *headers,
 		variables,
 		args->channel_id,
 		args->other_channel_id,
+		args->originator,
 		response);
 }
 
@@ -919,6 +1086,7 @@ void ast_ari_channels_originate(struct ast_variable *headers,
 		variables,
 		args->channel_id,
 		args->other_channel_id,
+		args->originator,
 		response);
 }
 
diff --git a/res/ari/resource_channels.h b/res/ari/resource_channels.h
index 104e1bdb371742ba8ad70952fcdde4d799ffcb10..627f9c97aea1a216105d9cb52ec267cda51283f7 100644
--- a/res/ari/resource_channels.h
+++ b/res/ari/resource_channels.h
@@ -74,6 +74,8 @@ struct ast_ari_channels_originate_args {
 	const char *channel_id;
 	/*! The unique id to assign the second channel when using local channels. */
 	const char *other_channel_id;
+	/*! The unique id of the channel which is originating this one. */
+	const char *originator;
 };
 /*!
  * \brief Body parsing function for /channels.
@@ -133,6 +135,8 @@ struct ast_ari_channels_originate_with_id_args {
 	struct ast_json *variables;
 	/*! The unique id to assign the second channel when using local channels. */
 	const char *other_channel_id;
+	/*! The unique id of the channel which is originating this one. */
+	const char *originator;
 };
 /*!
  * \brief Body parsing function for /channels/{channelId}.
diff --git a/res/res_ari_channels.c b/res/res_ari_channels.c
index 08edc64dc925ae29a14c024bcbe686f604e8de27..8cc25f1d87bcba4b3c2d17eb02945c1350e4a2ac 100644
--- a/res/res_ari_channels.c
+++ b/res/res_ari_channels.c
@@ -148,6 +148,10 @@ int ast_ari_channels_originate_parse_body(
 	if (field) {
 		args->other_channel_id = ast_json_string_get(field);
 	}
+	field = ast_json_object_get(body, "originator");
+	if (field) {
+		args->originator = ast_json_string_get(field);
+	}
 	return 0;
 }
 
@@ -202,6 +206,9 @@ static void ast_ari_channels_originate_cb(
 		if (strcmp(i->name, "otherChannelId") == 0) {
 			args.other_channel_id = (i->value);
 		} else
+		if (strcmp(i->name, "originator") == 0) {
+			args.originator = (i->value);
+		} else
 		{}
 	}
 	/* Look for a JSON request entity */
@@ -354,6 +361,10 @@ int ast_ari_channels_originate_with_id_parse_body(
 	if (field) {
 		args->other_channel_id = ast_json_string_get(field);
 	}
+	field = ast_json_object_get(body, "originator");
+	if (field) {
+		args->originator = ast_json_string_get(field);
+	}
 	return 0;
 }
 
@@ -405,6 +416,9 @@ static void ast_ari_channels_originate_with_id_cb(
 		if (strcmp(i->name, "otherChannelId") == 0) {
 			args.other_channel_id = (i->value);
 		} else
+		if (strcmp(i->name, "originator") == 0) {
+			args.originator = (i->value);
+		} else
 		{}
 	}
 	for (i = path_vars; i; i = i->next) {
diff --git a/rest-api/api-docs/channels.json b/rest-api/api-docs/channels.json
index 67634740ae0445ae9a0d4335c053be04732560cb..f9c8d8647a114e9ab14fdc12a25c4b4cc1b4f15c 100644
--- a/rest-api/api-docs/channels.json
+++ b/rest-api/api-docs/channels.json
@@ -112,6 +112,14 @@
 							"required": false,
 							"allowMultiple": false,
 							"dataType": "string"
+						},
+						{
+							"name": "originator",
+							"description": "The unique id of the channel which is originating this one.",
+							"paramType": "query",
+							"required": false,
+							"allowMultiple": false,
+							"dataType": "string"
 						}
 					],
 					"errorResponses": [
@@ -244,6 +252,14 @@
 							"required": false,
 							"allowMultiple": false,
 							"dataType": "string"
+						},
+						{
+							"name": "originator",
+							"description": "The unique id of the channel which is originating this one.",
+							"paramType": "query",
+							"required": false,
+							"allowMultiple": false,
+							"dataType": "string"
 						}
 					],
 					"errorResponses": [