Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
e401a07
DEVEXP-1473: Add Voice V2 Destination helper
edu-sinch Oct 16, 2026
73c3d73
DEVEXP-1473: Add Voice V2 Destination helper refactor
edu-sinch Oct 16, 2026
1a7f020
Merge pull request #66 from sinch/edu-sinch/DEVEXP-1473-VoiceV2Helper…
edu-sinch Oct 19, 2026
ef20974
DEVEXP-1473: Add Voice V2 SVAML command helpers
edu-sinch Oct 19, 2026
ad85647
DEVEXP-1473: Add Voice V2 menu helpers
edu-sinch Oct 19, 2026
d4e9e35
DEVEXP-1473: Add Voice V2 CommandsSequenceCreator
edu-sinch Oct 20, 2026
505e74a
DEVEXP-1473: Add Voice V2 call behavior and Sinch Event response helpers
edu-sinch Oct 20, 2026
1949886
DEVEXP-1473: Use the Voice V2 helpers in snippets, examples and README
edu-sinch Oct 20, 2026
8f17d44
DEVEXP-1473: improvements for the helpers
edu-sinch Oct 20, 2026
9da987d
Address comments for the helpers
edu-sinch Oct 22, 2026
8b21e78
DEVEXP-1473: Add the Voice V2 VoiceName catalog to the helpers
edu-sinch Oct 22, 2026
3be0eaf
DEVEXP-1473: Voice V2 setCommands accepts one or more commands
edu-sinch Oct 22, 2026
b0b69ae
Updated README
edu-sinch Oct 22, 2026
9fe28fb
Merge pull request #67 from sinch/edu-sinch/DEVEXP-1473-VoiceV2Helper…
edu-sinch Oct 22, 2026
b9ff5c8
Merge pull request #68 from sinch/edu-sinch/DEVEXP-1473-VoiceV2Helpers
edu-sinch Oct 26, 2026
9c2f76f
build (release): Bump version to 2.4.0 for sources
invalid-email-address Oct 28, 2026
b44ad77
[release] Set release & tag: 2.4.0
invalid-email-address Oct 28, 2026
f6d712a
[release] Set next version: 2.5.0-SNAPSHOT
invalid-email-address Oct 28, 2026
2eb55cd
build (release): Set next version to 2.5.0-dev for sources
invalid-email-address Oct 28, 2026
c8dc925
Update CHANGELOG with date and version
edu-sinch Oct 28, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,16 @@ All notable changes to the **Sinch Java SDK** are documented in this file.
> - `[design]` — API design change
> - `[tech]` — technical improvement

---
## v2.4.0 - 2026-10-28

### Voice
- **[feature]** V2 helpers: `Destination`, SVAML commands (`Calls`, `Amd`, `Messages`, `Recording`, `CustomEvents`, `Menu`) and `CommandsSequenceCreator`. Event handlers accept a sequence lambda
- **[feature]** V2 helpers: `CallBehaviorHelper` for services and `SinchEventResponses` for Sinch Events
- **[feature]** V2 helpers: `VoiceName` catalog of text-to-speech voices
- **[feature]** V2 `setCommands(...)` accepts one or more commands
- **[doc]** V2 snippets, `sinch-events` example and README use the helpers

---
## v2.3.0 - 2026-10-15

Expand Down
25 changes: 25 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,31 @@ You can find a complete example in [examples/sinch-events](https://github.com/si

The Voice API v2 needs no extra parameters, use the [common client](#client-initialization) shown above.

The helpers in `com.sinch.sdk.domains.voice.models.v2.helpers` build the SVAML commands of a call, the call behavior of a service and the responses to Sinch Events. For example, to call a number, play a greeting once the call is answered, then hang up:

```java
import com.sinch.sdk.domains.voice.models.v2.calls.request.StartCallRequest;
import com.sinch.sdk.domains.voice.models.v2.helpers.Calls;
import com.sinch.sdk.domains.voice.models.v2.helpers.CommandsSequenceCreator;

StartCallRequest request =
StartCallRequest.builder()
.setCommands(
CommandsSequenceCreator.create()
.dial("RECIPIENT_PHONE_NUMBER", dial -> dial
.from("SINCH_VIRTUAL_PHONE_NUMBER")
.onAnswer(answered -> answered.text(
"Hello from the Sinch Java SDK!",
"Emma",
greeting -> greeting.onFinish(Calls.hangup()))))
.build())
.build();

client.voice().v2().calls().start(request);
```

The same commands answer a Sinch Event, with `SinchEventResponses.response(...)` or, for a `call.incoming` event, `SinchEventResponses.incomingCallResponse(...)`.


### Your first request

Expand Down
2 changes: 1 addition & 1 deletion client/src/main/com/sinch/sdk/SDK.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
public class SDK {

public static final String NAME = "Sinch Java SDK";
public static final String VERSION = "2.4.0-dev";
public static final String VERSION = "2.5.0-dev";
public static final String AUXILIARY_FLAG = "";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.sinch.sdk.domains.voice.models.v2.helpers;

/**
* Helpers to build the Answering Machine Detection SVAML command
*
* @since 2.4
*/
public final class Amd {

private Amd() {}

/**
* Detect what answered the call: a human, a machine, a beep, or an unknown result
*
* <p>Detection runs in parallel with the next commands. Set the commands to run for each result
* on the returned creator.
*
* @return The creator of the <code>amd</code> command
* @since 2.4
*/
public static AmdCreator activate() {
return new AmdCreator();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
package com.sinch.sdk.domains.voice.models.v2.helpers;

import com.sinch.sdk.domains.voice.models.v2.svaml.SvamlCommand;
import com.sinch.sdk.domains.voice.models.v2.svaml.amd.AmdCommand;
import com.sinch.sdk.domains.voice.models.v2.svaml.amd.AmdEvents;
import java.util.Collection;
import java.util.List;
import java.util.function.Consumer;

/**
* Fluent creator of an <code>amd</code> command, returned by {@link Amd#activate()}
*
* <p>Calling an event handler more than once appends the commands.
*
* @since 2.4
*/
public final class AmdCreator {

private List<SvamlCommand> onHuman;
private List<SvamlCommand> onMachine;
private List<SvamlCommand> onBeep;
private List<SvamlCommand> onUnknown;

AmdCreator() {}

/**
* Add commands to run when a human answers
*
* @param commands Commands to append
* @return This creator
* @since 2.4
*/
public AmdCreator onHuman(SvamlCommand... commands) {
onHuman = Commands.append(onHuman, commands);
return this;
}

/**
* Add commands to run when a human answers
*
* @param commands Commands to append
* @return This creator
* @since 2.4
*/
public AmdCreator onHuman(Collection<? extends SvamlCommand> commands) {
onHuman = Commands.append(onHuman, commands);
return this;
}

/**
* Add commands to run when a human answers
*
* @param sequence Lambda adding the commands to append
* @return This creator
* @since 2.4
*/
public AmdCreator onHuman(Consumer<CommandsSequenceCreator> sequence) {
onHuman = Commands.append(onHuman, sequence);
return this;
}

/**
* Add commands to run when a machine answers
*
* @param commands Commands to append
* @return This creator
* @since 2.4
*/
public AmdCreator onMachine(SvamlCommand... commands) {
onMachine = Commands.append(onMachine, commands);
return this;
}

/**
* Add commands to run when a machine answers
*
* @param commands Commands to append
* @return This creator
* @since 2.4
*/
public AmdCreator onMachine(Collection<? extends SvamlCommand> commands) {
onMachine = Commands.append(onMachine, commands);
return this;
}

/**
* Add commands to run when a machine answers
*
* @param sequence Lambda adding the commands to append
* @return This creator
* @since 2.4
*/
public AmdCreator onMachine(Consumer<CommandsSequenceCreator> sequence) {
onMachine = Commands.append(onMachine, sequence);
return this;
}

/**
* Add commands to run when a beep is detected
*
* @param commands Commands to append
* @return This creator
* @since 2.4
*/
public AmdCreator onBeep(SvamlCommand... commands) {
onBeep = Commands.append(onBeep, commands);
return this;
}

/**
* Add commands to run when a beep is detected
*
* @param commands Commands to append
* @return This creator
* @since 2.4
*/
public AmdCreator onBeep(Collection<? extends SvamlCommand> commands) {
onBeep = Commands.append(onBeep, commands);
return this;
}

/**
* Add commands to run when a beep is detected
*
* @param sequence Lambda adding the commands to append
* @return This creator
* @since 2.4
*/
public AmdCreator onBeep(Consumer<CommandsSequenceCreator> sequence) {
onBeep = Commands.append(onBeep, sequence);
return this;
}

/**
* Add commands to run when the result is unknown
*
* @param commands Commands to append
* @return This creator
* @since 2.4
*/
public AmdCreator onUnknown(SvamlCommand... commands) {
onUnknown = Commands.append(onUnknown, commands);
return this;
}

/**
* Add commands to run when the result is unknown
*
* @param commands Commands to append
* @return This creator
* @since 2.4
*/
public AmdCreator onUnknown(Collection<? extends SvamlCommand> commands) {
onUnknown = Commands.append(onUnknown, commands);
return this;
}

/**
* Add commands to run when the result is unknown
*
* @param sequence Lambda adding the commands to append
* @return This creator
* @since 2.4
*/
public AmdCreator onUnknown(Consumer<CommandsSequenceCreator> sequence) {
onUnknown = Commands.append(onUnknown, sequence);
return this;
}

/**
* Build the <code>amd</code> command
*
* @return The command. Its <code>events</code> are only set when a handler was given
* @since 2.4
*/
public AmdCommand build() {
AmdCommand.Builder builder = AmdCommand.builder();
if (null != onHuman || null != onMachine || null != onBeep || null != onUnknown) {
builder.setEvents(buildEvents());
}
return builder.build();
}

private AmdEvents buildEvents() {
AmdEvents.Builder builder = AmdEvents.builder();
if (null != onHuman) {
builder.setOnHuman(Commands.copy(onHuman));
}
if (null != onMachine) {
builder.setOnMachine(Commands.copy(onMachine));
}
if (null != onBeep) {
builder.setOnBeep(Commands.copy(onBeep));
}
if (null != onUnknown) {
builder.setOnUnknown(Commands.copy(onUnknown));
}
return builder.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.sinch.sdk.domains.voice.models.v2.helpers;

import com.sinch.sdk.domains.voice.models.v2.destination.CallDestination;
import com.sinch.sdk.domains.voice.models.v2.destination.CallOrigin;

/**
* Call endpoint built by {@link Destination#of(String)}
*
* <p>Valid as <code>to</code> ({@link CallDestination}) and <code>from</code> ({@link CallOrigin}).
*
* <p>A stream endpoint is only valid as <code>to</code>: the API rejects it as <code>from</code>.
*
* @since 2.4
*/
public interface BaseDestination extends CallOrigin, CallDestination {}
Loading
Loading