Azure Communication Call Automation (Java)
Build server-side call automation workflows including IVR systems, call routing, recording, and AI-powered interactions.
Installation
xml
<dependency> <groupId>com.azure</groupId> <artifactId>azure-communication-callautomation</artifactId> <version>1.6.0</version></dependency>Client Creation
java
import com.azure.communication.callautomation.CallAutomationClient;import com.azure.communication.callautomation.CallAutomationClientBuilder;import com.azure.core.credential.TokenCredential;import com.azure.identity.AzureIdentityEnvVars;import com.azure.identity.DefaultAzureCredentialBuilder;import com.azure.identity.ManagedIdentityCredentialBuilder;
// Local dev: DefaultAzureCredential. Production: set AZURE_TOKEN_CREDENTIALS=prod or AZURE_TOKEN_CREDENTIALS=<specific_credential>TokenCredential credential = new DefaultAzureCredentialBuilder() .requireEnvVars(AzureIdentityEnvVars.AZURE_TOKEN_CREDENTIALS) .build();// Or use a specific credential directly in production:// See https://learn.microsoft.com/java/api/overview/azure/identity-readme?view=azure-java-stable#credential-classes// TokenCredential credential = new ManagedIdentityCredentialBuilder().build();
// With DefaultAzureCredentialCallAutomationClient client = new CallAutomationClientBuilder() .endpoint("https://<resource>.communication.azure.com") .credential(credential) .buildClient();
// With connection stringCallAutomationClient client = new CallAutomationClientBuilder() .connectionString("<connection-string>") .buildClient();Key Concepts
| Class | Purpose |
|---|---|
CallAutomationClient | Make calls, answer/reject incoming calls, redirect calls |
CallConnection | Actions in established calls (add participants, terminate) |
CallMedia | Media operations (play audio, recognize DTMF/speech) |
CallRecording | Start/stop/pause recording |
CallAutomationEventParser | Parse webhook events from ACS |
Create Outbound Call
java
import com.azure.communication.callautomation.models.*;import com.azure.communication.common.CommunicationUserIdentifier;import com.azure.communication.common.PhoneNumberIdentifier;
// Call to PSTN numberPhoneNumberIdentifier target = new PhoneNumberIdentifier("+14255551234");PhoneNumberIdentifier caller = new PhoneNumberIdentifier("+14255550100");
CreateCallOptions options = new CreateCallOptions( new CommunicationUserIdentifier("<user-id>"), // Source List.of(target)) // Targets .setSourceCallerId(caller) .setCallbackUrl("https://your-app.com/api/callbacks");
CreateCallResult result = client.createCall(options);String callConnectionId = result.getCallConnectionProperties().getCallConnectionId();Answer Incoming Call
java
// From Event Grid webhook - IncomingCall eventString incomingCallContext = "<incoming-call-context-from-event>";
AnswerCallOptions options = new AnswerCallOptions( incomingCallContext, "https://your-app.com/api/callbacks");
AnswerCallResult result = client.answerCall(options);CallConnection callConnection = result.getCallConnection();Play Audio (Text-to-Speech)
java
CallConnection callConnection = client.getCallConnection(callConnectionId);CallMedia callMedia = callConnection.getCallMedia();
// Play text-to-speechTextSource textSource = new TextSource() .setText("Welcome to Contoso. Press 1 for sales, 2 for support.") .setVoiceName("en-US-JennyNeural");
PlayOptions playOptions = new PlayOptions( List.of(textSource), List.of(new CommunicationUserIdentifier("<target-user>")));
callMedia.play(playOptions);
// Play audio fileFileSource fileSource = new FileSource() .setUrl("https://storage.blob.core.windows.net/audio/greeting.wav");
callMedia.play(new PlayOptions(List.of(fileSource), List.of(target)));Recognize DTMF Input
java
// Recognize DTMF tonesDtmfTone stopTones = DtmfTone.POUND;
CallMediaRecognizeDtmfOptions recognizeOptions = new CallMediaRecognizeDtmfOptions( new CommunicationUserIdentifier("<target-user>"), 5) // Max tones to collect .setInterToneTimeout(Duration.ofSeconds(5)) .setStopTones(List.of(stopTones)) .setInitialSilenceTimeout(Duration.ofSeconds(15)) .setPlayPrompt(new TextSource().setText("Enter your account number followed by pound."));
callMedia.startRecognizing(recognizeOptions);Recognize Speech
java
// Speech recognition with AICallMediaRecognizeSpeechOptions speechOptions = new CallMediaRecognizeSpeechOptions( new CommunicationUserIdentifier("<target-user>")) .setEndSilenceTimeout(Duration.ofSeconds(2)) .setSpeechLanguage("en-US") .setPlayPrompt(new TextSource().setText("How can I help you today?"));
callMedia.startRecognizing(speechOptions);Call Recording
java
CallRecording callRecording = client.getCallRecording();
// Start recordingStartRecordingOptions recordingOptions = new StartRecordingOptions( new ServerCallLocator("<server-call-id>")) .setRecordingChannel(RecordingChannel.MIXED) .setRecordingContent(RecordingContent.AUDIO_VIDEO) .setRecordingFormat(RecordingFormat.MP4);
RecordingStateResult recordingResult = callRecording.start(recordingOptions);String recordingId = recordingResult.getRecordingId();
// Pause/resume/stopcallRecording.pause(recordingId);callRecording.resume(recordingId);callRecording.stop(recordingId);
// Download recording (after RecordingFileStatusUpdated event)callRecording.downloadTo(recordingUrl, Paths.get("recording.mp4"));Add Participant to Call
java
CallConnection callConnection = client.getCallConnection(callConnectionId);
CommunicationUserIdentifier participant = new CommunicationUserIdentifier("<user-id>");AddParticipantOptions addOptions = new AddParticipantOptions(participant) .setInvitationTimeout(Duration.ofSeconds(30));
AddParticipantResult result = callConnection.addParticipant(addOptions);Transfer Call
java
// Blind transferPhoneNumberIdentifier transferTarget = new PhoneNumberIdentifier("+14255559999");TransferCallToParticipantResult result = callConnection.transferCallToParticipant(transferTarget);Handle Events (Webhook)
java
import com.azure.communication.callautomation.CallAutomationEventParser;import com.azure.communication.callautomation.models.events.*;
// In your webhook endpointpublic void handleCallback(String requestBody) { List<CallAutomationEventBase> events = CallAutomationEventParser.parseEvents(requestBody); for (CallAutomationEventBase event : events) { if (event instanceof CallConnected) { CallConnected connected = (CallConnected) event; System.out.println("Call connected: " + connected.getCallConnectionId()); } else if (event instanceof RecognizeCompleted) { RecognizeCompleted recognized = (RecognizeCompleted) event; // Handle DTMF or speech recognition result DtmfResult dtmfResult = (DtmfResult) recognized.getRecognizeResult(); String tones = dtmfResult.getTones().stream() .map(DtmfTone::toString) .collect(Collectors.joining()); System.out.println("DTMF received: " + tones); } else if (event instanceof PlayCompleted) { System.out.println("Audio playback completed"); } else if (event instanceof CallDisconnected) { System.out.println("Call ended"); } }}Hang Up Call
java
// Hang up for all participantscallConnection.hangUp(true);
// Hang up only this legcallConnection.hangUp(false);Error Handling
java
import com.azure.core.exception.HttpResponseException;
try { client.answerCall(options);} catch (HttpResponseException e) { if (e.getResponse().getStatusCode() == 404) { System.out.println("Call not found or already ended"); } else if (e.getResponse().getStatusCode() == 400) { System.out.println("Invalid request: " + e.getMessage()); }}Environment Variables
bash
AZURE_COMMUNICATION_ENDPOINT=https://<resource>.communication.azure.com # Required for all auth methodsAZURE_COMMUNICATION_CONNECTION_STRING=endpoint=https://...;accesskey=... # Alternative to Entra ID authCALLBACK_BASE_URL=https://your-app.com/api/callbacks # Required for webhook callbacksAZURE_TOKEN_CREDENTIALS=prod # Required only if DefaultAzureCredential is used in productionTrigger Phrases
- "call automation Java", "IVR Java", "interactive voice response"
- "call recording Java", "DTMF recognition Java"
- "text to speech call", "speech recognition call"
- "answer incoming call", "transfer call Java"
- "Azure Communication Services call automation"

