---
title: "Create a customer flow"
method: POST
path: "/v1/customer-flow"
tags: ["Customer Flow"]
---

# Create a customer flow

`POST /v1/customer-flow`

Creates a customer flow. A SCRIPTED flow carries a step graph and gets one way of running it per path through the graph; an IMPROV flow carries the briefs you send. Customer flows replace the older simulation scenarios, so build a flow for anything new.

## Request body

- union — Input for creating a customer flow. SCRIPTED writes the conversation out as a graph of turns; IMPROV gives the simulated customer a brief and lets it improvise.
  - CreateScriptedCustomerFlowInput
    - `type` 'SCRIPTED', required
    - `title` string, required
    - `description` string, nullable
    - `agentExpectations` FlowExpectationInput[]
      - `prompt` string, required — What the agent under test is graded against.
    - `agentIds` string[] — Agents this flow exercises. Optional for scripted flows.
    - `branchingMode` 'DETERMINISTIC' | 'ADAPTIVE' — How a run walks the graph. DETERMINISTIC ("Simulate every path" in the app) places one call per variant, each following its path exactly whatever the agent says. ADAPTIVE ("Adapt to your agent") collapses the paths into one call PER PERSONA, on which the simulated customer picks a branch from what the agent actually said. Both modes speak the exact authored lines, and neither changes how metrics or expectations grade. (DETERMINISTIC is the default.)
    - `graph` FlowStep[], required — The conversation, as a graph of steps. At most 100 steps across at most 25 paths. The variants come from the graph: one per path, so they are not sent here.
      - union — One step in a scripted flow's conversation. `nodeId` is the identity contract: include it to update the existing step, omit it to create a new one. A step continues into `steps` (more than one child is a branch point) and/or `mergeIntoNodeIds`, which names steps elsewhere in the same request that this step rejoins. Branches that come back together are represented that way rather than by repeating the shared step, so reading a flow, editing it and writing it back preserves it exactly. A merge target is named by its `nodeId` when it already exists, or by `ref` when it is being created in the same request. `ref` is a label you choose, it is request-local, and it is never stored or returned. Put the shared step inline under the first branch that reaches it and point the others at it: a top-level step is a root wired straight from the start of the flow, so a merge target parked there would also be reachable directly. The two DTMF types are mirror images and both require `dtmfDigits`. `CUSTOMER_DTMF` is keys the simulated caller presses while navigating your agent. `AGENT_DTMF` is keys your agent under test is expected to press while navigating a menu the simulation is playing, so its digits are an assertion the run is graded against rather than an instruction, and it counts as an agent turn for role alternation.
        - object
          - `nodeId` string, uuid
          - `ref` string
          - `steps` FlowStep[]
          - `mergeIntoNodeIds` string[]
          - `type` 'AGENT_TURN', required
          - `content` string, nullable
        - object
          - `nodeId` string, uuid
          - `ref` string
          - `steps` FlowStep[]
          - `mergeIntoNodeIds` string[]
          - `type` 'CUSTOMER_TURN', required
          - `content` string, nullable
        - object
          - `nodeId` string, uuid
          - `ref` string
          - `steps` FlowStep[]
          - `mergeIntoNodeIds` string[]
          - `type` 'CUSTOMER_FIRST_MESSAGE', required
          - `content` string, nullable
        - object
          - `nodeId` string, uuid
          - `ref` string
          - `steps` FlowStep[]
          - `mergeIntoNodeIds` string[]
          - `type` 'CUSTOMER_SILENCE', required
          - `silenceDurationSeconds` integer, nullable
        - object
          - `nodeId` string, uuid
          - `ref` string
          - `steps` FlowStep[]
          - `mergeIntoNodeIds` string[]
          - `type` 'CUSTOMER_DTMF', required
          - `dtmfDigits` string, nullable
        - object
          - `nodeId` string, uuid
          - `ref` string
          - `steps` FlowStep[]
          - `mergeIntoNodeIds` string[]
          - `type` 'AGENT_DTMF', required
          - `dtmfDigits` string, nullable
        - object
          - `nodeId` string, uuid
          - `ref` string
          - `steps` FlowStep[]
          - `mergeIntoNodeIds` string[]
          - `type` 'VOICEMAIL', required
        - object
          - `nodeId` string, uuid
          - `ref` string
          - `steps` FlowStep[]
          - `mergeIntoNodeIds` string[]
          - `type` 'SCENARIO_LINK', required
          - `linkedCustomerFlowId` string, uuid, nullable
          - `linkedCustomerFlowVariantId` string, uuid, nullable
  - CreateImprovCustomerFlowInput
    - `type` 'IMPROV', required
    - `title` string, required
    - `description` string, nullable
    - `agentExpectations` FlowExpectationInput[]
      - `prompt` string, required — What the agent under test is graded against.
    - `agentIds` string[], required — Agents this flow exercises. At least one is required for improv flows.
    - `happyPath` FlowHappyPathInput, required — The way this flow is meant to go.
      - `title` string, required
      - `environmentId` string, uuid, required — The conditions this flow runs under. Edge cases inherit them unless they name their own.
      - `prompt` string, nullable
      - `precededByCustomerFlowId` string, uuid, nullable
      - `precededByCustomerFlowVariantId` string, uuid, nullable
      - `personaOverrideId` string, uuid, required — The persona this flow runs as. Edge cases inherit it unless they name their own.
    - `edgeCases` FlowEdgeCaseInput[] — Other ways of running it, each inheriting from the happy path what it does not name.
      - `title` string, required
      - `environmentId` string, uuid, nullable
      - `prompt` string, nullable
      - `precededByCustomerFlowId` string, uuid, nullable
      - `precededByCustomerFlowVariantId` string, uuid, nullable
      - `personaOverrideId` string, uuid, nullable — The persona this runs as. Omit to inherit the happy path's.

## Response `201`

The created customer flow

- object
  - `data` union, required — The conversation a simulated customer has with the agent under test.
    - ScriptedCustomerFlow — A flow whose conversation is written out as a graph of turns.
      - `id` string, uuid, required
      - `title` string, required
      - `description` string, nullable
      - `source` 'SYSTEM' | 'CUSTOM', required
      - `createdAt` string, required — Creation timestamp in ISO 8601 format
      - `updatedAt` string, required — Last update timestamp in ISO 8601 format
      - `agents` object[], required — The agents this flow is run against.
        - `id` string, uuid, required — Unique identifier of the agent
        - `name` string, required — Name of the agent
        - `description` string, nullable, required — Description of the agent
        - `customId` string, nullable, required — Custom identifier for the agent
        - `createdAt` string, required — Creation timestamp in ISO 8601 format
        - `updatedAt` string, required — Last update timestamp in ISO 8601 format
      - `agentExpectations` FlowExpectation[], required
        - `id` string, uuid, required
        - `prompt` string, required — What the agent under test is graded against.
      - `type` 'SCRIPTED', required
      - `branchingMode` 'DETERMINISTIC' | 'ADAPTIVE', required — How a run walks the graph. DETERMINISTIC ("Simulate every path" in the app) places one call per variant, each following its path exactly whatever the agent says. ADAPTIVE ("Adapt to your agent") collapses the paths into one call PER PERSONA, on which the simulated customer picks a branch from what the agent actually said. Both modes speak the exact authored lines, and neither changes how metrics or expectations grade.
      - `graph` FlowStep[] — The conversation, as a graph of steps. Present on a single flow; omitted from the list, where reading it would mean walking the project step graph once per row.
        - union — One step in a scripted flow's conversation. `nodeId` is the identity contract: include it to update the existing step, omit it to create a new one. A step continues into `steps` (more than one child is a branch point) and/or `mergeIntoNodeIds`, which names steps elsewhere in the same request that this step rejoins. Branches that come back together are represented that way rather than by repeating the shared step, so reading a flow, editing it and writing it back preserves it exactly. A merge target is named by its `nodeId` when it already exists, or by `ref` when it is being created in the same request. `ref` is a label you choose, it is request-local, and it is never stored or returned. Put the shared step inline under the first branch that reaches it and point the others at it: a top-level step is a root wired straight from the start of the flow, so a merge target parked there would also be reachable directly. The two DTMF types are mirror images and both require `dtmfDigits`. `CUSTOMER_DTMF` is keys the simulated caller presses while navigating your agent. `AGENT_DTMF` is keys your agent under test is expected to press while navigating a menu the simulation is playing, so its digits are an assertion the run is graded against rather than an instruction, and it counts as an agent turn for role alternation.
          - object
            - `nodeId` string, uuid
            - `ref` string
            - `steps` FlowStep[]
            - `mergeIntoNodeIds` string[]
            - `type` 'AGENT_TURN', required
            - `content` string, nullable
          - object
            - `nodeId` string, uuid
            - `ref` string
            - `steps` FlowStep[]
            - `mergeIntoNodeIds` string[]
            - `type` 'CUSTOMER_TURN', required
            - `content` string, nullable
          - object
            - `nodeId` string, uuid
            - `ref` string
            - `steps` FlowStep[]
            - `mergeIntoNodeIds` string[]
            - `type` 'CUSTOMER_FIRST_MESSAGE', required
            - `content` string, nullable
          - object
            - `nodeId` string, uuid
            - `ref` string
            - `steps` FlowStep[]
            - `mergeIntoNodeIds` string[]
            - `type` 'CUSTOMER_SILENCE', required
            - `silenceDurationSeconds` integer, nullable
          - object
            - `nodeId` string, uuid
            - `ref` string
            - `steps` FlowStep[]
            - `mergeIntoNodeIds` string[]
            - `type` 'CUSTOMER_DTMF', required
            - `dtmfDigits` string, nullable
          - object
            - `nodeId` string, uuid
            - `ref` string
            - `steps` FlowStep[]
            - `mergeIntoNodeIds` string[]
            - `type` 'AGENT_DTMF', required
            - `dtmfDigits` string, nullable
          - object
            - `nodeId` string, uuid
            - `ref` string
            - `steps` FlowStep[]
            - `mergeIntoNodeIds` string[]
            - `type` 'VOICEMAIL', required
          - object
            - `nodeId` string, uuid
            - `ref` string
            - `steps` FlowStep[]
            - `mergeIntoNodeIds` string[]
            - `type` 'SCENARIO_LINK', required
            - `linkedCustomerFlowId` string, uuid, nullable
            - `linkedCustomerFlowVariantId` string, uuid, nullable
      - `happyPath` ScriptedFlowHappyPath, required — One path through a scripted flow. The path engine owns which paths exist, so editing the graph is what creates and removes these.
        - `id` string, uuid, required
        - `title` string, required
        - `precededByCustomerFlowId` string, uuid, nullable, required
        - `precededByCustomerFlowVariantId` string, uuid, nullable, required
        - `isGenerated` boolean, required
        - `createdAt` string, required — Creation timestamp in ISO 8601 format
        - `updatedAt` string, required — Last update timestamp in ISO 8601 format
        - `personaOverride` object, nullable, required — The persona this runs as instead of the happy path's. Null means it inherits.
          - `id` string, uuid, required — Unique identifier of the persona
          - `name` string, required — The name the agent will identify as during conversations
          - `description` string, nullable — Human-readable description of the persona
          - `language` 'EN' | 'ES' | 'DE' | 'HI' | 'FR' | 'NL' | 'AR' | 'EL' | 'IT' | 'ID' | 'TH' | 'JA' | 'TL' | 'MS' | 'ZH' | 'TR' | 'PT' | 'HE', required — Primary language ISO 639-1 code for the persona
          - `secondaryLanguage` 'EN', nullable — Secondary language ISO 639-1 code for code-switching (e.g., Hinglish, Spanglish)
          - `understoodLanguages` string[], required — Languages the persona can understand. Multilingual combinations are limited by multilingual speech recognition support.
          - `accent` 'US' | 'US_X_SOUTH' | 'GB' | 'ES' | 'DE' | 'IN' | 'FR' | 'NL' | 'SA' | 'GR' | 'AU' | 'IT' | 'ID' | 'TH' | 'JP' | 'NZ' | 'PH' | 'SG' | 'MY' | 'HK' | 'TR' | 'PT' | 'IL', required — Accent of the persona, defined using ISO 3166-1 alpha-2 country codes with optional variants
          - `age` 'CHILD' | 'TEENAGER' | 'ADULT' | 'ELDERLY', required — How old the caller sounds and behaves. Only ages the persona's accent has a voice for are accepted; defaults to ADULT, which every accent supports.
          - `gender` 'MALE' | 'FEMALE', required — Gender of the persona
          - `backgroundNoise` 'NONE' | 'AIRPORT' | 'CHILDREN_PLAYING' | 'CITY' | 'COFFEE_SHOP' | 'DRIVING' | 'OFFICE' | 'THUNDERSTORM', required — Background noise setting
          - `speechPace` 'SUPER_SLOW' | 'SLOW' | 'NORMAL' | 'FAST' | 'SUPER_FAST', required — Speech pace of the persona
          - `speechClarity` 'CLEAR' | 'VAGUE' | 'RAMBLING', required — Speech clarity of the persona
          - `hasDisfluencies` boolean, required — Whether the persona uses filler words like "um" and "uh"
          - `baseEmotion` 'NEUTRAL' | 'CHEERFUL' | 'CONFUSED' | 'FRUSTRATED' | 'SKEPTICAL' | 'RUSHED' | 'DISTRACTED', required — Base emotional state of the persona
          - `intentClarity` 'CLEAR' | 'INDIRECT' | 'VAGUE', required — How clearly the persona expresses their intentions
          - `confirmationStyle` 'EXPLICIT' | 'VAGUE', required — How the persona confirms information
          - `memoryReliability` 'HIGH' | 'LOW', required — How reliable the persona's memory is
          - `responseTiming` 'RELAXED' | 'NORMAL' | 'QUICK', required — Controls how quickly the persona responds to pauses in conversation (QUICK, NORMAL, RELAXED)
          - `backstoryPrompt` string, nullable — Background story and behavioral patterns for the persona
          - `idleMessages` string[], nullable, required — Messages the persona will say when the agent goes silent during a call. null = "Automatic": language-appropriate defaults are used at call time.
          - `idleTimeoutSeconds` integer, required — Seconds of silence before the persona sends an idle message
          - `idleMessageMaxSpokenCount` integer, required — Maximum number of idle messages the persona will send before giving up
          - `idleMessageResetCountOnUserSpeechEnabled` boolean, required — Whether the idle message counter resets when the agent speaks
          - `properties` object, required — Additional custom properties about the persona
          - `createdAt` string, required — Creation timestamp
          - `updatedAt` string, required — Last update timestamp
        - `environment` EnvironmentResponse, required — A simulation environment: the ambient conditions a customer flow variant runs under. The list includes both your own and the ones Roark curates for every project.
          - `id` string, uuid, required
          - `name` string, required
          - `description` string, nullable
          - `backgroundNoise` 'NONE' | 'AIRPORT' | 'CHILDREN_PLAYING' | 'CITY' | 'COFFEE_SHOP' | 'DRIVING' | 'OFFICE' | 'THUNDERSTORM', required
          - `createdAt` string, required — Creation timestamp in ISO 8601 format
          - `updatedAt` string, required — Last update timestamp in ISO 8601 format
        - `additionalExpectations` FlowExpectation[], required — Graded on top of the flow's own expectations, for this variant only.
          - `id` string, uuid, required
          - `prompt` string, required — What the agent under test is graded against.
        - `type` 'SCRIPTED', required
        - `steps` FlowStep[], required — The one path through the graph this variant runs, in order. Linear by construction, so these steps never nest.
          - union — One step in a scripted flow's conversation. `nodeId` is the identity contract: include it to update the existing step, omit it to create a new one. A step continues into `steps` (more than one child is a branch point) and/or `mergeIntoNodeIds`, which names steps elsewhere in the same request that this step rejoins. Branches that come back together are represented that way rather than by repeating the shared step, so reading a flow, editing it and writing it back preserves it exactly. A merge target is named by its `nodeId` when it already exists, or by `ref` when it is being created in the same request. `ref` is a label you choose, it is request-local, and it is never stored or returned. Put the shared step inline under the first branch that reaches it and point the others at it: a top-level step is a root wired straight from the start of the flow, so a merge target parked there would also be reachable directly. The two DTMF types are mirror images and both require `dtmfDigits`. `CUSTOMER_DTMF` is keys the simulated caller presses while navigating your agent. `AGENT_DTMF` is keys your agent under test is expected to press while navigating a menu the simulation is playing, so its digits are an assertion the run is graded against rather than an instruction, and it counts as an agent turn for role alternation.
            - object
              - …
            - object
              - …
            - object
              - …
            - object
              - …
            - object
              - …
            - object
              - …
            - object
              - …
            - object
              - …
      - `edgeCases` ScriptedFlowVariant[], required — Every other way of running this flow.
        - `id` string, uuid, required
        - `title` string, required
        - `precededByCustomerFlowId` string, uuid, nullable, required
        - `precededByCustomerFlowVariantId` string, uuid, nullable, required
        - `isGenerated` boolean, required
        - `createdAt` string, required — Creation timestamp in ISO 8601 format
        - `updatedAt` string, required — Last update timestamp in ISO 8601 format
        - `personaOverride` object, nullable, required — The persona this runs as instead of the happy path's. Null means it inherits.
          - `id` string, uuid, required — Unique identifier of the persona
          - `name` string, required — The name the agent will identify as during conversations
          - `description` string, nullable — Human-readable description of the persona
          - `language` 'EN' | 'ES' | 'DE' | 'HI' | 'FR' | 'NL' | 'AR' | 'EL' | 'IT' | 'ID' | 'TH' | 'JA' | 'TL' | 'MS' | 'ZH' | 'TR' | 'PT' | 'HE', required — Primary language ISO 639-1 code for the persona
          - `secondaryLanguage` 'EN', nullable — Secondary language ISO 639-1 code for code-switching (e.g., Hinglish, Spanglish)
          - `understoodLanguages` string[], required — Languages the persona can understand. Multilingual combinations are limited by multilingual speech recognition support.
          - `accent` 'US' | 'US_X_SOUTH' | 'GB' | 'ES' | 'DE' | 'IN' | 'FR' | 'NL' | 'SA' | 'GR' | 'AU' | 'IT' | 'ID' | 'TH' | 'JP' | 'NZ' | 'PH' | 'SG' | 'MY' | 'HK' | 'TR' | 'PT' | 'IL', required — Accent of the persona, defined using ISO 3166-1 alpha-2 country codes with optional variants
          - `age` 'CHILD' | 'TEENAGER' | 'ADULT' | 'ELDERLY', required — How old the caller sounds and behaves. Only ages the persona's accent has a voice for are accepted; defaults to ADULT, which every accent supports.
          - `gender` 'MALE' | 'FEMALE', required — Gender of the persona
          - `backgroundNoise` 'NONE' | 'AIRPORT' | 'CHILDREN_PLAYING' | 'CITY' | 'COFFEE_SHOP' | 'DRIVING' | 'OFFICE' | 'THUNDERSTORM', required — Background noise setting
          - `speechPace` 'SUPER_SLOW' | 'SLOW' | 'NORMAL' | 'FAST' | 'SUPER_FAST', required — Speech pace of the persona
          - `speechClarity` 'CLEAR' | 'VAGUE' | 'RAMBLING', required — Speech clarity of the persona
          - `hasDisfluencies` boolean, required — Whether the persona uses filler words like "um" and "uh"
          - `baseEmotion` 'NEUTRAL' | 'CHEERFUL' | 'CONFUSED' | 'FRUSTRATED' | 'SKEPTICAL' | 'RUSHED' | 'DISTRACTED', required — Base emotional state of the persona
          - `intentClarity` 'CLEAR' | 'INDIRECT' | 'VAGUE', required — How clearly the persona expresses their intentions
          - `confirmationStyle` 'EXPLICIT' | 'VAGUE', required — How the persona confirms information
          - `memoryReliability` 'HIGH' | 'LOW', required — How reliable the persona's memory is
          - `responseTiming` 'RELAXED' | 'NORMAL' | 'QUICK', required — Controls how quickly the persona responds to pauses in conversation (QUICK, NORMAL, RELAXED)
          - `backstoryPrompt` string, nullable — Background story and behavioral patterns for the persona
          - `idleMessages` string[], nullable, required — Messages the persona will say when the agent goes silent during a call. null = "Automatic": language-appropriate defaults are used at call time.
          - `idleTimeoutSeconds` integer, required — Seconds of silence before the persona sends an idle message
          - `idleMessageMaxSpokenCount` integer, required — Maximum number of idle messages the persona will send before giving up
          - `idleMessageResetCountOnUserSpeechEnabled` boolean, required — Whether the idle message counter resets when the agent speaks
          - `properties` object, required — Additional custom properties about the persona
          - `createdAt` string, required — Creation timestamp
          - `updatedAt` string, required — Last update timestamp
        - `environment` EnvironmentResponse, required — A simulation environment: the ambient conditions a customer flow variant runs under. The list includes both your own and the ones Roark curates for every project.
          - `id` string, uuid, required
          - `name` string, required
          - `description` string, nullable
          - `backgroundNoise` 'NONE' | 'AIRPORT' | 'CHILDREN_PLAYING' | 'CITY' | 'COFFEE_SHOP' | 'DRIVING' | 'OFFICE' | 'THUNDERSTORM', required
          - `createdAt` string, required — Creation timestamp in ISO 8601 format
          - `updatedAt` string, required — Last update timestamp in ISO 8601 format
        - `additionalExpectations` FlowExpectation[], required — Graded on top of the flow's own expectations, for this variant only.
          - `id` string, uuid, required
          - `prompt` string, required — What the agent under test is graded against.
        - `type` 'SCRIPTED', required
        - `steps` FlowStep[], required — The one path through the graph this variant runs, in order. Linear by construction, so these steps never nest.
          - union — One step in a scripted flow's conversation. `nodeId` is the identity contract: include it to update the existing step, omit it to create a new one. A step continues into `steps` (more than one child is a branch point) and/or `mergeIntoNodeIds`, which names steps elsewhere in the same request that this step rejoins. Branches that come back together are represented that way rather than by repeating the shared step, so reading a flow, editing it and writing it back preserves it exactly. A merge target is named by its `nodeId` when it already exists, or by `ref` when it is being created in the same request. `ref` is a label you choose, it is request-local, and it is never stored or returned. Put the shared step inline under the first branch that reaches it and point the others at it: a top-level step is a root wired straight from the start of the flow, so a merge target parked there would also be reachable directly. The two DTMF types are mirror images and both require `dtmfDigits`. `CUSTOMER_DTMF` is keys the simulated caller presses while navigating your agent. `AGENT_DTMF` is keys your agent under test is expected to press while navigating a menu the simulation is playing, so its digits are an assertion the run is graded against rather than an instruction, and it counts as an agent turn for role alternation.
            - object
              - …
            - object
              - …
            - object
              - …
            - object
              - …
            - object
              - …
            - object
              - …
            - object
              - …
            - object
              - …
    - ImprovCustomerFlow — A flow whose conversation is not written out: each variant gives the simulated customer a brief and lets it improvise.
      - `id` string, uuid, required
      - `title` string, required
      - `description` string, nullable
      - `source` 'SYSTEM' | 'CUSTOM', required
      - `createdAt` string, required — Creation timestamp in ISO 8601 format
      - `updatedAt` string, required — Last update timestamp in ISO 8601 format
      - `agents` object[], required — The agents this flow is run against.
        - `id` string, uuid, required — Unique identifier of the agent
        - `name` string, required — Name of the agent
        - `description` string, nullable, required — Description of the agent
        - `customId` string, nullable, required — Custom identifier for the agent
        - `createdAt` string, required — Creation timestamp in ISO 8601 format
        - `updatedAt` string, required — Last update timestamp in ISO 8601 format
      - `agentExpectations` FlowExpectation[], required
        - `id` string, uuid, required
        - `prompt` string, required — What the agent under test is graded against.
      - `type` 'IMPROV', required
      - `happyPath` ImprovFlowHappyPath, required — One brief to run an improv flow with.
        - `id` string, uuid, required
        - `title` string, required
        - `precededByCustomerFlowId` string, uuid, nullable, required
        - `precededByCustomerFlowVariantId` string, uuid, nullable, required
        - `isGenerated` boolean, required
        - `createdAt` string, required — Creation timestamp in ISO 8601 format
        - `updatedAt` string, required — Last update timestamp in ISO 8601 format
        - `personaOverride` object, nullable, required — The persona this runs as instead of the happy path's. Null means it inherits.
          - `id` string, uuid, required — Unique identifier of the persona
          - `name` string, required — The name the agent will identify as during conversations
          - `description` string, nullable — Human-readable description of the persona
          - `language` 'EN' | 'ES' | 'DE' | 'HI' | 'FR' | 'NL' | 'AR' | 'EL' | 'IT' | 'ID' | 'TH' | 'JA' | 'TL' | 'MS' | 'ZH' | 'TR' | 'PT' | 'HE', required — Primary language ISO 639-1 code for the persona
          - `secondaryLanguage` 'EN', nullable — Secondary language ISO 639-1 code for code-switching (e.g., Hinglish, Spanglish)
          - `understoodLanguages` string[], required — Languages the persona can understand. Multilingual combinations are limited by multilingual speech recognition support.
          - `accent` 'US' | 'US_X_SOUTH' | 'GB' | 'ES' | 'DE' | 'IN' | 'FR' | 'NL' | 'SA' | 'GR' | 'AU' | 'IT' | 'ID' | 'TH' | 'JP' | 'NZ' | 'PH' | 'SG' | 'MY' | 'HK' | 'TR' | 'PT' | 'IL', required — Accent of the persona, defined using ISO 3166-1 alpha-2 country codes with optional variants
          - `age` 'CHILD' | 'TEENAGER' | 'ADULT' | 'ELDERLY', required — How old the caller sounds and behaves. Only ages the persona's accent has a voice for are accepted; defaults to ADULT, which every accent supports.
          - `gender` 'MALE' | 'FEMALE', required — Gender of the persona
          - `backgroundNoise` 'NONE' | 'AIRPORT' | 'CHILDREN_PLAYING' | 'CITY' | 'COFFEE_SHOP' | 'DRIVING' | 'OFFICE' | 'THUNDERSTORM', required — Background noise setting
          - `speechPace` 'SUPER_SLOW' | 'SLOW' | 'NORMAL' | 'FAST' | 'SUPER_FAST', required — Speech pace of the persona
          - `speechClarity` 'CLEAR' | 'VAGUE' | 'RAMBLING', required — Speech clarity of the persona
          - `hasDisfluencies` boolean, required — Whether the persona uses filler words like "um" and "uh"
          - `baseEmotion` 'NEUTRAL' | 'CHEERFUL' | 'CONFUSED' | 'FRUSTRATED' | 'SKEPTICAL' | 'RUSHED' | 'DISTRACTED', required — Base emotional state of the persona
          - `intentClarity` 'CLEAR' | 'INDIRECT' | 'VAGUE', required — How clearly the persona expresses their intentions
          - `confirmationStyle` 'EXPLICIT' | 'VAGUE', required — How the persona confirms information
          - `memoryReliability` 'HIGH' | 'LOW', required — How reliable the persona's memory is
          - `responseTiming` 'RELAXED' | 'NORMAL' | 'QUICK', required — Controls how quickly the persona responds to pauses in conversation (QUICK, NORMAL, RELAXED)
          - `backstoryPrompt` string, nullable — Background story and behavioral patterns for the persona
          - `idleMessages` string[], nullable, required — Messages the persona will say when the agent goes silent during a call. null = "Automatic": language-appropriate defaults are used at call time.
          - `idleTimeoutSeconds` integer, required — Seconds of silence before the persona sends an idle message
          - `idleMessageMaxSpokenCount` integer, required — Maximum number of idle messages the persona will send before giving up
          - `idleMessageResetCountOnUserSpeechEnabled` boolean, required — Whether the idle message counter resets when the agent speaks
          - `properties` object, required — Additional custom properties about the persona
          - `createdAt` string, required — Creation timestamp
          - `updatedAt` string, required — Last update timestamp
        - `environment` EnvironmentResponse, required — A simulation environment: the ambient conditions a customer flow variant runs under. The list includes both your own and the ones Roark curates for every project.
          - `id` string, uuid, required
          - `name` string, required
          - `description` string, nullable
          - `backgroundNoise` 'NONE' | 'AIRPORT' | 'CHILDREN_PLAYING' | 'CITY' | 'COFFEE_SHOP' | 'DRIVING' | 'OFFICE' | 'THUNDERSTORM', required
          - `createdAt` string, required — Creation timestamp in ISO 8601 format
          - `updatedAt` string, required — Last update timestamp in ISO 8601 format
        - `additionalExpectations` FlowExpectation[], required — Graded on top of the flow's own expectations, for this variant only.
          - `id` string, uuid, required
          - `prompt` string, required — What the agent under test is graded against.
        - `type` 'IMPROV', required
        - `prompt` string, nullable — The brief the simulated customer improvises from.
      - `edgeCases` ImprovFlowVariant[], required — Every other way of running this flow.
        - `id` string, uuid, required
        - `title` string, required
        - `precededByCustomerFlowId` string, uuid, nullable, required
        - `precededByCustomerFlowVariantId` string, uuid, nullable, required
        - `isGenerated` boolean, required
        - `createdAt` string, required — Creation timestamp in ISO 8601 format
        - `updatedAt` string, required — Last update timestamp in ISO 8601 format
        - `personaOverride` object, nullable, required — The persona this runs as instead of the happy path's. Null means it inherits.
          - `id` string, uuid, required — Unique identifier of the persona
          - `name` string, required — The name the agent will identify as during conversations
          - `description` string, nullable — Human-readable description of the persona
          - `language` 'EN' | 'ES' | 'DE' | 'HI' | 'FR' | 'NL' | 'AR' | 'EL' | 'IT' | 'ID' | 'TH' | 'JA' | 'TL' | 'MS' | 'ZH' | 'TR' | 'PT' | 'HE', required — Primary language ISO 639-1 code for the persona
          - `secondaryLanguage` 'EN', nullable — Secondary language ISO 639-1 code for code-switching (e.g., Hinglish, Spanglish)
          - `understoodLanguages` string[], required — Languages the persona can understand. Multilingual combinations are limited by multilingual speech recognition support.
          - `accent` 'US' | 'US_X_SOUTH' | 'GB' | 'ES' | 'DE' | 'IN' | 'FR' | 'NL' | 'SA' | 'GR' | 'AU' | 'IT' | 'ID' | 'TH' | 'JP' | 'NZ' | 'PH' | 'SG' | 'MY' | 'HK' | 'TR' | 'PT' | 'IL', required — Accent of the persona, defined using ISO 3166-1 alpha-2 country codes with optional variants
          - `age` 'CHILD' | 'TEENAGER' | 'ADULT' | 'ELDERLY', required — How old the caller sounds and behaves. Only ages the persona's accent has a voice for are accepted; defaults to ADULT, which every accent supports.
          - `gender` 'MALE' | 'FEMALE', required — Gender of the persona
          - `backgroundNoise` 'NONE' | 'AIRPORT' | 'CHILDREN_PLAYING' | 'CITY' | 'COFFEE_SHOP' | 'DRIVING' | 'OFFICE' | 'THUNDERSTORM', required — Background noise setting
          - `speechPace` 'SUPER_SLOW' | 'SLOW' | 'NORMAL' | 'FAST' | 'SUPER_FAST', required — Speech pace of the persona
          - `speechClarity` 'CLEAR' | 'VAGUE' | 'RAMBLING', required — Speech clarity of the persona
          - `hasDisfluencies` boolean, required — Whether the persona uses filler words like "um" and "uh"
          - `baseEmotion` 'NEUTRAL' | 'CHEERFUL' | 'CONFUSED' | 'FRUSTRATED' | 'SKEPTICAL' | 'RUSHED' | 'DISTRACTED', required — Base emotional state of the persona
          - `intentClarity` 'CLEAR' | 'INDIRECT' | 'VAGUE', required — How clearly the persona expresses their intentions
          - `confirmationStyle` 'EXPLICIT' | 'VAGUE', required — How the persona confirms information
          - `memoryReliability` 'HIGH' | 'LOW', required — How reliable the persona's memory is
          - `responseTiming` 'RELAXED' | 'NORMAL' | 'QUICK', required — Controls how quickly the persona responds to pauses in conversation (QUICK, NORMAL, RELAXED)
          - `backstoryPrompt` string, nullable — Background story and behavioral patterns for the persona
          - `idleMessages` string[], nullable, required — Messages the persona will say when the agent goes silent during a call. null = "Automatic": language-appropriate defaults are used at call time.
          - `idleTimeoutSeconds` integer, required — Seconds of silence before the persona sends an idle message
          - `idleMessageMaxSpokenCount` integer, required — Maximum number of idle messages the persona will send before giving up
          - `idleMessageResetCountOnUserSpeechEnabled` boolean, required — Whether the idle message counter resets when the agent speaks
          - `properties` object, required — Additional custom properties about the persona
          - `createdAt` string, required — Creation timestamp
          - `updatedAt` string, required — Last update timestamp
        - `environment` EnvironmentResponse, required — A simulation environment: the ambient conditions a customer flow variant runs under. The list includes both your own and the ones Roark curates for every project.
          - `id` string, uuid, required
          - `name` string, required
          - `description` string, nullable
          - `backgroundNoise` 'NONE' | 'AIRPORT' | 'CHILDREN_PLAYING' | 'CITY' | 'COFFEE_SHOP' | 'DRIVING' | 'OFFICE' | 'THUNDERSTORM', required
          - `createdAt` string, required — Creation timestamp in ISO 8601 format
          - `updatedAt` string, required — Last update timestamp in ISO 8601 format
        - `additionalExpectations` FlowExpectation[], required — Graded on top of the flow's own expectations, for this variant only.
          - `id` string, uuid, required
          - `prompt` string, required — What the agent under test is graded against.
        - `type` 'IMPROV', required
        - `prompt` string, nullable — The brief the simulated customer improvises from.
    - VoicemailCustomerFlow — A flow that leaves a voicemail. Curated by Roark, read-only.
      - `id` string, uuid, required
      - `title` string, required
      - `description` string, nullable
      - `source` 'SYSTEM' | 'CUSTOM', required
      - `createdAt` string, required — Creation timestamp in ISO 8601 format
      - `updatedAt` string, required — Last update timestamp in ISO 8601 format
      - `agents` object[], required — The agents this flow is run against.
        - `id` string, uuid, required — Unique identifier of the agent
        - `name` string, required — Name of the agent
        - `description` string, nullable, required — Description of the agent
        - `customId` string, nullable, required — Custom identifier for the agent
        - `createdAt` string, required — Creation timestamp in ISO 8601 format
        - `updatedAt` string, required — Last update timestamp in ISO 8601 format
      - `agentExpectations` FlowExpectation[], required
        - `id` string, uuid, required
        - `prompt` string, required — What the agent under test is graded against.
      - `type` 'VOICEMAIL', required
      - `happyPath` VoicemailFlowHappyPath, required — One voicemail greeting.
        - `id` string, uuid, required
        - `title` string, required
        - `precededByCustomerFlowId` string, uuid, nullable, required
        - `precededByCustomerFlowVariantId` string, uuid, nullable, required
        - `isGenerated` boolean, required
        - `createdAt` string, required — Creation timestamp in ISO 8601 format
        - `updatedAt` string, required — Last update timestamp in ISO 8601 format
        - `personaOverride` object, nullable, required — The persona this runs as instead of the happy path's. Null means it inherits.
          - `id` string, uuid, required — Unique identifier of the persona
          - `name` string, required — The name the agent will identify as during conversations
          - `description` string, nullable — Human-readable description of the persona
          - `language` 'EN' | 'ES' | 'DE' | 'HI' | 'FR' | 'NL' | 'AR' | 'EL' | 'IT' | 'ID' | 'TH' | 'JA' | 'TL' | 'MS' | 'ZH' | 'TR' | 'PT' | 'HE', required — Primary language ISO 639-1 code for the persona
          - `secondaryLanguage` 'EN', nullable — Secondary language ISO 639-1 code for code-switching (e.g., Hinglish, Spanglish)
          - `understoodLanguages` string[], required — Languages the persona can understand. Multilingual combinations are limited by multilingual speech recognition support.
          - `accent` 'US' | 'US_X_SOUTH' | 'GB' | 'ES' | 'DE' | 'IN' | 'FR' | 'NL' | 'SA' | 'GR' | 'AU' | 'IT' | 'ID' | 'TH' | 'JP' | 'NZ' | 'PH' | 'SG' | 'MY' | 'HK' | 'TR' | 'PT' | 'IL', required — Accent of the persona, defined using ISO 3166-1 alpha-2 country codes with optional variants
          - `age` 'CHILD' | 'TEENAGER' | 'ADULT' | 'ELDERLY', required — How old the caller sounds and behaves. Only ages the persona's accent has a voice for are accepted; defaults to ADULT, which every accent supports.
          - `gender` 'MALE' | 'FEMALE', required — Gender of the persona
          - `backgroundNoise` 'NONE' | 'AIRPORT' | 'CHILDREN_PLAYING' | 'CITY' | 'COFFEE_SHOP' | 'DRIVING' | 'OFFICE' | 'THUNDERSTORM', required — Background noise setting
          - `speechPace` 'SUPER_SLOW' | 'SLOW' | 'NORMAL' | 'FAST' | 'SUPER_FAST', required — Speech pace of the persona
          - `speechClarity` 'CLEAR' | 'VAGUE' | 'RAMBLING', required — Speech clarity of the persona
          - `hasDisfluencies` boolean, required — Whether the persona uses filler words like "um" and "uh"
          - `baseEmotion` 'NEUTRAL' | 'CHEERFUL' | 'CONFUSED' | 'FRUSTRATED' | 'SKEPTICAL' | 'RUSHED' | 'DISTRACTED', required — Base emotional state of the persona
          - `intentClarity` 'CLEAR' | 'INDIRECT' | 'VAGUE', required — How clearly the persona expresses their intentions
          - `confirmationStyle` 'EXPLICIT' | 'VAGUE', required — How the persona confirms information
          - `memoryReliability` 'HIGH' | 'LOW', required — How reliable the persona's memory is
          - `responseTiming` 'RELAXED' | 'NORMAL' | 'QUICK', required — Controls how quickly the persona responds to pauses in conversation (QUICK, NORMAL, RELAXED)
          - `backstoryPrompt` string, nullable — Background story and behavioral patterns for the persona
          - `idleMessages` string[], nullable, required — Messages the persona will say when the agent goes silent during a call. null = "Automatic": language-appropriate defaults are used at call time.
          - `idleTimeoutSeconds` integer, required — Seconds of silence before the persona sends an idle message
          - `idleMessageMaxSpokenCount` integer, required — Maximum number of idle messages the persona will send before giving up
          - `idleMessageResetCountOnUserSpeechEnabled` boolean, required — Whether the idle message counter resets when the agent speaks
          - `properties` object, required — Additional custom properties about the persona
          - `createdAt` string, required — Creation timestamp
          - `updatedAt` string, required — Last update timestamp
        - `environment` EnvironmentResponse, required — A simulation environment: the ambient conditions a customer flow variant runs under. The list includes both your own and the ones Roark curates for every project.
          - `id` string, uuid, required
          - `name` string, required
          - `description` string, nullable
          - `backgroundNoise` 'NONE' | 'AIRPORT' | 'CHILDREN_PLAYING' | 'CITY' | 'COFFEE_SHOP' | 'DRIVING' | 'OFFICE' | 'THUNDERSTORM', required
          - `createdAt` string, required — Creation timestamp in ISO 8601 format
          - `updatedAt` string, required — Last update timestamp in ISO 8601 format
        - `additionalExpectations` FlowExpectation[], required — Graded on top of the flow's own expectations, for this variant only.
          - `id` string, uuid, required
          - `prompt` string, required — What the agent under test is graded against.
        - `type` 'VOICEMAIL', required
      - `edgeCases` VoicemailFlowVariant[], required — Every other way of running this flow.
        - `id` string, uuid, required
        - `title` string, required
        - `precededByCustomerFlowId` string, uuid, nullable, required
        - `precededByCustomerFlowVariantId` string, uuid, nullable, required
        - `isGenerated` boolean, required
        - `createdAt` string, required — Creation timestamp in ISO 8601 format
        - `updatedAt` string, required — Last update timestamp in ISO 8601 format
        - `personaOverride` object, nullable, required — The persona this runs as instead of the happy path's. Null means it inherits.
          - `id` string, uuid, required — Unique identifier of the persona
          - `name` string, required — The name the agent will identify as during conversations
          - `description` string, nullable — Human-readable description of the persona
          - `language` 'EN' | 'ES' | 'DE' | 'HI' | 'FR' | 'NL' | 'AR' | 'EL' | 'IT' | 'ID' | 'TH' | 'JA' | 'TL' | 'MS' | 'ZH' | 'TR' | 'PT' | 'HE', required — Primary language ISO 639-1 code for the persona
          - `secondaryLanguage` 'EN', nullable — Secondary language ISO 639-1 code for code-switching (e.g., Hinglish, Spanglish)
          - `understoodLanguages` string[], required — Languages the persona can understand. Multilingual combinations are limited by multilingual speech recognition support.
          - `accent` 'US' | 'US_X_SOUTH' | 'GB' | 'ES' | 'DE' | 'IN' | 'FR' | 'NL' | 'SA' | 'GR' | 'AU' | 'IT' | 'ID' | 'TH' | 'JP' | 'NZ' | 'PH' | 'SG' | 'MY' | 'HK' | 'TR' | 'PT' | 'IL', required — Accent of the persona, defined using ISO 3166-1 alpha-2 country codes with optional variants
          - `age` 'CHILD' | 'TEENAGER' | 'ADULT' | 'ELDERLY', required — How old the caller sounds and behaves. Only ages the persona's accent has a voice for are accepted; defaults to ADULT, which every accent supports.
          - `gender` 'MALE' | 'FEMALE', required — Gender of the persona
          - `backgroundNoise` 'NONE' | 'AIRPORT' | 'CHILDREN_PLAYING' | 'CITY' | 'COFFEE_SHOP' | 'DRIVING' | 'OFFICE' | 'THUNDERSTORM', required — Background noise setting
          - `speechPace` 'SUPER_SLOW' | 'SLOW' | 'NORMAL' | 'FAST' | 'SUPER_FAST', required — Speech pace of the persona
          - `speechClarity` 'CLEAR' | 'VAGUE' | 'RAMBLING', required — Speech clarity of the persona
          - `hasDisfluencies` boolean, required — Whether the persona uses filler words like "um" and "uh"
          - `baseEmotion` 'NEUTRAL' | 'CHEERFUL' | 'CONFUSED' | 'FRUSTRATED' | 'SKEPTICAL' | 'RUSHED' | 'DISTRACTED', required — Base emotional state of the persona
          - `intentClarity` 'CLEAR' | 'INDIRECT' | 'VAGUE', required — How clearly the persona expresses their intentions
          - `confirmationStyle` 'EXPLICIT' | 'VAGUE', required — How the persona confirms information
          - `memoryReliability` 'HIGH' | 'LOW', required — How reliable the persona's memory is
          - `responseTiming` 'RELAXED' | 'NORMAL' | 'QUICK', required — Controls how quickly the persona responds to pauses in conversation (QUICK, NORMAL, RELAXED)
          - `backstoryPrompt` string, nullable — Background story and behavioral patterns for the persona
          - `idleMessages` string[], nullable, required — Messages the persona will say when the agent goes silent during a call. null = "Automatic": language-appropriate defaults are used at call time.
          - `idleTimeoutSeconds` integer, required — Seconds of silence before the persona sends an idle message
          - `idleMessageMaxSpokenCount` integer, required — Maximum number of idle messages the persona will send before giving up
          - `idleMessageResetCountOnUserSpeechEnabled` boolean, required — Whether the idle message counter resets when the agent speaks
          - `properties` object, required — Additional custom properties about the persona
          - `createdAt` string, required — Creation timestamp
          - `updatedAt` string, required — Last update timestamp
        - `environment` EnvironmentResponse, required — A simulation environment: the ambient conditions a customer flow variant runs under. The list includes both your own and the ones Roark curates for every project.
          - `id` string, uuid, required
          - `name` string, required
          - `description` string, nullable
          - `backgroundNoise` 'NONE' | 'AIRPORT' | 'CHILDREN_PLAYING' | 'CITY' | 'COFFEE_SHOP' | 'DRIVING' | 'OFFICE' | 'THUNDERSTORM', required
          - `createdAt` string, required — Creation timestamp in ISO 8601 format
          - `updatedAt` string, required — Last update timestamp in ISO 8601 format
        - `additionalExpectations` FlowExpectation[], required — Graded on top of the flow's own expectations, for this variant only.
          - `id` string, uuid, required
          - `prompt` string, required — What the agent under test is graded against.
        - `type` 'VOICEMAIL', required

## Other responses

- `400` — Bad Request
- `401` — Unauthorized
- `403` — Forbidden
- `429` — Too Many Requests
- `500` — Internal Server Error

## Changes

- **2026-09-04** `7d9ee4f358d1` — 3 breaking, 1 info
  - added `subschema #6` to the `data/oneOf[subschema #1: Scripted]/edgeCases/items/steps/items/` response property `oneOf` list for the response status `201`
  - added `subschema #6` to the `data/oneOf[subschema #1: Scripted]/graph/items/` response property `oneOf` list for the response status `201`
  - added `subschema #6` to the `data/oneOf[subschema #1: Scripted]/happyPath/oneOf[subschema #1: Scripted]/allOf[subschema #1: Scripted]/steps/items/` response property `oneOf` list for the response status `201`
  - added `subschema #6` to the `oneOf[subschema #1: Scripted]/graph/items/` request property `oneOf` list
- **2026-08-26** `b4a59c7057ca` — 6 info
  - added the required property `data/oneOf[subschema #1: Scripted]/edgeCases/items/personaOverride/age` to the response with the `201` status
  - added the required property `data/oneOf[subschema #1: Scripted]/happyPath/oneOf[subschema #1: Scripted]/allOf[subschema #1: Scripted]/personaOverride/age` to the response with the `201` status
  - added the required property `data/oneOf[subschema #2: Improv]/edgeCases/items/personaOverride/age` to the response with the `201` status
  - added the required property `data/oneOf[subschema #2: Improv]/happyPath/oneOf[subschema #1: Improv]/allOf[subschema #1: Improv]/personaOverride/age` to the response with the `201` status
  - …2 more
- …earlier changes not shown

[Full history](https://skmtc.dev/roarkhq/apis/roark-analytics-api/changes/v1/customer-flow/post.md)

---

[API](https://skmtc.dev/roarkhq/apis/roark-analytics-api.md) · [All operations](https://skmtc.dev/roarkhq/apis/roark-analytics-api/llms.txt) · [OpenAPI document](https://skmtc.dev/roarkhq/apis/roark-analytics-api/revisions/7bed4709abaa?raw)
