# Voice API v2

# Core Concepts

The Voice API enables embedding voice calling into applications for virtually limitless use cases. From **number masking** for privacy, automated **appointment reminders**, and **outreach campaigns** with answering machine detection, to **bridging calls** between PSTN and SIP endpoints, the API offers the flexibility and control needed for modern communications.

## Call Model

{% table %}

- Concept 
- Description

---

- **Session**
- A session initiates as soon as the first call is created. It serves as a container for all related calls and their connections, maintaining context and state throughout the interaction. The session persists until all associated calls are terminated.

---

- **Call**
- A single participant's connection in a session (e.g., caller or callee).
- **Inbound Call:** A call initiated from an external source (PSTN, SIP, etc.) into the service.
- **Outbound Call:** A call initiated by the service to an external destination.

---

- **Bridge**
- A mechanism to connect one or more calls, so that participants can communicate with each other.
![session bridge chart](/images/voicev2/voicev2-session-chart.png)

{% /table %}

### Initiating Calls

There are a few ways to create a call:

1. **Inbound Calls:** Triggered by incoming traffic from PSTN, SIP, or other sources.
2. **Outbound Calls (via Dial):** Initiated from within an existing call session using the `dial` command.
3. **Outbound Calls (via API):** Created directly by sending an API request to the Voice API.
4. **Call Queuing:** Calls can be queued and processed based on parameters such as priority, time, or custom logic.

### Call Pacing (Batch)

The new Voice API v2 supports Call pacing via batch calling to efficiently manage high volumes of outbound calls. This is especially useful for scenarios like appointment reminders, notifications, or campaigns where customers need to reach multiple recipients in a controlled and scalable way.

#### How To Initiate Batch Calls

To initiate several calls in a batch, send a POST request to the `/v2/projects/{projectId}/calls` endpoint. The request body contains a SVAML payload describing the call flow and a list of parameters for each call in the batch. The API queues and triggers calls according to the provided configuration, such as maximum calls per second (`maxCps`) and time-to-live (`ttlSeconds`).

```json
{
  "commands": [
    {
      "command": "dial",
      "callName": "batch-notification",
      "from": { 
        "type": "PHONE",
        "phone": { "number": "@from" } 
      },
      "to": { 
        "type": "PHONE",
        "phone": { "number": "@to" } 
      },
      "events": {
        "onAnswer": [
          {
            "command": "messages",
            "messages": [
              {
                "type": "SAY",
                "say": {
                  "text": "Hello @name, you have an appointment tomorrow at 10 AM.",
                  "voiceName": "Emma"
                }
              }
            ]
          }
        ]
      }
    }
  ],
  "parameters": [
    { "from": "+46712345678", "to": "+46787654321", "name": "Alice" },
    { "from": "+46712345678", "to": "+46781234567", "name": "Bob" }
  ],
  "batchOptions": {
    "maxCps": 10,
    "ttlSeconds": 60
  }
}
```

- **commands:** SVAML commands describing the call flow for each call in the batch. Parameter placeholders start with `@` and can be used as variables for each call. They can be used alone as in `@from` or in combination with text in a say message (e.g., `Hello @name, your appointment is at @time`).
- **parameters:** An array of objects, each specifying the values for the placeholders in the commands. Each object represents a call to be queued and triggered.
- **batchOptions:** Controls how the batch is processed:
  - `maxCps`: Maximum number of calls per second to be initiated.
  - `ttlSeconds`: Time-to-live for the batch in seconds; calls not initiated within this time window will be skipped.

The API responds with metadata for the queued calls:

- **sessionIds:** Each call in the batch is assigned a unique sessionId, which can be used to track the state and progress of individual calls.
- **batchId:** The batchId identifies the entire batch operation, allowing batch state and summaries to be queried, or the batch to be managed as a whole (e.g., cancel unprocessed calls).
- **Other properties:** The response may also include other Ids, timestamps, and state related information.


#### How Calls Are Triggered

When a batch request is submitted:
1. The API validates the SVAML commands and parameters.
2. Calls are queued and triggered according to `maxCps` and `ttlSeconds` settings.
3. Each call is processed independently, using the provided parameters to personalize the call flow.
4. The API tracks the state of each call (e.g., `QUEUED`, `INITIATED`, `IN_PROGRESS`, `COMPLETED`).
5. Batch progress can be monitored and summaries can be retrieved via the [GET] `/v2/projects/{projectId}/batches/{batchId}` endpoint.

## Call Lifecycle

A call progresses through several states from creation to completion.

**Call States**

{% table %}

- State
- Description

---

- `QUEUED` 
- Call is waiting to be processed.

---

- `INITIATED`
- Call setup is in progress (ringing).

---

- `IN_PROGRESS`
- Call is answered and active.

---

- `COMPLETED`
- Call ended normally.

---

- `REJECTED`
- Recipient rejected the call.

---

- `NO_ANSWER`
- Recipient did not answer.

---

- `CANCEL`
- Call was cancelled before being answered.

---

- `BUSY`
- Recipient was busy.

---

- `FAILED`
- Call could not be set up.

{% /table %}

**Call Transitions**

![transition states flowchart](/images/voicev2/voicev2-transition-states.png)

This diagram shows how a call moves between states. Typically, most calls start at `QUEUED`, progress to `INITIATED`, and either get answered (`IN_PROGRESS`) or end in a final state (`COMPLETED`, `NO_ANSWER`, etc.).

## Handling Events with Webhooks

When a specific event occurs (for example, a call is answered), the Voice API v2 sends an HTTP request (usually POST) to the webhook URL configured in service settings. The request contains details about the event, such as call identifiers and timestamps. The application can then respond with [SVAML commands](/docs/voice-2.0/api-reference/svaml) to control the ongoing call or perform other actions.

### Typical Request-Response Cycle

1. An event (e.g., call.answered) occurs in the Voice API.
2. The API sends a POST request to the configured webhook endpoint with event details.
3. The server processes the event and responds with SVAML commands (e.g., play a message, gather input).
4. The API executes the commands and updates the call state.

```mermaid
sequenceDiagram
  participant VoiceAPI as Voice API
  participant Backend as Application Backend
  VoiceAPI ->> Backend: POST webhook (event details)
  Backend ->> VoiceAPI: SVAML commands (response)
  VoiceAPI ->> Backend: Further webhooks (if needed)
  Backend ->> VoiceAPI: Additional SVAML commands
```

Webhook endpoints must respond within 5 seconds. If the endpoint fails or times out and a `fallbackUrl` is configured, the request is re-sent to the fallback URL. See *Timeouts and failover* in the **Webhooks** section for the algorithm and its effect on delivery guarantees.

### Webhooks vs. Events

- **Webhooks:** External HTTP notifications sent to the application when specific events occur.
- **Events:** Internal API notifications about call state changes; can be exposed via webhooks for external handling or internally by predefining event handlers in SVAML commands.

### Event Naming Convention

Events are named using the pattern `resource.command.event`.

For example:
- `call.answered`: Indicates that a call was answered.
- `call.amd.machine`: Indicates that the Answering Machine Detection (AMD) on a call detected a machine.

This convention helps clearly identify the resource, the command involved, and the specific event that occurred.

#### Common Webhook Events

- `call.incoming`: Triggered when a call is received from PSTN, SIP, etc.
- `call.answered`: Triggered when a call is answered.
- `call.hangup`: Triggered when a call is hung up.

### Precedence Rules

When handling events in call flows, the Voice API applies the following precedence rules to determine which SVAML commands are executed:

- **Command-Level Event Handlers:**  
  If an event handler (e.g., `on_answer`, `on_machine`) is defined directly within a SVAML command, the commands specified in that handler are executed first for that event.

- **Service Configuration Fallback:**  
  If the event handler is not defined in the SVAML command, the API falls back to the event handler defined in the service configuration. This allows default behaviors for events to be set at the service level.

- **Execution Order:**  
  - Command-level event handlers always take priority over service-level handlers.
  - If neither is defined, the event is ignored and no commands are executed for that event.

**Best Practice:**  
Define event handlers in SVAML commands for custom, per-call logic. Use service configuration event handlers for default or global behaviors across all calls.


### Webhook Request Example

When a call is answered, the API sends a POST request to the configured webhook endpoint that includes the event type and the current call details.

The webhook endpoint should return a valid SVAML payload specifying which commands to execute on the call. For example, the response below synthesizes a welcome message and then ends the call.

```json
{
  "commands": [
    {
      "command": "messages",
      "messages": [
        {
          "type": "SAY",
          "say": {
            "text": "Welcome to our service!",
            "voiceName": "Emma"
          }
        }
      ],
      "events": {
        "onFinish": [
          {
            "command": "hangup"
          }
        ]
      }
    }
  ]
}
```

### Regions

The following table displays the servers available for each region.

| Region | Server |
| ------ | ------ |
| Global endpoint - Redirected by Sinch to the closest region. | `https://voice.api.sinch.com` |
| North America 1 - East | `https://us1.voice.api.sinch.com` |
| South America 1 - East | `https://br1.voice.api.sinch.com` |
| Europe 1 - Central | `https://eu1.voice.api.sinch.com` |
| Asia Pacific 1 - Southeast | `https://sg1.voice.api.sinch.com` |
| Australia & Oceania 1 - Southeast | `https://au1.voice.api.sinch.com` |

### Best Practices

- **Respond Quickly:** Webhook requests should be processed and responded to as quickly as possible to avoid call delays.
- **Idempotency:** A failed request is re-sent to the fallback URL, so the same event can arrive more than once. Make the handler idempotent and deduplicate on the `ce-id` and `ce-source` headers — see *Timeouts and failover* in the **Webhooks** section.
- **Logging:** Log incoming webhook requests and responses for troubleshooting and auditing.
- **Validation:** Validate incoming requests to ensure they are from the Voice API (see Security below).

### Security

To safeguard a webhook endpoint, verify that incoming requests are genuinely sent by the Voice API and have not been altered in transit. This prevents unauthorized access and mitigates risks such as man-in-the-middle attacks.

1. Each service has an identifier and a secret.
2. When a webhook arrives, use the secret to compute a signature over the canonical request string.
3. Compare the computed signature to the one in the request authorization header.
4. Only process the webhook if the signatures match.

For the exact `Authorization` header format, the canonical string that is signed, the signature algorithm and a worked example, see *Request signing* on the **Call webhook** operation in the **Webhooks** section.

Access to the webhook endpoint may also be restricted by IP address, and HTTPS can be used to encrypt traffic.


Make and receive voice calls with Sinch's RESTful Voice API interface.

Version: 2.0.58
License: Sinch License

## Servers

Endpoint which enables consuming the Voice API globally - Redirected by Sinch to the closest region.
```
https://voice.api.sinch.com
```

North America 1 - East
```
https://us1.voice.api.sinch.com
```

South America 1 - East
```
https://br1.voice.api.sinch.com
```

Europe 1 - Central
```
https://eu1.voice.api.sinch.com
```

Asia Pacific 1 - Southeast
```
https://sg1.voice.api.sinch.com
```

[object Object]
```
https://au1.voice.api.sinch.com
```

## Security

### BasicAuth

[object Object],[object Object],[object Object],[object Object],[object Object]

Type: http
Scheme: basic

### SinchOAuth2

[object Object],[object Object],[object Object],[object Object]

Type: oauth2
Token URL: https://auth.sinch.com/oauth2/token
Scopes:

## Download OpenAPI description

 - [Voice API v2](https://developers.sinch.com/_bundle/docs/voice-2.0/api-reference/voice.yaml)

## Calls

 - [GET /v2/projects/{projectId}/calls](https://developers.sinch.com/docs/voice-2.0/api-reference/voice/calls/listcalls.md): List and filter calls made with Sinch
 - [POST /v2/projects/{projectId}/calls](https://developers.sinch.com/docs/voice-2.0/api-reference/voice/calls/createcall.md): Create a new outbound call associated to the project's default service or to the service specified in the `serviceId` query parameter.
 - [GET /v2/projects/{projectId}/calls/{callId}](https://developers.sinch.com/docs/voice-2.0/api-reference/voice/calls/getcallbyid.md): Retrieve detailed information about a specific call using its unique identifier.
 - [PATCH /v2/projects/{projectId}/calls/{callId}](https://developers.sinch.com/docs/voice-2.0/api-reference/voice/calls/patchcallbyid.md): Interact with an ongoing call by submitting a set of SVAML commands. Use this to force disconnect, play messages, bridge with another call, or perform other call control actions.
 - [PATCH /v2/projects/{projectId}/sessions/{sessionId}/calls/{callName}](https://developers.sinch.com/docs/voice-2.0/api-reference/voice/calls/patchcallbysessionandname.md): Interact with an ongoing call identified by its session and call name by submitting a set of SVAML commands. Use this to force disconnect, play messages, bridge with another call, or perform other cal
## Sessions

 - [GET /v2/projects/{projectId}/sessions/{sessionId}](https://developers.sinch.com/docs/voice-2.0/api-reference/voice/sessions/getsessionbyid.md): Retrieve detailed information about a specific session, including all associated calls and their current states. Sessions represent the complete interaction lifecycle and can contain multiple related
## Batches

 - [Key Features](https://developers.sinch.com/docs/voice-2.0/api-reference/voice/batches/key-features.md): ### Key Features - **Rate limiting**: Control the maximum calls per second (CPS) to manage load and comply with carrier requirements - **TTL (Time-to-Live)**: Set a maximum time window for initiating
 - [DELETE /v2/projects/{projectId}/batches/{batchId}](https://developers.sinch.com/docs/voice-2.0/api-reference/voice/batches/stopbatchprocessing.md): Stop processing a batch of call sessions. This will prevent any queued calls in the batch from being initiated. Calls that are already in progress will not be affected and will continue until comple
 - [GET /v2/projects/{projectId}/batches/{batchId}](https://developers.sinch.com/docs/voice-2.0/api-reference/voice/batches/getbatchcallsummary.md): Retrieve a summary of a batch call operation, including statistics on completed, failed, in-progress, and queued calls. This provides an overview of the batch execution state and individual call sess
 - [GET /v2/projects/{projectId}/batches/{batchId}/details](https://developers.sinch.com/docs/voice-2.0/api-reference/voice/batches/getbatchdetails.md): Retrieve per-session details for a batch call operation, including the current state of each call session in the batch. Use this endpoint when individual session-level visibility is needed (for exampl
## Webhooks

 - [Request Format](https://developers.sinch.com/docs/voice-2.0/api-reference/voice/webhooks/request-format.md): ## Request Format Webhook requests conform to the [CloudEvents 1.0](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md) specification using **HTTP binary content mode**: - CloudEvent
 - [When webhooks are triggered](https://developers.sinch.com/docs/voice-2.0/api-reference/voice/webhooks/when-webhooks-are-triggered.md): ## When webhooks are triggered - **Incoming calls**: When a call arrives on a service configured with a webhook URL. Services using static SVAML behavior (`STATIC`) do not trigger this webhook. - **Ca
 - [Response](https://developers.sinch.com/docs/voice-2.0/api-reference/voice/webhooks/response.md): ## Response The endpoint must return HTTP `200` with a JSON body containing SVAML commands to execute next, or an empty `commands` array to take no action.
 - [Timeouts and failover](https://developers.sinch.com/docs/voice-2.0/api-reference/voice/webhooks/timeouts-and-failover.md): ## Timeouts and failover - Sinch enforces a **5-second response timeout**. Slow responses may affect call quality. - Webhook requests are **blocking**: execution of the call flow pauses until the endp
 - [What counts as a failure](https://developers.sinch.com/docs/voice-2.0/api-reference/voice/webhooks/what-counts-as-a-failure.md): ### What counts as a failure A delivery attempt has failed when: - The endpoint returns a non-successful status code. - The endpoint does not respond within the 5-second timeout. - Returned body does
 - [Failover algorithm](https://developers.sinch.com/docs/voice-2.0/api-reference/voice/webhooks/failover-algorithm.md): ### Failover algorithm This section is the authoritative description of how the webhook URL is selected. When a `fallbackUrl` is configured: 1. Requests are sent to the primary `url`. 2. If a request
 - [Delivery guarantees](https://developers.sinch.com/docs/voice-2.0/api-reference/voice/webhooks/delivery-guarantees.md): ### Delivery guarantees Because a failed request is re-sent to the fallback URL, the same event can be delivered more than once — for example when the primary endpoint received and processed the reque
 - [POST call.webhook](https://developers.sinch.com/docs/voice-2.0/api-reference/voice/webhooks/callwebhook.md): Receives webhook notifications for call events from the Voice Platform. ### Request signing Every webhook request is signed by the Voice Platform so that the receiving endpoint can verify that the req
## Services

 - [Default Services](https://developers.sinch.com/docs/voice-2.0/api-reference/voice/services/default-services.md): ### Default Services When a new project is created a default service is automatically generated under this project. A default cannot be deleted directly, in order to delete a default service you must
 - [Dashboard](https://developers.sinch.com/docs/voice-2.0/api-reference/voice/services/dashboard.md): ### Dashboard Voice services and their settings can be managed via the [Dashboard](https://dashboard.sinch.com/voice-v2/services).
 - [GET /v2/projects/{projectId}/services](https://developers.sinch.com/docs/voice-2.0/api-reference/voice/services/listservices.md): Retrieve a list of voice services in the specified project. Optionally: - Filter services by partial match on name or description (`filter`) - Return only the default service (`default=true`)
 - [POST /v2/projects/{projectId}/services](https://developers.sinch.com/docs/voice-2.0/api-reference/voice/services/createservice.md): Creates a new voice service in the specified project.
 - [GET /v2/projects/{projectId}/services/{serviceId}](https://developers.sinch.com/docs/voice-2.0/api-reference/voice/services/getservice.md): Retrieve the full details of a specific voice service by its `serviceId`.
 - [PATCH /v2/projects/{projectId}/services/{serviceId}](https://developers.sinch.com/docs/voice-2.0/api-reference/voice/services/updateservice.md): Updates an existing service resource with the provided properties. Only the fields included in the request body will be modified; omitted fields remain unchanged. To set a service as the default for t
 - [DELETE /v2/projects/{projectId}/services/{serviceId}](https://developers.sinch.com/docs/voice-2.0/api-reference/voice/services/deleteservice.md): Deletes a service permanently. **Important:** The default service cannot be deleted. To delete the current default service, a different service must first be designated as the default using the PATCH
## Payloads

 - [POST /v2/projects/{projectId}/svaml/describe](https://developers.sinch.com/docs/voice-2.0/api-reference/voice/payloads/describesvaml.md): This endpoint is useful for understanding the structure and flow of a SVAML payload without executing it. It provides a detailed description of the commands, events, and messages defined in the SVAML.
 - [POST /v2/projects/{projectId}/svaml/validate](https://developers.sinch.com/docs/voice-2.0/api-reference/voice/payloads/validatesvaml.md): This endpoint checks the structure and content of the SVAML commands to ensure they conform to the expected schema and rules. It can operate in different validation modes, such as strict or lenient, d
