Doing a Cold Transfer with the Amazon Connect Streams API
The Amazon Connect Streams API allows you to create custom interfaces for the soft-phone and provides many functions for interacting with the current connection. It is a powerful set of tools but some of the more sophisticated functions may not be so obvious. This blog post describes how to implement a cold transfer using the plain Streams API.
Transfer Mode Definitions
Warm Transfer
Put customer on hold, connect to 3rd party, introduce yourself, begin conference, introduce parties, leave conference.
Blind Transfer
Initiate connection to 3rd party, leave the call as its dialing.
Cold Transfer
Initiate connection to 3rd party, leave the call AFTER the 3rd party picks up.
The Problem with Blind Transfer
From a customer service perspective – a blind transfer should NEVER be used.
What if the 3rd party does not pick up? You would not want your customer to go through the whole process again – and potentially get dropped yet again.
What Happens in a Cold Transfer?
Simply put – a cold transfer does not disconnect the agent until the 3rd party picks up.

Implementation
Special Sauce
The event subscription within the addConnection function below is what makes this work.
If a callback is passed in, the method creates a subscription to the contact REFRESH event.
When that event fires:
- If outbound is still connecting: we wait for the next event.
- If outbound is connected: the callback is executed and we unsubscribe.
Otherwise: Connection failed for some reason, so we don’t execute the callback and we unsubscribe.
Code Sample
To make things simpler, I did not include implementations for these underscore methods.
_getContact: Gets the current contact object from agent.getContacts()
_getConnectionByType: filters given connections and returns based on type.
/**
* Initiates a cold transfer.
* If 3rd party picks up - agent disconnects
* If 3rd party does not pick up - customer is left on-hold and agent stays connected.
*/
const coldTransferToDestination = function(endpoint){
var contact = _getContact();
holdConnection(connect.ConnectionType.INBOUND, function() {
addConnection(contact, endpoint, function(){
beginConference(function(){
endConference(function(){
console.log("Cold transfer complete");
})
})
});
});
}
/**
* Holds a connection and provides error handling.
*/
const holdConnection = function(connectionType, callback) {
var contact = _getContact();
var connection = _getConnectionByType(contact.getConnections(), connectionType);
if(connection){
if(!connection.isOnHold()) {
connection.hold({
success: function() {
if (callback) {
callback();
}
},
failure: function(e) {
console.error("connection hold error: " + e.message);
}
});
} else {
callback();
}
}
}
/**
* Wrapper method for adding connections with error handling
* Method executes callback when outbound connection connects.
*/
const addConnection = function(contact, endpoint, callback){
contact.addConnection(endpoint,
{
success: function() {
if(callback){
// Execute callback when outbound call is connected.
var bus = connect.core.getEventBus();
bus.subscribe(contact.getEventName(connect.ContactEvents.REFRESH), function(){
try {
var contact = _getContact();
if(contact){
var outbound = _getConnectionByType(
contact.getConnections(), connect.ConnectionType.OUTBOUND);
if(outbound && outbound.isConnecting()){
// Still connecting, wait for next event
return;
}
if(outbound && outbound.isConnected()){
callback();
}
}
// Clean up subscription. 'this' is now the event
this.unsubscribe()
} catch (e) {
console.error("Error in addConnection:OnRefresh. " + e.message);
}
});
}
},
failure: function(e) {
console.error("Couldn't add connection to contact. " + e.message);
}
});
}
/**
* Begins conference between Agent, Incoming (customer) and Outgoing (thirdParty)
*/
const beginConference = function(callback) {
var contact = _getContact();
if (contact) {
contact.conferenceConnections(
{
success: function() {
if (callback) {
callback();
}
},
failure: function(e) {
console.error("Couldn't begin conference for contact. " + e.message);
}
});
} else {
console.error("Couldn't begin conference, there's no conversation.");
}
}
/**
* Disconnects agent from conference
*/
const endConference = function(callback) {
var contact = _getContact();
if (contact) {
var agentConnection = contact.getAgentConnection();
if (agentConnection) {
agentConnection.destroy(
{
success: function() {
if (callback) {
callback();
}
},
failure: function(e) {
console.error("Couldn't end agent connection to conference. " + e.message);
}
});
}
} else {
console.error("Couldn't end conference, there's no conversation.");
}
}