# Studio Flow Definition

To represent the complex structure and requirements of a Studio Flow and its widget configurations, the Flow definition is expressed as a [JSON schema](/docs/studio/rest-api/v2/schemas). Thus, when creating or updating Flows via the REST API, the JSON sent in the `Definition` parameter must pass validation against that schema.

Below are sample Flow and widget definitions you can copy and paste into your application. Alternatively, use the [Studio editor in Twilio Console](https://www.twilio.com/console/studio) to automatically create valid definitions and export them from the API to save them locally or to add them to version control. Refer to the [JSON schemas](/docs/studio/rest-api/v2/schemas) for full details of widgets and properties.

## Standalone Definitions

The following sample definitions can be used as standalone starters for your application. Include the complete JSON as the `Definition` parameter in your [`POST` to the API](/docs/studio/rest-api/v2/flow#create-a-flow-resource).

```json title="Simple Flow Definition" description="Simple Flow for handling Incoming Message, Incoming Call and REST API triggered Executions"
{
  "states": [
      {
        "transitions": [
            {
                "event": "incomingMessage",
                "next": "send_message_1"
            },
            {
                "event": "incomingCall",
                "next": "say_play_1"
            },
            {
                "event": "incomingRequest",
                "next": "call_user_1"
            }
        ],
        "type": "trigger",
        "name": "Trigger",
        "properties": {
            "offset": {
                "y": 0,
                "x": 0
            }
        }
      },
      {
        "transitions": [
            {
                "event": "audioComplete"
            }
        ],
        "type": "say-play",
        "name": "say_play_1",
        "properties": {
            "say": "Hello world!",
            "loop": 1,
            "offset": {
                "y": 210,
                "x": 130
            }
        }
      },
      {
        "transitions": [
            {
                "event": "sent"
            },
            {
                "event": "failed"
            }
        ],
        "type": "send-message",
        "name": "send_message_1",
        "properties": {
            "body": "Hello world!",
            "from": "{{flow.channel.address}}",
            "service": "{{trigger.message.InstanceSid}}",
            "to": "{{contact.channel.address}}",
            "offset": {
                "y": 210,
                "x": -240
            },
            "channel": "{{trigger.message.ChannelSid}}"
        }
      },
      {
        "transitions": [
            {
                "event": "answered",
                "next": "say_play_1"
            },
            {
                "event": "busy"
            },
            {
                "event": "noAnswer"
            },
            {
                "event": "failed"
            }
        ],
        "type": "make-outgoing-call-v2",
        "name": "call_user_1",
        "properties": {
            "trim": "true",
            "machine_detection_silence_timeout": "5000",
            "from": "{{flow.channel.address}}",
            "recording_status_callback": "",
            "record": false,
            "machine_detection_speech_threshold": "2400",
            "to": "{{contact.channel.address}}",
            "detect_answering_machine": false,
            "sip_auth_username": "",
            "machine_detection": "Enable",
            "send_digits": "",
            "machine_detection_timeout": "30",
            "timeout": 60,
            "offset": {
                "y": 210,
                "x": 490
            },
            "machine_detection_speech_end_threshold": "1200",
            "sip_auth_password": "",
            "recording_channels": "mono"
        }
      }
  ],
  "initial_state": "Trigger",
  "flags": {
      "allow_concurrent_calls": true
  },
  "description": "A New Flow"
}
```

```json title="Trigger" description="Blank Flow with no widgets attached to the Trigger"
{
  "states": [
      {
        "transitions": [
            {
                "event": "incomingMessage",
                "next": null
            },
            {
                "event": "incomingCall",
                "next": null
            },
            {
                "event": "incomingRequest",
                "next": null
            }
        ],
        "type": "trigger",
        "name": "Trigger",
        "properties": {
            "offset": {
                "y": 0,
                "x": 0
            }
        }
      }
    ],
  "initial_state": "Trigger",
  "flags": {
      "allow_concurrent_calls": true
  },
  "description": "A New Flow"
}
```

## Widget Snippets

Widgets are defined as "states" that the Studio workflow engine transitions to in response to events. The following JSON snippets can be used to add individual widgets as `states` to an existing Flow definition.

Add each widget snippet as a new item in the `states` array:

```csharp
{
  "states": [
      // ADD WIDGET SNIPPETS HERE
    ],
  "initial_state": "Trigger",
  "flags": {
      "allow_concurrent_calls": true
  },
  "description": "A New Flow"
}

```

```json title="Add TwiML Redirect" description="Snippet of JSON to add a TwiML redirect"
{
  "transitions": [
      {
          "event": "return"
          "next": null
      },
      {
          "event": "timeout"
          "next": null
      },
      {
          "event": "fail"
          "next": null
      }
  ],
  "type": "add-twiml-redirect",
  "name": "redirect_1",
  "properties": {
      "url": "https://funny-name-1234.twil.io/",
      "method": "POST",
      "timeout": "14400",
      "offset": {
          "y": 0,
          "x": 0
      }
  }
}
```

```json title="Capture Payments" description="Snippet of JSON to capture payments"
{
  "transitions": [
      {
          "event": "success"
          "next": null
      },
      {
          "event": "maxFailedAttempts"
          "next": null
      },
      {
          "event": "providerError"
          "next": null
      },
      {
          "event": "payInterrupted"
          "next": null
      },
      {
          "event": "hangup"
          "next": null
      },
      {
          "event": "validationError"
          "next": null
      }
  ],
  "type": "capture-payments",
  "name": "pay_1",
  "properties": {
      "payment_token_type": "reusable",
      "currency": "usd",
      "postal_code": "true",
      "timeout": 5,
      "offset": {
          "y": 0,
          "x": 0
      },
      "valid_card_types": [],
      "security_code": true,
      "max_attempts": 2
  }
}
```

```json title="Connect Call To" description="Snippet of JSON to connect the caller to another number"
{
  "transitions": [
      {
          "event": "callCompleted"
          "next": null
      },
      {
          "event": "hangup"
          "next": null
      }
  ],
  "type": "connect-call-to",
  "name": "connect_call_1",
  "properties": {
      "noun": "number",
      "to": "+14155551212",
      "caller_id": "{{contact.channel.address}}",
      "record": true,
      "timeout": 30,
      "offset": {
          "y": 0,
          "x": 0
      }
  }
}
```

```json title="Enqueue Call" description="Snippet of JSON to enqueue the call"
{
  "transitions": [
      {
          "event": "callComplete"
          "next": null
      },
      {
          "event": "failedToEnqueue"
          "next": null
      },
      {
          "event": "callFailure"
          "next": null
      }
  ],
  "type": "enqueue-call",
  "name": "enqueue_1",
  "properties": {
      "workflow_sid": "WW1111111111111111111111",
      "offset": {
          "y": 0,
          "x": 0
      }
  }
}
```

```json title="Fork Stream" description="Snippet of JSON to fork the audio stream to another endpoint"
{
  "transitions": [
      {
          "event": "next",
          "next": null
      }
  ],
  "type": "fork-stream",
  "name": "stream_1",
  "properties": {
      "stream_action": "start",
      "stream_name": "stream",
      "stream_transport_type": "websocket",
      "stream_track": "inbound_track",
      "offset": {
          "y": 0,
          "x": 0
      },
      "stream_url": "wss://funny-name-1234.twil.io/"
  }
}
```

```json title="Gather Input On Call" description="Snippet of JSON to gather digits or speech input"
{
  "transitions": [
      {
          "event": "keypress",
          "next": null
      },
      {
          "event": "speech"
          "next": null
      },
      {
          "event": "timeout",
          "next": null
      }
  ],
  "type": "gather-input-on-call",
  "name": "gather_1",
  "properties": {
      "stop_gather": true,
      "gather_language": "en",
      "say": "Please press any key to continue.",
      "loop": 1,
      "timeout": 5,
      "offset": {
          "y": 0,
          "x": 0
      },
      "finish_on_key": "#"
  }
}
```

```json title="Make HTTP Request" description="Snippet of JSON to make an HTTP request to another API"
{
  "transitions": [
      {
          "event": "success",
          "next": null
      },
      {
          "event": "failed",
          "next": null
      }
  ],
  "type": "make-http-request",
  "name": "http_1",
  "properties": {
      "url": "https://funny-name-1234.twil.io/",
      "parameters": [
          {
              "key": "count",
              "value": "{{flow.variables.count}}"
          }
      ],
      "method": "POST",
      "content_type": "application/x-www-form-urlencoded;charset=utf-8",
      "offset": {
          "y": 0,
          "x": 0
      }
  }
}
```

```json title="Make Outgoing Call" description="Snippet of JSON to initiate an outbound call"
{
  "transitions": [
      {
          "event": "answered",
          "next": null
      },
      {
          "event": "busy",
          "next": null
      },
      {
          "event": "noAnswer",
          "next": null
      },
      {
          "event": "failed",
          "next": null
      }
  ],
  "type": "make-outgoing-call-v2",
  "name": "call_user_1",
  "properties": {
      "trim": "true",
      "machine_detection_silence_timeout": "5000",
      "from": "{{flow.channel.address}}",
      "recording_status_callback": "",
      "record": false,
      "machine_detection_speech_threshold": "2400",
      "to": "{{contact.channel.address}}",
      "detect_answering_machine": false,
      "sip_auth_username": "",
      "machine_detection": "Enable",
      "send_digits": "",
      "machine_detection_timeout": "30",
      "timeout": 60,
      "offset": {
          "y": 0,
          "x": 0
      },
      "machine_detection_speech_end_threshold": "1200",
      "sip_auth_password": "",
      "recording_channels": "mono"
  }
}
```

```json title="Record Call" description="Snippet of JSON to record an inbound call"
{
  "transitions": [
      {
          "event": "success",
          "next": null
      },
      {
          "event": "failed",
          "next": null
      }
  ],
  "type": "record-call",
  "name": "call_recording_1",
  "properties": {
      "trim": "do-not-trim",
      "offset": {
          "y": 0,
          "x": 0
      },
      "recording_status_callback_events": "completed",
      "recording_status_callback_method": "POST",
      "record_call": true,
      "recording_channels": "dual"
  }
}
```

```json title="Record Voicemail" description="Snippet of JSON to record voicemail from the caller"
{
  "transitions": [
      {
          "event": "recordingComplete",
          "next": null
      },
      {
          "event": "noAudio",
          "next": null
      },
      {
          "event": "hangup",
          "next": null
      }
  ],
  "type": "record-voicemail",
  "name": "record_voicemail_1",
  "properties": {
      "max_length": 3600,
      "timeout": 5,
      "offset": {
          "y": 0,
          "x": 0
      }
  }
}
```

```json title="Run Function" description="Snippet of JSON to run a Twilio Function"
{
  "transitions": [
      {
          "event": "success",
          "next": null
      },
      {
          "event": "fail"
      }
  ],
  "type": "run-function",
  "name": "function_1",
  "properties": {
      "url": "https://funny-name-1234.twil.io/",
      "parameters": [
          {
              "key": "foo",
              "value": "bar"
          }
      ],
      "offset": {
          "y": 0,
          "x": 0
      }
  }
}
```

```json title="Say/Play" description="Snippet of JSON to say a message to the caller"
{
  "transitions": [
      {
          "event": "audioComplete",
          "next": null
      }
  ],
  "type": "say-play",
  "name": "say_play_1",
  "properties": {
      "say": "This call is being recorded for quality assurance.",
      "loop": 1,
      "offset": {
          "y": 0,
          "x": 0
      }
  }
}
```

```json title="Send & Wait For Reply" description="Snippet of JSON to send a text message and wait for a reply"
{
  "transitions": [
      {
          "event": "incomingMessage",
          "next": null
      },
      {
          "event": "timeout",
          "next": null
      },
      {
          "event": "deliveryFailure",
          "next": null
      }
  ],
  "type": "send-and-wait-for-reply",
  "name": "send_and_reply_1",
  "properties": {
      "body": "Hello. Please reply.",
      "from": "{{flow.channel.address}}",
      "service": "{{trigger.message.InstanceSid}}",
      "timeout": 3600,
      "offset": {
          "y": 0,
          "x": 0
      },
      "channel": "{{trigger.message.ChannelSid}}"
  }
}
```

```json title="Send Message" description="Snippet of JSON to send a text message"
{
  "transitions": [
      {
          "event": "sent",
          "next": null
      },
      {
          "event": "failed",
          "next": null
      }
  ],
  "type": "send-message",
  "name": "send_message_1",
  "properties": {
      "body": "Hello world!",
      "from": "{{flow.channel.address}}",
      "service": "{{trigger.message.InstanceSid}}",
      "to": "{{contact.channel.address}}",
      "offset": {
          "y": 0,
          "x": 0
      },
      "channel": "{{trigger.message.ChannelSid}}"
  }
}
```

```json title="Send to Flex" description="Snippet of JSON to route the contact to a Flex agent"
{
  "transitions": [
      {
          "event": "callComplete",
          "next": null
      },
      {
          "event": "failedToEnqueue",
          "next": null
      },
      {
          "event": "callFailure",
          "next": null
      }
  ],
  "type": "send-to-flex",
  "name": "send_to_flex_1",
  "properties": {
      "workflow": "WW11111111111111111111111111111111",
      "channel": "TC11111111111111111111111111111111",
      "offset": {
          "y": 0,
          "x": 0
      }
  }
}
```

```json title="Set Variables" description="Snippet of JSON to set Execution-level variables"
{
  "transitions": [
      {
          "event": "next",
          "next": null
      }
  ],
  "type": "set-variables",
  "name": "set_variables_1",
  "properties": {
      "variables": [
          {
              "index": "0",
              "key": "count",
              "value": "{% if flow.variables.count %}\n  {{flow.variables.count | plus: 1}}\n{% else %}\n  1\n{% endif %}"
          }
      ],
      "offset": {
          "y": 0,
          "x": 0
      }
  }
}
```

```json title="Split Based On" description="Snippet of JSON to add branching logic"
{
  "transitions": [
      {
          "event": "noMatch",
          "next": null
      },
      {
          "conditions": [
              {
                  "type": "equal_to",
                  "friendly_name": "If value equal_to 1",
                  "arguments": [
                      "{{widgets.gather_1.Digits}}"
                  ],
                  "value": "1"
              }
          ],
          "event": "match",
          "next": null
      },
      {
          "conditions": [
              {
                  "type": "equal_to",
                  "friendly_name": "If value equal_to 2",
                  "arguments": [
                      "{{widgets.gather_1.Digits}}"
                  ],
                  "value": "2"
              }
          ],
          "event": "match",
          "next": null
      }
  ],
  "type": "split-based-on",
  "name": "split_1",
  "properties": {
      "input": "{{widgets.gather_1.Digits}}",
      "offset": {
          "y": 0,
          "x": 0
      }
  }
}
```
