diff --git a/channels/chan_pjsip.c b/channels/chan_pjsip.c
index 7680aec54ccaf52e5fa8dac1e805346d659706fc..342eabb21fa315aa2731ed76636f0010c111bea6 100644
--- a/channels/chan_pjsip.c
+++ b/channels/chan_pjsip.c
@@ -145,6 +145,8 @@ static struct ast_sip_session_supplement chan_pjsip_supplement = {
 	.session_end = chan_pjsip_session_end,
 	.incoming_request = chan_pjsip_incoming_request,
 	.incoming_response = chan_pjsip_incoming_response,
+	/* It is important that this supplement runs after media has been negotiated */
+	.response_priority = AST_SIP_SESSION_AFTER_MEDIA,
 };
 
 static int chan_pjsip_incoming_ack(struct ast_sip_session *session, struct pjsip_rx_data *rdata);
@@ -2029,6 +2031,11 @@ static int call_pickup_incoming_request(struct ast_sip_session *session, pjsip_r
 	struct ast_features_pickup_config *pickup_cfg = ast_get_chan_features_pickup_config(session->channel);
 	struct ast_channel *chan;
 
+	/* We don't care about reinvites */
+	if (session->inv_session->state >= PJSIP_INV_STATE_CONFIRMED) {
+		return 0;
+	}
+
 	if (!pickup_cfg) {
 		ast_log(LOG_ERROR, "Unable to retrieve pickup configuration options. Unable to detect call pickup extension.\n");
 		return 0;
@@ -2071,6 +2078,11 @@ static int pbx_start_incoming_request(struct ast_sip_session *session, pjsip_rx_
 {
 	int res;
 
+	/* We don't care about reinvites */
+	if (session->inv_session->state >= PJSIP_INV_STATE_CONFIRMED) {
+		return 0;
+	}
+
 	res = ast_pbx_start(session->channel);
 
 	switch (res) {
diff --git a/include/asterisk/res_pjsip_session.h b/include/asterisk/res_pjsip_session.h
index 51908f99b880ffbd2447623e7ed6ab1f19706b49..010a74dc0e58a662d3eac0915e2ca4fd732a9887 100644
--- a/include/asterisk/res_pjsip_session.h
+++ b/include/asterisk/res_pjsip_session.h
@@ -140,6 +140,36 @@ typedef int (*ast_sip_session_request_creation_cb)(struct ast_sip_session *sessi
 typedef int (*ast_sip_session_response_cb)(struct ast_sip_session *session, pjsip_rx_data *rdata);
 typedef int (*ast_sip_session_sdp_creation_cb)(struct ast_sip_session *session, pjmedia_sdp_session *sdp);
 
+/*!
+ * \brief Describes when a supplement should be called into on incoming responses.
+ *
+ * In most cases, session supplements will not need to worry about this because in most cases,
+ * the correct value will be automatically applied. However, there are rare circumstances
+ * when a supplement will want to specify when it should be called.
+ *
+ * The values below are listed in chronological order.
+ */
+enum ast_sip_session_response_priority {
+	/*!
+	 * When processing 3XX responses, the supplement is called into before
+	 * the redirecting information is processed.
+	 */
+	AST_SIP_SESSION_BEFORE_REDIRECTING = (1 << 0),
+	/*!
+	 * For responses to INVITE transactions, the supplement is called into
+	 * before media is negotiated.
+	 *
+	 * This priority is applied by default to any session supplement that
+	 * does not specify a response priority.
+	 */
+	AST_SIP_SESSION_BEFORE_MEDIA = (1 << 1),
+	/*!
+	 * For INVITE transactions, the supplement is called into after media
+	 * is negotiated.
+	 */
+	AST_SIP_SESSION_AFTER_MEDIA = (1 << 2),
+};
+
 /*!
  * \brief A supplement to SIP message processing
  *
@@ -214,6 +244,11 @@ struct ast_sip_session_supplement {
 	void (*outgoing_response)(struct ast_sip_session *session, struct pjsip_tx_data *tdata);
 	/*! Next item in the list */
 	AST_LIST_ENTRY(ast_sip_session_supplement) next;
+	/*!
+	 * Determines when the supplement is processed when handling a response.
+	 * Defaults to AST_SIP_SESSION_BEFORE_MEDIA
+	 */
+	enum ast_sip_session_response_priority response_priority;
 };
 
 enum ast_sip_session_sdp_stream_defer {
diff --git a/res/res_pjsip_diversion.c b/res/res_pjsip_diversion.c
index a27b0757182cdf5f07feb9cfce1485aaac0f1f7a..f8aca35f6d7544a67b277a1c9b2fa5df6777e473 100644
--- a/res/res_pjsip_diversion.c
+++ b/res/res_pjsip_diversion.c
@@ -325,6 +325,7 @@ static struct ast_sip_session_supplement diversion_supplement = {
 	.incoming_response = diversion_incoming_response,
 	.outgoing_request = diversion_outgoing_request,
 	.outgoing_response = diversion_outgoing_response,
+	.response_priority = AST_SIP_SESSION_BEFORE_REDIRECTING,
 };
 
 static int load_module(void)
diff --git a/res/res_pjsip_session.c b/res/res_pjsip_session.c
index c26693f18df65c2dc24bf9de8ad984d530b65f8d..83be0cd2b6d2907d68969371f87c1bfa11e4bd76 100644
--- a/res/res_pjsip_session.c
+++ b/res/res_pjsip_session.c
@@ -53,8 +53,10 @@
 
 /* Some forward declarations */
 static void handle_incoming_request(struct ast_sip_session *session, pjsip_rx_data *rdata, pjsip_event_id_e type);
-static void handle_incoming_response(struct ast_sip_session *session, pjsip_rx_data *rdata, pjsip_event_id_e type);
-static int handle_incoming(struct ast_sip_session *session, pjsip_rx_data *rdata, pjsip_event_id_e type);
+static void handle_incoming_response(struct ast_sip_session *session, pjsip_rx_data *rdata, pjsip_event_id_e type,
+		enum ast_sip_session_response_priority response_priority);
+static int handle_incoming(struct ast_sip_session *session, pjsip_rx_data *rdata, pjsip_event_id_e type,
+		enum ast_sip_session_response_priority response_priority);
 static void handle_outgoing_request(struct ast_sip_session *session, pjsip_tx_data *tdata);
 static void handle_outgoing_response(struct ast_sip_session *session, pjsip_tx_data *tdata);
 static void handle_outgoing(struct ast_sip_session *session, pjsip_tx_data *tdata);
@@ -483,6 +485,10 @@ int ast_sip_session_register_supplement(struct ast_sip_session_supplement *suppl
 	int inserted = 0;
 	SCOPED_LOCK(lock, &session_supplements, AST_RWLIST_WRLOCK, AST_RWLIST_UNLOCK);
 
+	if (!supplement->response_priority) {
+		supplement->response_priority = AST_SIP_SESSION_BEFORE_MEDIA;
+	}
+
 	AST_RWLIST_TRAVERSE_SAFE_BEGIN(&session_supplements, iter, next) {
 		if (iter->priority > supplement->priority) {
 			AST_RWLIST_INSERT_BEFORE_CURRENT(supplement, next);
@@ -1795,27 +1801,27 @@ static void handle_incoming_request(struct ast_sip_session *session, pjsip_rx_da
 	}
 }
 
-static void handle_incoming_response(struct ast_sip_session *session, pjsip_rx_data *rdata, pjsip_event_id_e type)
+static void handle_incoming_response(struct ast_sip_session *session, pjsip_rx_data *rdata, pjsip_event_id_e type,
+		enum ast_sip_session_response_priority response_priority)
 {
 	struct ast_sip_session_supplement *supplement;
 	struct pjsip_status_line status = rdata->msg_info.msg->line.status;
 
-	/* Squash all redirect transaction related responses as the supplements have already been invoked */
-	if (type == PJSIP_EVENT_TSX_STATE && PJSIP_IS_STATUS_IN_CLASS(status.code, 300)) {
-		return;
-	}
-
 	ast_debug(3, "Response is %d %.*s\n", status.code, (int) pj_strlen(&status.reason),
 			pj_strbuf(&status.reason));
 
 	AST_LIST_TRAVERSE(&session->supplements, supplement, next) {
+		if (!(supplement->response_priority & response_priority)) {
+			continue;
+		}
 		if (supplement->incoming_response && does_method_match(&rdata->msg_info.cseq->method.name, supplement->method)) {
 			supplement->incoming_response(session, rdata);
 		}
 	}
 }
 
-static int handle_incoming(struct ast_sip_session *session, pjsip_rx_data *rdata, pjsip_event_id_e type)
+static int handle_incoming(struct ast_sip_session *session, pjsip_rx_data *rdata, pjsip_event_id_e type,
+		enum ast_sip_session_response_priority response_priority)
 {
 	ast_debug(3, "Received %s\n", rdata->msg_info.msg->type == PJSIP_REQUEST_MSG ?
 			"request" : "response");
@@ -1823,7 +1829,7 @@ static int handle_incoming(struct ast_sip_session *session, pjsip_rx_data *rdata
 	if (rdata->msg_info.msg->type == PJSIP_REQUEST_MSG) {
 		handle_incoming_request(session, rdata, type);
 	} else {
-		handle_incoming_response(session, rdata, type);
+		handle_incoming_response(session, rdata, type, response_priority);
 	}
 
 	return 0;
@@ -1913,7 +1919,8 @@ static void session_inv_on_state_changed(pjsip_inv_session *inv, pjsip_event *e)
 		handle_outgoing(session, e->body.tx_msg.tdata);
 		break;
 	case PJSIP_EVENT_RX_MSG:
-		handle_incoming(session, e->body.rx_msg.rdata, type);
+		handle_incoming(session, e->body.rx_msg.rdata, type,
+				AST_SIP_SESSION_BEFORE_MEDIA);
 		break;
 	case PJSIP_EVENT_TSX_STATE:
 		ast_debug(3, "Source of transaction state change is %s\n", pjsip_event_str(e->body.tsx_state.type));
@@ -1923,7 +1930,8 @@ static void session_inv_on_state_changed(pjsip_inv_session *inv, pjsip_event *e)
 			handle_outgoing(session, e->body.tsx_state.src.tdata);
 			break;
 		case PJSIP_EVENT_RX_MSG:
-			handle_incoming(session, e->body.tsx_state.src.rdata, type);
+			handle_incoming(session, e->body.tsx_state.src.rdata, type,
+					AST_SIP_SESSION_BEFORE_MEDIA);
 			break;
 		case PJSIP_EVENT_TRANSPORT_ERROR:
 		case PJSIP_EVENT_TIMER:
@@ -1965,6 +1973,7 @@ static void session_inv_on_tsx_state_changed(pjsip_inv_session *inv, pjsip_trans
 	}
 	switch (e->body.tsx_state.type) {
 	case PJSIP_EVENT_TX_MSG:
+		handle_outgoing(session, e->body.tsx_state.src.tdata);
 		/* When we create an outgoing request, we do not have access to the transaction that
 		 * is created. Instead, We have to place transaction-specific data in the tdata. Here,
 		 * we transfer the data into the transaction. This way, when we receive a response, we
@@ -1973,6 +1982,8 @@ static void session_inv_on_tsx_state_changed(pjsip_inv_session *inv, pjsip_trans
 		tsx->mod_data[session_module.id] = e->body.tsx_state.src.tdata->mod_data[session_module.id];
 		break;
 	case PJSIP_EVENT_RX_MSG:
+		handle_incoming(session, e->body.tsx_state.src.rdata, e->type,
+				AST_SIP_SESSION_AFTER_MEDIA);
 		if (tsx->method.id == PJSIP_INVITE_METHOD) {
 			if (tsx->role == PJSIP_ROLE_UAC) {
 				if (tsx->state == PJSIP_TSX_STATE_COMPLETED) {
@@ -2004,10 +2015,6 @@ static void session_inv_on_tsx_state_changed(pjsip_inv_session *inv, pjsip_trans
 					}
 				}
 			}
-		} else {
-			if (tsx->role == PJSIP_ROLE_UAS && tsx->state == PJSIP_TSX_STATE_TRYING) {
-				handle_incoming_request(session, e->body.tsx_state.src.rdata, PJSIP_EVENT_TSX_STATE);
-			}
 		}
 		if ((cb = ast_sip_mod_data_get(tsx->mod_data, session_module.id,
 					       MOD_DATA_ON_RESPONSE))) {
@@ -2182,7 +2189,8 @@ static pjsip_redirect_op session_inv_on_redirected(pjsip_inv_session *inv, const
 		return PJSIP_REDIRECT_STOP;
 	}
 
-	handle_incoming(session, e->body.rx_msg.rdata, PJSIP_EVENT_RX_MSG);
+	handle_incoming(session, e->body.rx_msg.rdata, PJSIP_EVENT_RX_MSG,
+			AST_SIP_SESSION_BEFORE_REDIRECTING);
 
 	uri = pjsip_uri_get_uri(target);