AT&T Enhanced WebRTC (Web Real Time Communication) allows you to build real time browser based communication applications. WebRTC Restful APIs allows you to discover other party in communication and use standard offer/answer model to exchange session parameter to establish effective audio/video communications.

AT&T Enhanced WebRTC allows you to use AT&T Mobile Number or existing member Account IDs or use AT&T's Virtual Number for communication.

Get DHS Configuration & Create Phone Object

<p> <button id="createPhoneObjectButton" onclick="createPhoneObject()">Create Phone Object</button> <button id="createPhoneSuccessButton" hidden disabled>Phone Object Created Successfully</button> </p>
var phone, accessToken, myDHS, myDHSURL = 'your_dhs_url';

var xhrConfig = new XMLHttpRequest();
xhrConfig.open('GET', myDHSURL + "/config/");
xhrConfig.onreadystatechange = function() {
     if (xhrConfig.readyState == 4) {
          if (xhrConfig.status == 200) {
	        myDHS = JSON.parse(xhrConfig.responseText);
	    } else {
	        console.log(xhrConfig.responseText);
	    }
     }
}
xhrConfig.send();  

function createPhoneObject() {
    phone = ATT.rtc.Phone.getPhone();
    registerEvents();
}

function registerEvents() {
    phone.on('error', onError); 
}

function onError(data) {
    console.log(data.error);
}
						

Login and Logout (Account ID Users)

<!-- Your code goes here --> <p> <input type="text" id="loginInput" placeholder="Example: alice or bob" size="30" hidden> <button id="loginButton" onclick="createAccessToken()" hidden>Account ID Login</button> <button id="logoutButton" onclick="logout()" hidden>Logout</button> </p>
function createPhoneObject() {
    // All initilaizations go here
    loginInput.hidden = false;
    loginButton.hidden = false;
}

function registerEvents() {
    // All registrations go here
    phone.on('session:ready', onSessionReady);
    phone.on('session:disconnected', onSessionDisconnected);
}

function onSessionReady() {
    loginButton.hidden = true;
    logoutButton.hidden = false;
}
    
function onSessionDisconnected() {
    loginButton.hidden = false;
    logoutButton.hidden = true;
}
       
function createAccessToken() {
    var xhrToken = new XMLHttpRequest();
    xhrToken.open('POST', myDHS.app_token_url);
    xhrToken.setRequestHeader("Content-Type", "application/json");
    xhrToken.onreadystatechange = function() {
        if (xhrToken.readyState == 4) {
            if (xhrToken.status == 200) {
                accessToken = (JSON.parse(xhrToken.responseText));
                associateAccessToken();
            } else {
                console.log(xhrToken.responseText);
            }
        }
    }
    xhrToken.send(JSON.stringify({app_scope: "ACCOUNT_ID"}));
}
    
function associateAccessToken() {
    phone.associateAccessToken({
        userId: loginInput.value,
        token: accessToken.access_token,
        success: login,
        error: onError
    }); 
}

function login() {
    phone.login({token: accessToken.access_token});
}
    
function logout() {
    phone.logout();
}
						

Make and Answer Call

<!-- Your code goes here --> <p> <input type="text" id="callToInput" placeholder="Account ID/Telephone" hidden> <button id="makeCallButton" onclick="makeCall()" hidden>Make Call alice@yourdomain.com or 1234567890</button> <button id="answerCallButton" onclick="answerCall()" hidden>Answer Call</button> <audio id="local" style="display:none"></audio> <audio id="remote" style="display:none"></audio> </p>
function createPhoneObject() {
    // All initilaizations go here
    loginInput.hidden = false;
    loginButton.hidden = false;
}

function registerEvents() {
    // All registrations go here
    phone.on('call:incoming', onIncomingCall);
    phone.on('call:connected', onConnectedCall);
}

function onSessionReady() {
    // All sesssion initialization go here
    callToInput.hidden = false;
    makeCallButton.hidden = false;
}

function onSessionDisconnected() {
    // All sesssion exit go here
    callToInput.hidden = true;
    makeCallButton.hidden = true;
}
    
function onIncomingCall () {
    makeCallButton.hidden = true;
    answerCallButton.hidden = false;
}
    
function onConnectedCall () {
    callToInput.value = "" ;
    makeCallButton.hidden = true; 
    answerCallButton.hidden = true;
}
    
function makeCall() {
    phone.dial({
       destination: phone.cleanPhoneNumber(callToInput.value),
       mediaType: 'audio',
       localMedia: document.getElementById('local'),
       remoteMedia: document.getElementById('remote')
    });
}

function answerCall() {
    phone.answer({
       mediaType: 'audio',
       localMedia: document.getElementById('local'),
       remoteMedia: document.getElementById('remote')
    });
}  
						

Reject and Hangup Call

<!-- Your code goes here --> <button id="rejectCallButton" onclick="rejectCall()" hidden>Reject Call</button> <button id="hangupCallButton" onclick="hangUpCall()" hidden>Hangup Call</button>
function registerEvents () {
    // All registrations go here
    phone.on('call:disconnected', onDisconnectedCall);
    phone.on('call:rejected', onRejectedCall);
}

function onIncomingCall () {
    // Your code goes here
    rejectCallButton.hidden = false;
}

function onConnectedCall () {
    // Your code goes here
    hangupCallButton.hidden = false;
    rejectCallButton.hidden = true;
}

function onDisconnectedCall () {
    makeCallButton.hidden = false;
    rejectCallButton.hidden = true;
    answerCallButton.hidden = true; 
    hangupCallButton.hidden = true;
}        

function onRejectedCall () {
    makeCallButton.hidden = false;
    rejectCallButton.hidden = true;
    answerCallButton.hidden = true; 
}        
            
function hangUpCall() {
    phone.hangup ();
}
    
function rejectCall() {
    phone.reject ();
}
						

Hold and Resume Call

<!-- Your code goes here --> <button id="holdCallButton" onclick="holdCall()" hidden>Hold Call</button> <button id="resumeCallButton" onclick="resumeCall()" hidden>Resume Call</button>
function registerEvents() {
    // All registrations go here
    phone.on('call:resumed', onResumedCall);
}

function onConnectedCall () {
    // Your code goes here
    holdCallButton.hidden = false;
}

function onDisconnectedCall () {
    // Your code goes here
    holdCallButton.hidden = true;
    resumeCallButton.hidden = true;
}

function onHeldCall () {
    hangupCallButton.hidden = true;
    resumeCallButton.hidden = false;
    holdCallButton.hidden = true;
}

function onResumedCall () {
    hangupCallButton.hidden = false;
    resumeCallButton.hidden = true;
    holdCallButton.hidden = false;
}        

function holdCall() {
    phone.hold();
}
    
function resumeCall() {
    phone.resume();
}
						

Mute and Unmute Call

<!-- Your code goes here --> <button id="muteCallButton" onclick="muteCall()" hidden>Mute Call</button> <button id="unmuteCallButton" onclick="unmuteCall()" hidden>Unmute Call</button>
function registerEvents() {
    // All registrations go here
    phone.on('call:muted', onMutedCall);
    phone.on('call:unmuted', onUnmutedCall);
}

function onConnectedCall () {
    // Your code goes here
    muteCallButton.hidden = false;
}

function onDisconnectedCall () {
    // Your code goes here
    muteCallButton.hidden = true;
    unmuteCallButton.hidden = true;
}

function onHeldCall () {
    // Your code goes here
    muteCallButton.hidden = true;
    unmuteCallButton.hidden = true;
}

function onResumedCall () {
    // Your code goes here
    muteCallButton.hidden = false;
}

function onMutedCall () {
    muteCallButton.hidden = true;
    unmuteCallButton.hidden = false;
}        

function onUnmutedCall () {
    muteCallButton.hidden = false;
    unmuteCallButton.hidden = true;
}        

function muteCall() {
    phone.mute();
}
    
function unmuteCall() {
    phone.unmute();
}
						

Move and Cancel Call

<!-- Your code goes here --> <button id="moveCallButton" onclick="moveCall()" hidden>Move Call</button> <button id="cancelCallButton" onclick="cancelCall()" hidden>Cancel Call</button>
function registerEvents() {
    // All registrations go here
    phone.on('call:connecting', onConnectingCall);
    phone.on('call:canceled', onCanceledCall);
}

function onConnectedCall () {
    // Your code goes here
    cancelCallButton.hidden = true;
    moveCallButton.hidden = false;
}

function onDisconnectedCall () {
    // Your code goes here
    moveCallButton.hidden = true; 
    cancelCallButton.hidden = true;
}

function onHeldCall () {
    // Your code goes here
    moveCallButton.hidden = true;
}

function onConnectingCall () {
    makeCallButton.hidden = true;
    cancelCallButton.hidden = false;
}

function onCanceledCall () {
    makeCallButton.hidden = false;
    rejectCallButton.hidden = true;
    answerCallButton.hidden = true;
    cancelCallButton.hidden = true;
}        

function moveCall() {
    phone.move();
}
    
function cancelCall() {
    phone.cancel();
} 						
					

Add 2nd Call and Switch Call

<!-- Your code goes here --> <p> <button id="addCallButton" onclick="addCall()" hidden> Add 2nd Call bob@yourdomain.com or 1234567890 (This is not Conference Call) </button> <button id="switchCallButton" onclick="switchCall()" hidden>Switch Call</button> </p>
function registerEvents() {
    // All registrations go here
    phone.on('call:connected', onConnectedCall);
    phone.on('session:call-switched', onCallSwitched);
}
    
function onConnectedCall () {
    // Your code goes here
    addCallButton.hidden = false;
}

function onCallSwitched () {
    addCallButton.hidden = true;
    switchCallButton.hidden = false;
}	        

function addCall() {
    phone.addCall({
        destination: phone.cleanPhoneNumber(callToInput.value),
        mediaType: 'audio',
        localMedia: document.getElementById('local'),
        remoteMedia: document.getElementById('remote')
    });
}

function switchCall () {
    phone.switchCall();
} 
						

Video Call

<!-- Your code goes here --> <video id="local" style="width:320px;"> <video id="remote" style="width:320px;">

// code to register for call events goes here ...

function makeCall() {
    phone.dial({
        destination: phone.cleanPhoneNumber(callToInput.value),
        mediaType: 'video',
        localMedia: document.getElementById('local'),
        remoteMedia: document.getElementById('remote')
    });
}

function answerCall() {
    phone.answer({
        mediaType: 'video',
        localMedia: document.getElementById('local'),
        remoteMedia: document.getElementById('remote')
    });
}  
						

Login Advanced

<p> <select id="tokenScopeSelect" onchange="onTokenScopeSelect()"> <option>Select a Account Login Type to start</option> <option value="ACCOUNT_ID">Account ID Login</option> <option value="MOBILE_NUMBER">Mobile Number Login</option> <option value="VIRTUAL_NUMBER">Virtual Number Login</option> </select> </p> <p> <button id="startLoginButton" onClick="onStartLoginClick()" disabled>Enter Account ID/Virtual Number and Click here to start</button> <input type="text" id="loginInput" value="" disabled size="55"> </p> <p> <button id="authCodeButton" onClick="onAuthCodeClick()" disabled >Get AT&T Mobile Subscriber Consent</button> <input id="authCodeResult" disabled size="55"> </p> <p> <button id="e911AddressButton" onClick="one911AddressClick()" disabled >Collect/Retrieve E911 Adress</button> <input id="e911AdressResult" disabled size="110"> </p> <p> <button id="e911AccessTokenButton" onClick="one911AccessTokenClick()" disabled >Create E911 Access Token</button> <input id="e911AccessTokenResult" disabled size="40"> </p> <p> <button id="e911IdButton" onClick="onE911IdClick()" disabled >Get E911 Address Identifier</button> <input id="e911IDInput" disabled size="70"> </p> <p> <button id="createUserAccessTokenButton" onClick="createUserAccessTokenClick()" disabled >Create User Access Token</button> <input id="userTokenResult" disabled size="40"> </p> <p> <button id="associateUserAccessTokenButton" onClick="associateUserAccessTokenClick()" disabled>Associate User Access Token</button> <input id="associatedUserTokenResult" disabled size="40"> </p> <p> <button id="loginButton" onClick="onLoginClick()" disabled>Login</button> <input id="loginSessionResult" disabled size="60"> <button id="logoutButton" onClick="logout()" hidden>Logout</button> <input id="errorMessage" value="There is an error. Check console log for details" hidden disabled size="60"> </p>
var phone, accessToken, e911Data, tokenScope, myDHS, myDHSURL = 'your_dhs_url';
         
// On page load, check for URL for an Auth Code
if (window.location.href.indexOf("?code=") > -1) {
    tokenScopeSelect.value = "MOBILE_NUMBER";
    onTokenScopeSelect();
    authCodeButton.disabled = true;
    authCodeResult.value = location.search.split('code=')[1];
    authCodeResult.value = (authCodeResult.value).replace('%7E', '~');
    authCodeResult.value = (authCodeResult.value).replace('%7E', '~');
    authCodeResult.value = (authCodeResult.value).replace('%7E', '~');
    onStartLoginClick();
}

var xhrConfig = new XMLHttpRequest();
xhrConfig.open('GET', myDHSURL + "/config/");
xhrConfig.onreadystatechange = function() {
if (xhrConfig.readyState == 4) {
    if (xhrConfig.status == 200) {
        console.log(xhrConfig.responseText);
        myDHS = JSON.parse(xhrConfig.responseText);
        createPhoneObject();
    } else {
        console.log(xhrConfig.responseText);
    }
}
}
xhrConfig.send(); 
    
function createPhoneObject() {
    phone = ATT.rtc.Phone.getPhone();
    registerEvents();
}

function registerEvents() {
    phone.on('error', onError); 
    phone.on('session:ready', onSessionReady);
    phone.on('session:disconnected', onSessionDisconnected);
}
    
function onError(data) {
    console.log(data.error);
    loginButton.disabled = true;
    errorMessage.hidden = false;
}

function onSessionReady(data) {
    loginButton.disabled = true;
    logoutButton.hidden = false;
    loginSessionResult.value = "Session ID ".concat(data.sessionId);
}

function onSessionDisconnected() {
    logoutButton.hidden = true;
    window.location ="step10-login-advanced.html"; 
}
    
function onTokenScopeSelect (data) {
    authCodeButton.disabled = true; // Disabled button on selection change
    e911AddressButton.disabled = true; // Disabled button on selection change
    createUserAccessTokenButton.disabled = true; // Disabled button on selection change
    e911IdButton.disabled = true; // Disabled button on selection change
    createUserAccessTokenButton.disabled = true; // Disabled button on selection change
    associateUserAccessTokenButton.disabled = true; // Disabled button on selection change
    loginButton.disabled = true; // Disabled button on selection change
    associatedUserTokenResult.placeholder = "Required";
    userTokenResult.placeholder = "Required";   
    loginSessionResult.placeholder = "Required";
    startLoginButton.disabled = false;
    loginInput.disabled = false;
    authCodeResult.placeholder = "Not Required";
    if (tokenScopeSelect.value == "ACCOUNT_ID") {
        loginInput.placeholder = "Enter Account ID (Ex: alice or bob)";
        e911AdressResult.placeholder = "Not Required";
        e911AccessTokenResult.placeholder = "Not Required";
        e911IDInput.placeholder = "Not Required";
    }
    else if (tokenScopeSelect.value == "VIRTUAL_NUMBER") { 
        loginInput.placeholder = "Enter Your Assigned Virtual Number (Ex: vtn:1234567890)";
        e911AdressResult.placeholder = "Required";
        e911AccessTokenResult.placeholder = "Required";
        e911IDInput.placeholder = "Required";
    }
    else {
        startLoginButton.disabled = true;
        loginInput.disabled = true;
        loginInput.placeholder = "Not Required";
        authCodeButton.disabled = false;
        authCodeResult.placeholder = "Get AT&T Subscriber User Consent Authorization Code";
        e911AdressResult.placeholder = "Required";
        e911AccessTokenResult.placeholder = "Required";
        e911IDInput.placeholder = "Required"
        associatedUserTokenResult.placeholder = "Not Required";
    }
}

function onAuthCodeClick() {
    if (myDHS.info.dhs_platform == 'PHP') { //Use PHP DHS Unverisal OAuth Callback
        window.location.href = myDHS.oauth_callback + '?redirect_uri=' + window.location.href; 
    } else { //Use App specific OAuth Callback
        window.location.href = 'https://api.att.com/oauth/v4/authorize?client_id=' + myDHS.app_key + '&scope=WEBRTCMOBILE&redirect_uri=' + window.location.href;   
    }
}
    
function onStartLoginClick(){
    startLoginButton.disabled = true;
    loginInput.disabled = true;
    if (tokenScopeSelect.value == "ACCOUNT_ID") {
        createUserAccessTokenButton.disabled = false;
        userTokenResult.placeholder = "Next create a user token";
    }
    else {
        e911AddressButton.disabled = false;
        e911AdressResult.placeholder = "Next collect/retrieve a valid physical address";
    }    
}
      
function one911AddressClick() {
    e911AddressButton.disabled = true;
    e911AdressResult.value = "For demo, we assumed a valid physical address has been entered by user or retrieved from your database";
    e911AccessTokenButton.disabled = false;
    e911AccessTokenResult.placeholder = "Next use E911 Scope to create acess token";
}

function one911AccessTokenClick() {
    e911AccessTokenResult.placeholder = "Creating E911 access token .....";
    tokenScope = "E911";
    createAccessToken();
}

function onE911IdClick() {
    e911IDInput.placeholder = "Getting E911 Address ID .....";  
    createE911Id () ;
}
    
function createUserAccessTokenClick() {
    userTokenResult.placeholder = "Creating user access token .....";
    tokenScope = tokenScopeSelect.value;
    createAccessToken();
}

function associateUserAccessTokenClick() {
    associatedUserTokenResult.placeholder = "Associating user access token .....";
    associateAccessToken();
}
    
function onLoginClick() {
    login();
}

function createAccessToken() {
    var xhrToken = new XMLHttpRequest();
    xhrToken.open('POST', myDHS.app_token_url);
    xhrToken.setRequestHeader("Content-Type", "application/json");
    xhrToken.onreadystatechange = function() {
        if (xhrToken.readyState == 4) {
            if (xhrToken.status == 200) {
                console.log(xhrToken.responseText);
                accessToken = (JSON.parse(xhrToken.responseText));
                if (tokenScope == "E911") {
                    e911AccessTokenButton.disabled = true;
                    e911AccessTokenResult.value = accessToken.access_token;
                    e911IdButton.disabled = false;
                    e911IDInput.placeholder = "Next use the E911 Address & E911 access token to get the E911 ID";
                } else {
                    userTokenResult.value = accessToken.access_token;
                    createUserAccessTokenButton.disabled = true;
                    if (tokenScope != "MOBILE_NUMBER") {
                        associateUserAccessTokenButton.disabled = false;
                        associatedUserTokenResult.placeholder = "Next associated user access token to user";
                    } else {
                        loginButton.disabled = false;
                        loginSessionResult.placeholder = "Next click login to get sesssion ID";
                    }
                }
            } else {
                console.log(xhrToken.responseText);
            }
        }
    }
    xhrToken.send(JSON.stringify({app_scope: tokenScope, auth_code: authCodeResult.value}));
}    

function createE911Id() {
    var xhrE911 = new XMLHttpRequest();
    xhrE911.open('POST', myDHS.app_e911id_url);
    xhrE911.setRequestHeader("Content-Type", "application/json");
    xhrE911.onreadystatechange = function() {
        if (xhrE911.readyState == 4) {
            if (xhrE911.status == 200) {
                console.log(xhrE911.responseText);
                e911Data = (JSON.parse(xhrE911.responseText));
                e911IDInput.value = e911Data.e911Locations.addressIdentifier;
                e911IdButton.disabled = true;
                createUserAccessTokenButton.disabled = false;
                userTokenResult.placeholder = "Next create a user access token";
            } else {
                console.log(xhrE911.responseText);
            }
        }
    }
    xhrE911.send(JSON.stringify({
        token: accessToken.access_token,
        address: {
                    first_name: 'ATT',
                    last_name: 'Inc',
                    house_number: '16221',
                    street: 'NE 72nd Way',
                    unit: '',
                    city: 'Redmond',
                    state: 'WA',
                    zip: '98052'
        },
        is_confirmed: 'true'
    }));
}
 
function associateAccessToken() {
    phone.associateAccessToken({
        userId: loginInput.value,
        token: userTokenResult.value,
        success:  function () {
                    associatedUserTokenResult.value = "Successfully associated token with user id";
                    associateUserAccessTokenButton.disabled = true;
                    loginButton.disabled = false;
                    loginSessionResult.placeholder = "Next click login to get sesssion ID";
        },
        error: onError
        }) 
}

function login() {
    phone.login({token: userTokenResult.value, e911Id: e911IDInput.value});
}

function logout() {
    phone.logout();
}
						

Start Conference

<!-- Your code goes here --> <button id="startConferenceButton" onclick="onStartConference()" hidden>Start Conference</button> <button id="endConferenceButton" onclick="endConference()" hidden>End Conference</button>
function registerEvents() {
    // All registrations go here
    phone.on('conference:connected', onConferenceConnected);
    phone.on('conference:ended', onConferenceEnded);
}

function onSessionReady() {
    // Your code goes here
    startConferenceButton.hidden = false;
}

function onSessionDisconnected() {
    // Your code goes here
    startConferenceButton.hidden = true;
    endConferenceButton.hidden = true;
}

function onConferenceConnected () {
    startConferenceButton.hidden = true;
    endConferenceButton.hidden = false;
}
    
function onConferenceEnded () {
    startConferenceButton.hidden = false;
    endConferenceButton.hidden = true;
}
    
function onStartConference() {
    startConference ();
}

function onEndConference() {
    endConference ();
}

function startConference() {
    phone.startConference({
        mediaType: 'video',
        localMedia: document.getElementById('local'),
        remoteMedia: document.getElementById('remote')
    });
}
    
function endConference() {
    phone.endConference();
}
						

Add Participants

<!-- Your code goes here --> <p> <input type="text" id="callToInput" placeholder="Account ID/Telephone" hidden> <button id="addParticipantButton" onclick="addParticipant()" hidden>Add Participant alice@yourdomain.com or 1234567890</button> <button id="invitationSentButton" hidden>Invitation Sent</button> <button id="invitationAcceptedButton" hidden>Invitation Accepted</button> <button id="invitationReceivedButton" onclick="onJoinConference()" hidden>Accept Conference Call</button> </p>
function registerEvents() {
    // All registrations go here
    phone.on('conference:invitation-sent', onConferenceInvitationSent);
    phone.on('conference:invitation-received', onConferenceInvitationReceived);
    phone.on('conference:invitation-accepted', onConferenceInvitationAccepted);
    phone.on('conference:joining', onConferenceJoining);
}

function onSessionDisconnected() {
    // Your code goes here
    callToInput.hidden = true;
}

function onConferenceConnected () {
    // Your code goes here
    if (isConferenceHost) {
        callToInput.hidden = false;
        addParticipantButton.hidden = false;
    }
}

function onConferenceEnded () {
    // Your code goes here
    callToInput.hidden = true;
    addParticipantButton.hidden = true;
    invitationSentButton.hidden = true;
    invitationAcceptedButton.hidden = true;
    invitationReceivedButton.hidden = true;
}

function onStartConference() {
    // Your code goes here
    isConferenceHost = true;
}

function endConference() {
    // Your code goes here
    isConferenceHost = false;
}

function onConferenceInvitationSent() {
    if (!phone.isCallInProgress) {
        addParticipantButton.hidden = true;
    }
    invitationSentButton.hidden = false;
    invitationAcceptedButton.hidden = true;
}
    
function onConferenceInvitationReceived() {
    addParticipantButton.hidden = true;
    startConferenceButton.hidden = true;
    invitationReceivedButton.hidden = false;
}
    
function onConferenceInvitationAccepted() {
    callToInput.value = "";
    callToInput.placeholder = "New Participant";
    addParticipantButton.hidden = false;
    invitationSentButton.hidden = true;
    invitationAcceptedButton.hidden = false;
}
    
function onConferenceJoining() {
    invitationReceivedButton.hidden = true;
}
        
function addParticipant() {
    phone.addParticipant(callToInput.value);
}
    
function onJoinConference() {
    phone.joinConference({
        localMedia: document.getElementById('local'),
        remoteMedia: document.getElementById('remote')
    });
    isConferenceHost = false;
}
						

Other Links

Additional links go here.

View details »