---
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' — DETERMINISTIC (the default) runs one variant per path through the graph; ADAPTIVE collapses the paths into one call the simulated customer adapts across.
    - `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.
        - 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` '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 — DETERMINISTIC runs one variant per path through the graph. ADAPTIVE collapses the paths into a single variant the simulated customer adapts across.
      - `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.
          - 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` '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.
            - 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.
            - 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-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
- **2026-08-21** `0db5f720e76f` — 2 info
  - the request property `oneOf[subschema #1: Scripted]/agentIds` became optional
  - the `agentIds` request property default value `` was added
- **2026-08-17** `887b091b3d81` — 1 info
  - endpoint added

[Change 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-service-production.skmtc.workers.dev/v1/apis/roarkhq/roark-analytics-api/revisions/1d61b68e9429/schema)
