# Studio User Guide

Twilio Studio is a visual low-code/no-code tool that helps you design, deploy, and scale customer communications. With Studio, cross-functional teams can collaborate to quickly build and iterate on customer engagement workflows.

https://www.youtube.com/watch?v=14FXnUgrZ6w

## When to use Twilio Studio

Any builder can use Twilio Studio to quickly create and modify workflows with little to no code. Studio is designed for use by cross-functional teams and individuals who want to build communications tools. It provides a common framework for everyone to collaborate on a project using a single tool. Designers can make swift UX modifications, copywriters can implement their own changes to messaging, and developers can delegate work to others and focus on building more complex features (such as calling Twilio Functions).

### Studio features

Studio provides the following capabilities:

* Trigger Flows by using inbound messages, inbound voice calls, webhooks, or other Studio Flows
* Create, modify, and deploy Flows
* Import and export Flows
* Add and remove Transitions between widgets
* Manage widget settings with the Inspector Panel
* Define Transitions to advance users through Flows
* Create and pass variables
* View Executions (individual runs through Flows)
* Organize use cases and logic in separate Flows
* Use Subflows to break apart large, complex Flows

## Get started

If you're new to Twilio Studio, see the [Getting Started guide](/docs/studio/user-guide/get-started) to learn the core concepts and interface. After you become familiar with the Studio interface, return to this guide for more detailed information about specific widgets and actions you can perform with Studio.

## Data retention in Studio

Studio retains Execution and Step data for 30 days after an Execution *starts*. (Before October 1, 2021, we retained this data for 30 days after an Execution *ended*.) After the data expires, it's unavailable through the Studio REST API and Twilio Console.

> \[!NOTE]
>
> To access your Execution and Step logs past 30 days, use [Event Streams to subscribe to Studio Flow events](/docs/studio/user-guide#subscribing-to-flow-events-with-event-streams) and log them in your own systems.

Studio also deletes active Executions that are still awaiting a response from your end user after 30 days. If your end user responds after their Execution is deleted, they return to the top of the Flow and start another Execution.

> \[!WARNING]
>
> **Studio Step logs**, the [resource](/docs/studio/rest-api/v2/step) that represent the runtime processing of a widget, are best-effort delivery. This means that the network does *not* guarantee that this data will be delivered.

### Data retention for underlying products

Data relating to underlying products used through Studio, such as SMS or Voice call logs, is *not* automatically deleted at the same time as Execution data. Data generated by other products is retained in line with those products' data policies. Details of individual product data retention policies can be found in the specific product documentation, such as [SMS](/docs/messaging/quickstart) and [voice calls](/docs/voice/quickstart/server).

## PCI compliance in Studio

Studio does *not* support the [PCI Mode setting in Programmable Voice](https://www.twilio.com/console/voice/settings), however you can build PCI compliant Flows that process payments with Studio using the [Capture Payments widget](/docs/studio/widget-library/capture-payments).

> \[!WARNING]
>
> Studio does *not* redact `<Gather>` data collected by the [Gather Input widget](/docs/studio/widget-library/gather-input-call). To use `<Gather>` for collecting PCI sensitive data, use the [TwiML Redirect widget](/docs/studio/widget-library/twiml-redirect) to redirect the call away from Studio to an external URL that can collect `<Gather>` data in a compliant way.
>
> Learn more about [Twilio PCI Compliance](https://www.twilio.com/en-us/pci-compliance).

## Triggering Flows

You can trigger a Flow's start in the following ways:

* Incoming Message
* Incoming Call
* Incoming Conversation
* REST API (Inbound Request)
* Subflow

All five of these appear in the Trigger widget, and you can drag and drop from one or more to reflect your use case.

### Incoming Message

The Incoming Message trigger is invoked when your Twilio Phone Number (or other message-based channel) receives a new message from the Programmable Messaging API. The API then sends it to your Studio Flow Webhook URL:

`https://webhooks.twilio.com/v1/Accounts/{AccountSid}/Flows/{FlowSid}`

By connecting [Send Message](/docs/studio/widget-library/send-message) or [Send & Wait for Reply](/docs/studio/widget-library/send-wait-reply) widgets, you can respond to those incoming messages and carry on a conversation with the contact.

Studio maintains a unique session based on the Contact's identifier (usually a phone number). For a messaging Flow, Studio only allows a single active Execution per contact. All messages from the contact to that Flow during an active Execution will be handled by that same Execution.

### Incoming Call

The Incoming Call trigger is invoked when your Twilio Phone Number (or other voice-based channel) receives a new call and sends it to your Studio Flow Webhook URL:

`https://webhooks.twilio.com/v1/Accounts/{AccountSid}/Flows/{FlowSid}`

By connecting voice widgets, such as [Say/Play](/docs/studio/widget-library/sayplay) and [Gather Input](/docs/studio/widget-library/gather-input-call), you can guide the Contact through a series of interactive voice responses (IVR). You can also connect the contact to another party with [Connect Call To](/docs/studio/widget-library/connect-call) or route them to [Record Voicemail](/docs/studio/widget-library/record-voicemail).

By default, Studio maintains a unique voice session based on the combination of the Contact's identifier (usually a phone number) and the unique Call SID. This ensures every call is handled uniquely, [even if concurrent calls use the same Caller ID](/docs/studio/user-guide#handling-concurrent-calls-from-the-same-number-in-studio).

#### Handling concurrent calls from the same number in Studio

**The concurrent calls setting only applies to Executions created via the Incoming Call trigger type. Incoming Message and REST API triggered Executions are not affected.**

**Note**: This functionality changed on October 1, 2018. Flows created after this date handle concurrent calls from the same caller ID by default. For Flows created before that date, make the switch in the call trigger (see screenshot below).

By default, Studio Flows can handle inbound concurrent calls from the same number. The Send and Wait For Reply widget cannot be attached anywhere downstream of the Incoming Call trigger point. If multiple users call from the same number, Studio can't uniquely text back one user in an active execution and correctly identify a reply because callers all share the same number.

For certain specific use cases where callers to a Studio Flow will always have a unique visible caller ID, you can turn off the concurrent calls mode in the Advanced Features dropdown in the Trigger widget (see below). When turned off, you can add the Send and Wait for Reply widget to incoming call trigger connected Flows. **This is only recommended for advanced users who know that their Flow is triggered from visible unique caller IDs**.

![Flow configuration showing a sample Flow with trigger and gather steps.](https://docs-resources.prod.twilio.com/3be9ec2a6f1448a41b4068c067efefaf3386a0efc36a224d768cc0ba126132eb.png)

**Note**: Concurrent Calls doesn't apply to Executions triggered by an Incoming Message or the REST API. Those trigger types can only handle one concurrent Execution per Contact to ensure each session is uniquely tracked.

### Incoming Conversation

The Incoming Conversation trigger is invoked when a [Conversation invokes a Studio Webhook](/docs/conversations/api/conversation-scoped-webhook-resource) for a new message.

By connecting [Send Message](/docs/studio/widget-library/send-message) or [Send & Wait for Reply](/docs/studio/widget-library/send-wait-reply) widgets, you can respond to those incoming messages and carry on a conversation with the contact.

> \[!NOTE]
>
> Follow this guide to [connect Studio to Twilio Conversations](/docs/conversations/connect-to-studio).

Studio maintains a unique session based on the Conversation's identifier. For a Conversations Flow, Studio only allows a single active Execution per Conversation. All incoming messages from the Conversation to that Flow during an active Execution will be handled by that same Execution. Multiple participants of the same Conversation are, therefore, able to advance the same Execution.

> \[!WARNING]
>
> Sending media is **not** supported when using the Conversations integration.

### REST API trigger

Using the Studio REST API, you can trigger an *outbound* call or message to a Contact. Use this trigger type to initiate appointment reminders, surveys, or alerts from your own application. Add widgets to the REST API trigger to control the conversation just as you would for Incoming Message or Incoming Call.

For outbound voice calls, use the [Make Outgoing Call widget](/docs/studio/widget-library/make-outgoing-call) to initiate the call. For outbound messages, use either [Send Message](/docs/studio/widget-library/send-message) to fire and forget or [Send and Wait for Reply](/docs/studio/widget-library/send-wait-reply) to initiate a two-way conversation.

Studio maintains a unique session based on the Contact's identifier (usually a phone number). For a REST API Flow, Studio only allows a single active Execution per Contact. In the V2 version of the Studio API, if an Execution is already active for a Contact, the API will return a 409 error.

**Tip**: Be sure the `To` and `From` phone numbers are formatted as [E.164](/docs/glossary/what-e164) (for example, +1xxxxxxxxxx) to ensure correct session tracking.

See the [Studio REST API docs](/docs/studio/rest-api/v2) for more details.

### Subflow trigger

To invoke a Flow as a Subflow, connect widgets to the Subflow trigger. The Subflow trigger is invoked by the [Run Subflow widget](/docs/studio/widget-library/run-subflow).

See [Studio Subflows](/docs/studio/subflows) for more details.

## Working with variables

As your Flow executes, it saves the state in the Flow Context. Any data in the Flow Context can be accessed by your widgets as variables, either in configuration fields or in text areas as variable substitution.

Studio supports the [Liquid template language](/docs/studio/user-guide/liquid-template-language), which provides both output tags and logic tags. For example, to send a text message and include the contact's name, you could use variables like so:

`Hello {{flow.data.first_name}}`

More sophisticated logic is also supported. In this example, assume you want to check if you actually know the contact's name before trying to reference it:

![Twilio Studio logic for greeting message with conditional first name check.](https://docs-resources.prod.twilio.com/20d5256eb4a0db9d4bbf9a79752c49b69f6bc29334a7d9586605dbee7f6c2605.png)

```liquid
{% if flow.data.first_name %}
Hello {{flow.data.first_name}}
{% else %}
Hello friend
{% endif %}
```

**Note**: Liquid template variables can render up to 16 KB strings max.

### Context variables

The Context stores the following types of data:

* **Flow**: data intrinsic to the Flow, such as the phone number associated with it
* **Trigger**: data that gets set when a Flow is initiated, such as the initial incoming message, phone call, or REST API
* **Widgets**: data that each widget sets itself and adds to the context as it gets executed, such as the digits a user presses or the body of an incoming message
* **Contact**: data about the current contact engaging with your Flow, such as their phone number

#### Flow variables

| Description                                           | Liquid variable            |
| ----------------------------------------------------- | -------------------------- |
| The Flow's SID                                        | `{{flow.flow_sid}}`        |
| The contact's SID for the current Flow Execution      | `{{flow.sid}}`             |
| The Flow's address (for example, Twilio phone number) | `{{flow.channel.address}}` |

Example Flow variables in JSON format:

```json
{
    "flow": {
        "flow_sid": "FWxxxx",
        "channel": {
            "address": "+1xxxxxxxxxx"
        },
        "sid": "FNxxxxx"
    }
}
```

#### Contact variables

| Description                                            | Liquid variable               |
| ------------------------------------------------------ | ----------------------------- |
| The user's address (for example, handset phone number) | `{{contact.channel.address}}` |

#### Widget variables

After execution, many widgets publish data variables to the Execution context, and these variables may be referenced by subsequent widgets. For example, when the Send Message widget step completes, it stores the following variables:

| Description                          | Liquid variable                           |
| ------------------------------------ | ----------------------------------------- |
| SID                                  | `{{widgets.MY_WIDGET_NAME.message.Sid}}`  |
| To (User's Contact Address)          | `{{widgets.MY_WIDGET_NAME.message.To}}`   |
| From (Studio Flow's Contact Address) | `{{widgets.MY_WIDGET_NAME.message.From}}` |
| Body (Message content)               | `{{widgets.MY_WIDGET_NAME.message.Body}}` |

Note the casing of variable names, and remember that widget names must be unique, must start with a letter and cannot include spaces or additional periods. Any variables that come from an external source, such as a status callback or Twilio API call, are cased according to the relevant spec for that callback. For example, an incoming message will have a "Body" parameter, where we keep the capitalized "Body" like in the Twilio SMS API. Variables specific to the `flow`, `trigger`, and `widgets` context are lower cased.

If a Flow is triggered with an inbound request (REST API), variables can be passed in at request time.

## Subscribing to Flow events with Event Streams

You can use [Event Streams](/docs/events) to subscribe to [Execution and Step events](/docs/events/event-types/studio/flow) from your Flow. Options for streaming Studio data include both Kinesis and traditional webhooks.

Use the following events to log data, generate real-time reports, or trigger other actions:

* `com.twilio.studio.flow.execution.started`
* `com.twilio.studio.flow.execution.ended`
* `com.twilio.studio.flow.step.ended`

Try the [Event Streams Webhook Quickstart](/docs/events/webhook-quickstart).

## Testing draft Flows

You can test a draft of your Studio Flow without publishing changes. To do this, click the Trigger widget to open the Trigger widget Inspector Panel. Then, add your phone number to the Test Users section. You can add multiple phone numbers, separated by commas. Numbers should be in [E.164 format](/docs/glossary/what-e164).

When you use one of the numbers that you entered in the Test Users section to contact the Twilio Phone Number associated with this Studio Flow, the Flow runs through the latest draft Flow rather than the latest published Flow.

![Flow name and URL fields with test users input for IVR setup.](https://docs-resources.prod.twilio.com/0d7289b0ac195c07ac72486d4319078bacc3e20713bd8c102339d72dc6266e76.png)

When you are finished testing, you can click Publish to make your changes accessible to everyone.

### Renaming Flows

To change the name of your Flow, click on the Trigger widget. The right-side configuration panel includes a field for Flow Name. Enter a different name, and click Save to rename your Flow.

![Renaming Studio Flows.](https://docs-resources.prod.twilio.com/c9df6b65acf40c309fbc7d37228c0473159895c784a49a2f9516b87806a160c3.png)

### Duplicating Flows

To make a copy of an existing Flow, go to your [list of Flows](https://www.twilio.com/console/studio/flows/) and locate the one you'd like to copy. Click on **Duplicate Flow** and a new copy of the Flow will be created and automatically opened.

![Flow management table with options to delete or duplicate flows.](https://docs-resources.prod.twilio.com/fdc8b31fb86ad5bf2f61f3dc34fb69f6696bcde9f872de31288751ba268bb7ce.png)

### Deleting Flows

If you'd like to delete a Flow, go to your [list of Flows](https://www.twilio.com/console/studio/flows/) and locate the one you'd like to remove. Click on **Delete Flow** to remove the Flow.

![Delete Flow.](https://docs-resources.prod.twilio.com/7da02db529ea2e5ea9a816e937c00bf0b71bc85684da4e17e859d235c8e8e8ce.png)

> \[!CAUTION]
>
> Deleting a Flow is not recoverable. If you delete a Flow that is being used in production to handle calls or messages, you will need to rebuild the Flow to restore service.

## Importing and exporting Flows

Use this functionality to export flow definitions as JSON and import them to other Twilio accounts.

If you want to duplicate a Flow within your own account, it's best to use the [Duplicate Flow](/docs/studio/user-guide#duplicating-flows) method to create a copy of a Flow in the same account. Importing and exporting Flows is intended for exporting a Flow to store elsewhere, for source control or to move Flows between Twilio accounts.

## Import/Export via the REST API v2

[Try the Quickstart](https://www.twilio.com/docs/studio/rest-api/v2/studio-flows-api-quickstart)

Import and export functionality for Flows is also available via the [REST API v2](/docs/studio/rest-api/v2). Check out the [Flows API Quickstart](/docs/studio/rest-api/v2/studio-flows-api-quickstart) to learn how to export the Flow JSON and import it into a new Flow via the REST API and SDKs.

> \[!WARNING]
>
> Your Studio Flow definition may reference other Twilio resources (like phone numbers, Functions, and more). These references aren't automatically copied when the Flow is imported to another account, and you may need to make manual updates to your Flow to refresh references to those resources.

### Exporting Flow data

Click on the [Trigger widget](/docs/studio/widget-library/trigger-start) and select **Show Flow JSON**.

![Flow configuration with trigger options for incoming message, call, and REST API.](https://docs-resources.prod.twilio.com/1e97f2e53cecbc5bd3ade422a6e0946e2dbdfdc181dd6a4e4aefd5d768a5bf3d.png)

This will display the JSON data that defines your Flow. You can copy this data and store it elsewhere.

![Studio Flow JSON with trigger and transition details.](https://docs-resources.prod.twilio.com/719807b453f4ff812ab90e74d17a2646b97a3775874f9004d9f82a1168b08e21.png)

### Importing Flow data

Create a new Flow, and select **Import from JSON** from the list of templates. Then, click **Next**.

![New Flow window for importing JSON Flow definition with empty code editor.](https://docs-resources.prod.twilio.com/8b432b09c938b1bfcfe0d9704a8e84b465e56613305a6e185d1186aa973fc8a0.png)

In the next window, you can paste the Flow JSON and click Next. This will create the new Flow as defined in the JSON you pasted.

![Studio new flow with JSON importing.](https://docs-resources.prod.twilio.com/376117c744aea0ebe3e598bd90e69ed6bdb2904bd5f80ec35aa73ef6f4aa0e76.png)

## Next steps

After you've learned the Studio User Guide basics, explore these resources:

* Learn to troubleshoot Studio Flows with this [Troubleshooting guide](/docs/studio/user-guide/studio-troubleshooting).
* Review the built-in limits in the [Studio FAQ](/docs/studio/user-guide/studio-faq#what-limits-are-present-within-studio).
* Explore [Studio widgets](/docs/studio/widget-library) to add more functionality to your Flows.
* Learn about [Studio Subflows](/docs/studio/subflows) to organize complex logic.
* Review the [Studio REST API](/docs/studio/rest-api/v2) for programmatic Flow management.
