# Create conversations programmatically

Active creation lets you populate conversations through the Conversation Orchestrator API or [TwiML](/docs/glossary/what-is-twilio-markup-language-twiml).

For a comparison with passive ingestion and guidance on which mode to use, see [Ingestion modes](/docs/conversations/orchestrator/concepts/ingestion).

## Prerequisites

* [Create a Twilio account](https://www.twilio.com/try-twilio).
* [Buy a voice- and SMS-enabled phone number](https://1console.twilio.com/phone-numbers/search).
* [Store your Twilio credentials in environment variables](/docs/usage/secure-credentials).
* [Create a memory store](/docs/conversations/orchestrator/quickstart#create-a-memory-store-and-conversation-configuration).

## Create a conversation configuration

Send a `POST` request to the Configurations endpoint. Omit `captureRules` and use `GROUP_BY_PROFILE` so that conversations follow the same customer across channels and devices:

Create a conversation configuration for active creation

```js
// Download the helper library from https://www.twilio.com/docs/node/install
const twilio = require("twilio"); // Or, for ESM: import twilio from "twilio";

// Find your Account SID at twilio.com/console
// Provision API Keys at twilio.com/console/runtime/api-keys
// and set the environment variables. See http://twil.io/secure
// For local testing, you can use your Account SID and Auth token
const accountSid = process.env.TWILIO_ACCOUNT_SID;
const apiKey = process.env.TWILIO_API_KEY;
const apiSecret = process.env.TWILIO_API_SECRET;
const client = twilio(apiKey, apiSecret, { accountSid: accountSid });

async function createConfiguration() {
  const configuration = await client.conversations.v2.configurations.create({
    displayName: "active-conversations",
    description: "Configuration for API-created conversations",
    conversationGroupingType: "GROUP_BY_PROFILE",
    memoryStoreId: "YOUR_MEMORY_STORE_ID",
    channelSettings: {
      SMS: {
        statusTimeouts: {
          inactive: 30,
          closed: 1440,
        },
      },
    },
  });

  console.log(configuration.statusUrl);
}

createConfiguration();
```

```python
# Download the helper library from https://www.twilio.com/docs/python/install
import os
from twilio.rest import Client
from twilio.rest.conversations.v2 import ConfigurationList

# Find your Account SID at twilio.com/console
# Provision API Keys at twilio.com/console/runtime/api-keys
# and set the environment variables. See http://twil.io/secure
# For local testing, you can use your Account SID and Auth token
api_key = os.environ["TWILIO_API_KEY"]
api_secret = os.environ["TWILIO_API_SECRET"]
account_sid = os.environ["TWILIO_ACCOUNT_SID"]
client = Client(api_key, api_secret, account_sid)

configuration = client.conversations.v2.configurations.create(
    create_configuration_request=ConfigurationList.CreateConfigurationRequest(
        {
            "displayName": "active-conversations",
            "description": "Configuration for API-created conversations",
            "conversationGroupingType": "GROUP_BY_PROFILE",
            "memoryStoreId": "YOUR_MEMORY_STORE_ID",
            "channelSettings": {
                "SMS": ConfigurationList.CreateConfigurationRequestChannelSettingsValue(
                    {
                        "statusTimeouts": ConfigurationList.CreateConfigurationRequestChannelSettingsValueStatusTimeouts(
                            {"inactive": 30, "closed": 1440}
                        )
                    }
                )
            },
        }
    )
)

print(configuration.status_url)
```

```csharp
// Install the C# / .NET helper library from twilio.com/docs/csharp/install

using System;
using Twilio;
using Twilio.Rest.Conversations.V2;
using System.Threading.Tasks;
using System.Collections.Generic;

class Program {
    public static async Task Main(string[] args) {
        // Find your Account SID at twilio.com/console
        // Provision API Keys at twilio.com/console/runtime/api-keys
        // and set the environment variables. See http://twil.io/secure
        // For local testing, you can use your Account SID and Auth token
        string apiKey = Environment.GetEnvironmentVariable("TWILIO_API_KEY");
        string apiSecret = Environment.GetEnvironmentVariable("TWILIO_API_SECRET");
        string accountSid = Environment.GetEnvironmentVariable("TWILIO_ACCOUNT_SID");

        TwilioClient.Init(apiKey, apiSecret, accountSid);

        var configuration = await ConfigurationResource.CreateAsync(new CreateConfigurationOptions() {
            CreateConfigurationRequest =
                new ConfigurationResource.CreateConfigurationRequest.Builder()
                    .WithDisplayName("active-conversations")
                    .WithDescription("Configuration for API-created conversations")
                    .WithConversationGroupingType("GROUP_BY_PROFILE")
                    .WithMemoryStoreId("YOUR_MEMORY_STORE_ID")
                    .WithChannelSettings(new Dictionary<
                                         string,
                                         ConfigurationResource
                                             .CreateConfigurationRequestChannelSettingsValue>() {
                        { "SMS",
                          new ConfigurationResource.CreateConfigurationRequestChannelSettingsValue
                              .Builder()
                              .WithStatusTimeouts(
                                  new ConfigurationResource
                                      .CreateConfigurationRequestChannelSettingsValueStatusTimeouts
                                      .Builder()
                                      .WithInactive(30)
                                      .WithClosed(1440)
                                      .Build())
                              .Build() }
                    })
                    .Build()
        });

        Console.WriteLine(configuration.StatusUrl);
    }
}
```

```java
// Install the Java helper library from twilio.com/docs/java/install

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import com.twilio.Twilio;
import com.twilio.rest.conversations.v2.Configuration;

public class Example {
    // Find your Account SID at twilio.com/console
    // Provision API Keys at twilio.com/console/runtime/api-keys
    // and set the environment variables. See http://twil.io/secure
    // For local testing, you can use your Account SID and Auth token
    public static final String API_KEY = System.getenv("TWILIO_API_KEY");
    public static final String API_SECRET = System.getenv("TWILIO_API_SECRET");
    public static final String ACCOUNT_SID = System.getenv("TWILIO_ACCOUNT_SID");

    public static void main(String[] args) {
        Twilio.init(API_KEY, API_SECRET, ACCOUNT_SID);

        Configuration.CreateConfigurationRequest createConfigurationRequest =
            Configuration.CreateConfigurationRequest
                .builder("active-conversations",
                    "Configuration for API-created conversations",
                    Configuration.ConversationGroupingType.GROUP_BY_PROFILE,
                    "YOUR_MEMORY_STORE_ID")
                .channelSettings(new HashMap<String, Map<String, Object>>() {
                    {
                        put("SMS", new HashMap<String, Map<String, Object>>() {
                            {
                                put("statusTimeouts", new HashMap<String, Object>() {
                                    {
                                        put("inactive", 30);
                                        put("closed", 1440);
                                    }
                                });
                            }
                        });
                    }
                })
                .build();

        Configuration.CreateConfigurationResponse response =
            Configuration.creator().setCreateConfigurationRequest(createConfigurationRequest).create();

        System.out.println(response.getStatusUrl());
    }
}
```

```ruby
# Download the helper library from https://www.twilio.com/docs/ruby/install
require 'twilio-ruby'

# Find your Account SID at twilio.com/console
# Provision API Keys at twilio.com/console/runtime/api-keys
# and set the environment variables. See http://twil.io/secure
# For local testing, you can use your Account SID and Auth token
api_key = ENV['TWILIO_API_KEY']
api_secret = ENV['TWILIO_API_SECRET']
account_sid = ENV['TWILIO_ACCOUNT_SID']
@client = Twilio::REST::Client.new(api_key, api_secret, account_sid)

configuration = @client
                .conversations
                .v2
                .configurations
                .create(
                  create_configuration_request: {
                    'displayName' => 'active-conversations',
                    'description' => 'Configuration for API-created conversations',
                    'conversationGroupingType' => 'GROUP_BY_PROFILE',
                    'memoryStoreId' => 'YOUR_MEMORY_STORE_ID',
                    'channelSettings' => {
                      'SMS' => {
                        'statusTimeouts' => {
                          'inactive' => 30,
                          'closed' => 1440
                        }
                      }
                    }
                  }
                )

puts configuration.status_url
```

```bash
CREATE_CONFIGURATION_REQUEST_OBJ=$(cat << EOF
{
  "displayName": "active-conversations",
  "description": "Configuration for API-created conversations",
  "conversationGroupingType": "GROUP_BY_PROFILE",
  "memoryStoreId": "YOUR_MEMORY_STORE_ID",
  "channelSettings": {
    "SMS": {
      "statusTimeouts": {
        "inactive": 30,
        "closed": 1440
      }
    }
  }
}
EOF
)
curl -X POST "https://conversations.twilio.com/v2/ControlPlane/Configurations" \
--json "$CREATE_CONFIGURATION_REQUEST_OBJ" \
-u $TWILIO_API_KEY:$TWILIO_API_SECRET
```

Configuration creation is asynchronous. Poll the returned `statusUrl` until `status` is `COMPLETED`.

## Create a conversation with participants

Send a `POST` request to the Conversations endpoint with the participants you want to include. Always set the participant `type` explicitly so that [profile resolution](/docs/conversations/orchestrator/concepts/profiles) runs against the correct address.

Create a conversation with participants

```js
// Download the helper library from https://www.twilio.com/docs/node/install
const twilio = require("twilio"); // Or, for ESM: import twilio from "twilio";

// Find your Account SID at twilio.com/console
// Provision API Keys at twilio.com/console/runtime/api-keys
// and set the environment variables. See http://twil.io/secure
// For local testing, you can use your Account SID and Auth token
const accountSid = process.env.TWILIO_ACCOUNT_SID;
const apiKey = process.env.TWILIO_API_KEY;
const apiSecret = process.env.TWILIO_API_SECRET;
const client = twilio(apiKey, apiSecret, { accountSid: accountSid });

async function createConversationWithConfig() {
  const conversation = await client.conversations.v2.conversations.create({
    configurationId: "YOUR_CONFIGURATION_ID",
    name: "Support chat for Kiran",
    participants: [
      {
        name: "Kiran A.",
        type: "CUSTOMER",
        addresses: [
          {
            channel: "SMS",
            address: "+15551234567",
          },
        ],
      },
      {
        name: "Kai B.",
        type: "HUMAN_AGENT",
        addresses: [
          {
            channel: "SMS",
            address: "YOUR_TWILIO_PHONE_NUMBER",
          },
        ],
      },
    ],
  });

  console.log(conversation.id);
}

createConversationWithConfig();
```

```python
# Download the helper library from https://www.twilio.com/docs/python/install
import os
from twilio.rest import Client
from twilio.rest.conversations.v2 import ConversationList

# Find your Account SID at twilio.com/console
# Provision API Keys at twilio.com/console/runtime/api-keys
# and set the environment variables. See http://twil.io/secure
# For local testing, you can use your Account SID and Auth token
api_key = os.environ["TWILIO_API_KEY"]
api_secret = os.environ["TWILIO_API_SECRET"]
account_sid = os.environ["TWILIO_ACCOUNT_SID"]
client = Client(api_key, api_secret, account_sid)

conversation = client.conversations.v2.conversations.create(
    create_conversation_with_config_request=ConversationList.CreateConversationWithConfigRequest(
        {
            "configurationId": "YOUR_CONFIGURATION_ID",
            "name": "Support chat for Kiran",
            "participants": [
                ConversationList.CreateConversationWithConfigRequestParticipants(
                    {
                        "name": "Kiran A.",
                        "type": "CUSTOMER",
                        "addresses": [
                            ConversationList.CreateConversationWithConfigRequestParticipantsAddresses(
                                {"channel": "SMS", "address": "+15551234567"}
                            )
                        ],
                    }
                ),
                ConversationList.CreateConversationWithConfigRequestParticipants(
                    {
                        "name": "Kai B.",
                        "type": "HUMAN_AGENT",
                        "addresses": [
                            ConversationList.CreateConversationWithConfigRequestParticipantsAddresses(
                                {
                                    "channel": "SMS",
                                    "address": "YOUR_TWILIO_PHONE_NUMBER",
                                }
                            )
                        ],
                    }
                ),
            ],
        }
    )
)

print(conversation.id)
```

```csharp
// Install the C# / .NET helper library from twilio.com/docs/csharp/install

using System;
using Twilio;
using Twilio.Rest.Conversations.V2;
using System.Threading.Tasks;
using System.Collections.Generic;

class Program {
    public static async Task Main(string[] args) {
        // Find your Account SID at twilio.com/console
        // Provision API Keys at twilio.com/console/runtime/api-keys
        // and set the environment variables. See http://twil.io/secure
        // For local testing, you can use your Account SID and Auth token
        string apiKey = Environment.GetEnvironmentVariable("TWILIO_API_KEY");
        string apiSecret = Environment.GetEnvironmentVariable("TWILIO_API_SECRET");
        string accountSid = Environment.GetEnvironmentVariable("TWILIO_ACCOUNT_SID");

        TwilioClient.Init(apiKey, apiSecret, accountSid);

        var conversation = await ConversationResource.CreateAsync(new CreateConversationOptions() {
            CreateConversationWithConfigRequest =
                new ConversationResource.CreateConversationWithConfigRequest.Builder()
                    .WithConfigurationId("YOUR_CONFIGURATION_ID")
                    .WithName("Support chat for Kiran")
                    .WithParticipants(new List<
                                      ConversationResource
                                          .CreateConversationWithConfigRequestParticipants> {
                        new ConversationResource.CreateConversationWithConfigRequestParticipants
                            .Builder()
                            .WithName("Kiran A.")
                            .WithType("CUSTOMER")
                            .WithAddresses(
                                new List<
                                    ConversationResource
                                        .CreateConversationWithConfigRequestParticipantsAddresses> {
                                    new ConversationResource
                                        .CreateConversationWithConfigRequestParticipantsAddresses
                                        .Builder()
                                        .WithChannel("SMS")
                                        .WithAddress("+15551234567")
                                        .Build()
                                })
                            .Build(),
                        new ConversationResource.CreateConversationWithConfigRequestParticipants
                            .Builder()
                            .WithName("Kai B.")
                            .WithType("HUMAN_AGENT")
                            .WithAddresses(
                                new List<
                                    ConversationResource
                                        .CreateConversationWithConfigRequestParticipantsAddresses> {
                                    new ConversationResource
                                        .CreateConversationWithConfigRequestParticipantsAddresses
                                        .Builder()
                                        .WithChannel("SMS")
                                        .WithAddress("YOUR_TWILIO_PHONE_NUMBER")
                                        .Build()
                                })
                            .Build()
                    })
                    .Build()
        });

        Console.WriteLine(conversation.Id);
    }
}
```

```java
// Install the Java helper library from twilio.com/docs/java/install

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import com.twilio.Twilio;
import com.twilio.rest.conversations.v2.Conversation;

public class Example {
    // Find your Account SID at twilio.com/console
    // Provision API Keys at twilio.com/console/runtime/api-keys
    // and set the environment variables. See http://twil.io/secure
    // For local testing, you can use your Account SID and Auth token
    public static final String API_KEY = System.getenv("TWILIO_API_KEY");
    public static final String API_SECRET = System.getenv("TWILIO_API_SECRET");
    public static final String ACCOUNT_SID = System.getenv("TWILIO_ACCOUNT_SID");

    public static void main(String[] args) {
        Twilio.init(API_KEY, API_SECRET, ACCOUNT_SID);

        Conversation.CreateConversationWithConfigRequestParticipantsAddresses
            createConversationWithConfigRequestParticipantsAddresses1 =
            Conversation.CreateConversationWithConfigRequestParticipantsAddresses
                .builder(Conversation.Channel.SMS, "+15551234567")
                .build();

        Conversation.CreateConversationWithConfigRequestParticipants createConversationWithConfigRequestParticipants1 =
            Conversation.CreateConversationWithConfigRequestParticipants.builder()
                .name("Kiran A.")
                .type(Conversation.Type.CUSTOMER)
                .addresses(Arrays.asList(createConversationWithConfigRequestParticipantsAddresses1))
                .build();

        Conversation.CreateConversationWithConfigRequestParticipantsAddresses
            createConversationWithConfigRequestParticipantsAddresses1 =
            Conversation.CreateConversationWithConfigRequestParticipantsAddresses
                .builder(Conversation.Channel.SMS, "YOUR_TWILIO_PHONE_NUMBER")
                .build();

        Conversation.CreateConversationWithConfigRequestParticipants createConversationWithConfigRequestParticipants2 =
            Conversation.CreateConversationWithConfigRequestParticipants.builder()
                .name("Kai B.")
                .type(Conversation.Type.HUMAN_AGENT)
                .addresses(Arrays.asList(createConversationWithConfigRequestParticipantsAddresses1))
                .build();

        Conversation.CreateConversationWithConfigRequest createConversationWithConfigRequest =
            Conversation.CreateConversationWithConfigRequest.builder("YOUR_CONFIGURATION_ID")
                .name("Support chat for Kiran")
                .participants(Arrays.asList(
                    createConversationWithConfigRequestParticipants1, createConversationWithConfigRequestParticipants2))
                .build();

        Conversation.CreateConversationResponse response =
            Conversation.creator().setCreateConversationWithConfigRequest(createConversationWithConfigRequest).create();

        System.out.println(response.getId());
    }
}
```

```ruby
# Download the helper library from https://www.twilio.com/docs/ruby/install
require 'twilio-ruby'

# Find your Account SID at twilio.com/console
# Provision API Keys at twilio.com/console/runtime/api-keys
# and set the environment variables. See http://twil.io/secure
# For local testing, you can use your Account SID and Auth token
api_key = ENV['TWILIO_API_KEY']
api_secret = ENV['TWILIO_API_SECRET']
account_sid = ENV['TWILIO_ACCOUNT_SID']
@client = Twilio::REST::Client.new(api_key, api_secret, account_sid)

conversation = @client
               .conversations
               .v2
               .conversations
               .create(
                 create_conversation_with_config_request: {
                   'configurationId' => 'YOUR_CONFIGURATION_ID',
                   'name' => 'Support chat for Kiran',
                   'participants' => [
                     {
                       'name' => 'Kiran A.',
                       'type' => 'CUSTOMER',
                       'addresses' => [
                         {
                           'channel' => 'SMS',
                           'address' => '+15551234567'
                         }
                       ]
                     },
                     {
                       'name' => 'Kai B.',
                       'type' => 'HUMAN_AGENT',
                       'addresses' => [
                         {
                           'channel' => 'SMS',
                           'address' => 'YOUR_TWILIO_PHONE_NUMBER'
                         }
                       ]
                     }
                   ]
                 }
               )

puts conversation.id
```

```bash
CREATE_CONVERSATION_WITH_CONFIG_REQUEST_OBJ=$(cat << EOF
{
  "configurationId": "YOUR_CONFIGURATION_ID",
  "name": "Support chat for Kiran",
  "participants": [
    {
      "name": "Kiran A.",
      "type": "CUSTOMER",
      "addresses": [
        {
          "channel": "SMS",
          "address": "+15551234567"
        }
      ]
    },
    {
      "name": "Kai B.",
      "type": "HUMAN_AGENT",
      "addresses": [
        {
          "channel": "SMS",
          "address": "YOUR_TWILIO_PHONE_NUMBER"
        }
      ]
    }
  ]
}
EOF
)
curl -X POST "https://conversations.twilio.com/v2/Conversations" \
--json "$CREATE_CONVERSATION_WITH_CONFIG_REQUEST_OBJ" \
-u $TWILIO_API_KEY:$TWILIO_API_SECRET
```

To add a participant after a conversation is created, send a `POST` request to the [Participants](/docs/api/conversations/v2/Participant) endpoint on the conversation.

## Optional: Ingest voice calls with TwiML

For voice channels, you can use TwiML to ingest calls into conversations. Conversation Orchestrator adds the call (and its transcription) to the conversation you specify.

| TwiML verb            | Architecture                                        | Use case                  |
| --------------------- | --------------------------------------------------- | ------------------------- |
| `<ConversationRelay>` | Synchronous bidirectional STT + TTS over WebSocket. | AI voice agents.          |
| `<Transcription>`     | Asynchronous fork of voice media for transcription. | Human agent augmentation. |

### Route a call to a new conversation

Use `<ConversationRelay>` with `conversationConfiguration` to start a new conversation using the given configuration:

```xml
<Response>
  <Connect>
    <ConversationRelay
      url="wss://your-voice-adapter/ws"
      conversationConfiguration="YOUR_CONFIGURATION_ID" />
  </Connect>
</Response>
```

### Add transcription to an existing conversation

Use `<Transcription>` with `conversationId` to add the call to a conversation you already created:

```xml
<Response>
  <Start>
    <Transcription conversationId="YOUR_CONVERSATION_ID" />
  </Start>
  <Say>Welcome to support. How can I help you today?</Say>
</Response>
```

### Parameter precedence

Both `<ConversationRelay>` and `<Transcription>` accept `conversationConfiguration` and `conversationId`. If both are present, `conversationId` takes precedence and grouping rules are bypassed.

| Parameters provided                                   | Behavior                                                                     |
| ----------------------------------------------------- | ---------------------------------------------------------------------------- |
| `conversationConfiguration` only                      | Uses the configuration's grouping rules to find or create a conversation.    |
| `conversationId` only                                 | Routes directly to the specified conversation. Grouping rules are bypassed.  |
| Both `conversationConfiguration` and `conversationId` | `conversationId` takes precedence. The configuration is ignored for routing. |
| Neither                                               | No Conversation Orchestrator integration. Transcription isn't captured.      |

### Human handoff: Conversation Relay to Transcription

When handing off from an AI agent to a human agent on the same call, end the Conversation Relay session and start `<Transcription>` with the same `conversationId`:

```xml
<Response>
  <Start>
    <Transcription conversationId="YOUR_CONVERSATION_ID" />
  </Start>
  <Dial>+15551234567</Dial>
</Response>
```

Both the AI portion and the human portion live in one conversation.

> \[!WARNING]
>
> If your configuration has voice capture rules and you pass `conversationConfiguration` on a `<ConversationRelay>` verb for the same call, you pay for STT twice. Remove voice capture rules from your configuration when using active TwiML with Conversation Relay. See the [Voice channel documentation](/docs/conversations/orchestrator/concepts/channels#voice).

## Next steps

* [Ingestion modes](/docs/conversations/orchestrator/concepts/ingestion): Compare active and passive modes and learn about when to combine them.
* [Profiles](/docs/conversations/orchestrator/concepts/profiles): Learn how participant types and addresses resolve to profiles.
* [Conversation lifecycle](/docs/conversations/orchestrator/concepts/lifecycle): Control when conversations close.
* [Connect Conversations API (classic)](/docs/conversations/orchestrator/guides/classic-bridge): Bring existing Conversations API (classic) services into Conversation Orchestrator.
