import Roark from '@roarkanalytics/sdk';
const client = new Roark({
bearerToken: process.env['ROARK_API_BEARER_TOKEN'], // This is the default and can be omitted
});
const response = await client.customerFlow.duplicate('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e');
console.log(response.data);import os
from roark_analytics import Roark
client = Roark(
bearer_token=os.environ.get("ROARK_API_BEARER_TOKEN"), # This is the default and can be omitted
)
response = client.customer_flow.duplicate(
flow_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
print(response.data)curl --request POST \
--url https://api.roark.ai/v1/customer-flow/{flowId}/duplicate \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"title": "Reschedule an appointment (v2)",
"agentIds": [
"3c90c3cc-0d44-4b50-8888-8dd25736052a"
]
}
'<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.roark.ai/v1/customer-flow/{flowId}/duplicate",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'title' => 'Reschedule an appointment (v2)',
'agentIds' => [
'3c90c3cc-0d44-4b50-8888-8dd25736052a'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.roark.ai/v1/customer-flow/{flowId}/duplicate"
payload := strings.NewReader("{\n \"title\": \"Reschedule an appointment (v2)\",\n \"agentIds\": [\n \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.roark.ai/v1/customer-flow/{flowId}/duplicate")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"title\": \"Reschedule an appointment (v2)\",\n \"agentIds\": [\n \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.roark.ai/v1/customer-flow/{flowId}/duplicate")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"title\": \"Reschedule an appointment (v2)\",\n \"agentIds\": [\n \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n ]\n}"
response = http.request(request)
puts response.read_body{
"data": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"title": "<string>",
"source": "CUSTOM",
"createdAt": "<string>",
"updatedAt": "<string>",
"agents": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "<string>",
"description": "<string>",
"customId": "<string>",
"createdAt": "<string>",
"updatedAt": "<string>"
}
],
"agentExpectations": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"prompt": "<string>"
}
],
"type": "SCRIPTED",
"scriptAdherence": "LOOSE",
"offScriptPolicy": {
"reaction": "STAY_SILENT",
"maxAttempts": 3,
"then": "HANG_UP",
"sayLine": "<string>",
"waitSeconds": 300
},
"branchingMode": "DETERMINISTIC",
"happyPath": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"title": "<string>",
"precededByCustomerFlowId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"precededByCustomerFlowVariantId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"isGenerated": false,
"createdAt": "<string>",
"updatedAt": "<string>",
"personaOverride": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "<string>",
"language": "EN",
"understoodLanguages": [
"EN"
],
"accent": "US",
"age": "ADULT",
"gender": "MALE",
"backgroundNoise": "NONE",
"speechPace": "NORMAL",
"speechClarity": "CLEAR",
"hasDisfluencies": false,
"baseEmotion": "NEUTRAL",
"intentClarity": "CLEAR",
"confirmationStyle": "EXPLICIT",
"memoryReliability": "HIGH",
"responseTiming": "NORMAL",
"interruption": "OFF",
"idleMessages": [
"<string>"
],
"idleTimeoutSeconds": 10,
"idleMessageMaxSpokenCount": 3,
"idleMessageResetCountOnUserSpeechEnabled": true,
"properties": {
"age": 35,
"zipCode": "94105",
"occupation": "Software Engineer"
},
"createdAt": "<string>",
"updatedAt": "<string>",
"displayName": "<string>",
"description": "<string>",
"secondaryLanguage": "EN",
"backstoryPrompt": "A busy professional calling during lunch break",
"phoneNumber": "+19312830919"
},
"environment": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "<string>",
"backgroundNoise": "NONE",
"backgroundNoiseVolume": 0.1,
"createdAt": "<string>",
"updatedAt": "<string>",
"description": "<string>"
},
"additionalExpectations": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"prompt": "<string>"
}
],
"type": "SCRIPTED",
"steps": [
{
"type": "AGENT_TURN",
"nodeId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"ref": "<string>",
"steps": "<array>",
"mergeIntoNodeIds": [
"<string>"
],
"stage": {
"name": "<string>",
"required": true,
"analyze": true
},
"content": "<string>",
"offScriptPolicy": {
"reaction": "STAY_SILENT",
"maxAttempts": 3,
"then": "HANG_UP",
"sayLine": "<string>",
"waitSeconds": 300
}
}
],
"systemKey": "<string>"
},
"edgeCases": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"title": "<string>",
"precededByCustomerFlowId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"precededByCustomerFlowVariantId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"isGenerated": false,
"createdAt": "<string>",
"updatedAt": "<string>",
"personaOverride": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "<string>",
"language": "EN",
"understoodLanguages": [
"EN"
],
"accent": "US",
"age": "ADULT",
"gender": "MALE",
"backgroundNoise": "NONE",
"speechPace": "NORMAL",
"speechClarity": "CLEAR",
"hasDisfluencies": false,
"baseEmotion": "NEUTRAL",
"intentClarity": "CLEAR",
"confirmationStyle": "EXPLICIT",
"memoryReliability": "HIGH",
"responseTiming": "NORMAL",
"interruption": "OFF",
"idleMessages": [
"<string>"
],
"idleTimeoutSeconds": 10,
"idleMessageMaxSpokenCount": 3,
"idleMessageResetCountOnUserSpeechEnabled": true,
"properties": {
"age": 35,
"zipCode": "94105",
"occupation": "Software Engineer"
},
"createdAt": "<string>",
"updatedAt": "<string>",
"displayName": "<string>",
"description": "<string>",
"secondaryLanguage": "EN",
"backstoryPrompt": "A busy professional calling during lunch break",
"phoneNumber": "+19312830919"
},
"environment": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "<string>",
"backgroundNoise": "NONE",
"backgroundNoiseVolume": 0.1,
"createdAt": "<string>",
"updatedAt": "<string>",
"description": "<string>"
},
"additionalExpectations": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"prompt": "<string>"
}
],
"type": "SCRIPTED",
"steps": [
{
"type": "AGENT_TURN",
"nodeId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"ref": "<string>",
"steps": "<array>",
"mergeIntoNodeIds": [
"<string>"
],
"stage": {
"name": "<string>",
"required": true,
"analyze": true
},
"content": "<string>",
"offScriptPolicy": {
"reaction": "STAY_SILENT",
"maxAttempts": 3,
"then": "HANG_UP",
"sayLine": "<string>",
"waitSeconds": 300
}
}
],
"systemKey": "<string>"
}
],
"description": "<string>",
"graph": [
{
"type": "AGENT_TURN",
"nodeId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"ref": "<string>",
"steps": "<array>",
"mergeIntoNodeIds": [
"<string>"
],
"stage": {
"name": "<string>",
"required": true,
"analyze": true
},
"content": "<string>",
"offScriptPolicy": {
"reaction": "STAY_SILENT",
"maxAttempts": 3,
"then": "HANG_UP",
"sayLine": "<string>",
"waitSeconds": 300
}
}
]
}
}{
"type": "validation",
"code": "invalid_parameter",
"message": "The request was invalid",
"param": "email"
}{
"type": "authentication",
"code": "unauthorized",
"message": "Authentication required"
}{
"type": "forbidden",
"code": "permission_denied",
"message": "You do not have permission to access this resource"
}{
"type": "not_found",
"code": "resource_not_found",
"message": "The requested resource could not be found"
}{
"type": "rate_limit",
"code": "too_many_requests",
"message": "Rate limit exceeded"
}{
"type": "internal",
"code": "internal_error",
"message": "Internal server error"
}Duplicate a customer flow
Deep-copies a flow into a new project-owned flow. The copy carries the source’s description, branching mode, linked agents, flow-level expectations and flow-owned metrics. A scripted flow copies its whole step graph; an improv flow copies its variants (personas, briefs, expectations). Duplicating a Roark-managed flow is how you customise it. Voicemail flows are Roark-managed and cannot be duplicated.
import Roark from '@roarkanalytics/sdk';
const client = new Roark({
bearerToken: process.env['ROARK_API_BEARER_TOKEN'], // This is the default and can be omitted
});
const response = await client.customerFlow.duplicate('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e');
console.log(response.data);import os
from roark_analytics import Roark
client = Roark(
bearer_token=os.environ.get("ROARK_API_BEARER_TOKEN"), # This is the default and can be omitted
)
response = client.customer_flow.duplicate(
flow_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
print(response.data)curl --request POST \
--url https://api.roark.ai/v1/customer-flow/{flowId}/duplicate \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"title": "Reschedule an appointment (v2)",
"agentIds": [
"3c90c3cc-0d44-4b50-8888-8dd25736052a"
]
}
'<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.roark.ai/v1/customer-flow/{flowId}/duplicate",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'title' => 'Reschedule an appointment (v2)',
'agentIds' => [
'3c90c3cc-0d44-4b50-8888-8dd25736052a'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.roark.ai/v1/customer-flow/{flowId}/duplicate"
payload := strings.NewReader("{\n \"title\": \"Reschedule an appointment (v2)\",\n \"agentIds\": [\n \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.roark.ai/v1/customer-flow/{flowId}/duplicate")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"title\": \"Reschedule an appointment (v2)\",\n \"agentIds\": [\n \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.roark.ai/v1/customer-flow/{flowId}/duplicate")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"title\": \"Reschedule an appointment (v2)\",\n \"agentIds\": [\n \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n ]\n}"
response = http.request(request)
puts response.read_body{
"data": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"title": "<string>",
"source": "CUSTOM",
"createdAt": "<string>",
"updatedAt": "<string>",
"agents": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "<string>",
"description": "<string>",
"customId": "<string>",
"createdAt": "<string>",
"updatedAt": "<string>"
}
],
"agentExpectations": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"prompt": "<string>"
}
],
"type": "SCRIPTED",
"scriptAdherence": "LOOSE",
"offScriptPolicy": {
"reaction": "STAY_SILENT",
"maxAttempts": 3,
"then": "HANG_UP",
"sayLine": "<string>",
"waitSeconds": 300
},
"branchingMode": "DETERMINISTIC",
"happyPath": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"title": "<string>",
"precededByCustomerFlowId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"precededByCustomerFlowVariantId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"isGenerated": false,
"createdAt": "<string>",
"updatedAt": "<string>",
"personaOverride": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "<string>",
"language": "EN",
"understoodLanguages": [
"EN"
],
"accent": "US",
"age": "ADULT",
"gender": "MALE",
"backgroundNoise": "NONE",
"speechPace": "NORMAL",
"speechClarity": "CLEAR",
"hasDisfluencies": false,
"baseEmotion": "NEUTRAL",
"intentClarity": "CLEAR",
"confirmationStyle": "EXPLICIT",
"memoryReliability": "HIGH",
"responseTiming": "NORMAL",
"interruption": "OFF",
"idleMessages": [
"<string>"
],
"idleTimeoutSeconds": 10,
"idleMessageMaxSpokenCount": 3,
"idleMessageResetCountOnUserSpeechEnabled": true,
"properties": {
"age": 35,
"zipCode": "94105",
"occupation": "Software Engineer"
},
"createdAt": "<string>",
"updatedAt": "<string>",
"displayName": "<string>",
"description": "<string>",
"secondaryLanguage": "EN",
"backstoryPrompt": "A busy professional calling during lunch break",
"phoneNumber": "+19312830919"
},
"environment": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "<string>",
"backgroundNoise": "NONE",
"backgroundNoiseVolume": 0.1,
"createdAt": "<string>",
"updatedAt": "<string>",
"description": "<string>"
},
"additionalExpectations": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"prompt": "<string>"
}
],
"type": "SCRIPTED",
"steps": [
{
"type": "AGENT_TURN",
"nodeId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"ref": "<string>",
"steps": "<array>",
"mergeIntoNodeIds": [
"<string>"
],
"stage": {
"name": "<string>",
"required": true,
"analyze": true
},
"content": "<string>",
"offScriptPolicy": {
"reaction": "STAY_SILENT",
"maxAttempts": 3,
"then": "HANG_UP",
"sayLine": "<string>",
"waitSeconds": 300
}
}
],
"systemKey": "<string>"
},
"edgeCases": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"title": "<string>",
"precededByCustomerFlowId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"precededByCustomerFlowVariantId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"isGenerated": false,
"createdAt": "<string>",
"updatedAt": "<string>",
"personaOverride": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "<string>",
"language": "EN",
"understoodLanguages": [
"EN"
],
"accent": "US",
"age": "ADULT",
"gender": "MALE",
"backgroundNoise": "NONE",
"speechPace": "NORMAL",
"speechClarity": "CLEAR",
"hasDisfluencies": false,
"baseEmotion": "NEUTRAL",
"intentClarity": "CLEAR",
"confirmationStyle": "EXPLICIT",
"memoryReliability": "HIGH",
"responseTiming": "NORMAL",
"interruption": "OFF",
"idleMessages": [
"<string>"
],
"idleTimeoutSeconds": 10,
"idleMessageMaxSpokenCount": 3,
"idleMessageResetCountOnUserSpeechEnabled": true,
"properties": {
"age": 35,
"zipCode": "94105",
"occupation": "Software Engineer"
},
"createdAt": "<string>",
"updatedAt": "<string>",
"displayName": "<string>",
"description": "<string>",
"secondaryLanguage": "EN",
"backstoryPrompt": "A busy professional calling during lunch break",
"phoneNumber": "+19312830919"
},
"environment": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "<string>",
"backgroundNoise": "NONE",
"backgroundNoiseVolume": 0.1,
"createdAt": "<string>",
"updatedAt": "<string>",
"description": "<string>"
},
"additionalExpectations": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"prompt": "<string>"
}
],
"type": "SCRIPTED",
"steps": [
{
"type": "AGENT_TURN",
"nodeId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"ref": "<string>",
"steps": "<array>",
"mergeIntoNodeIds": [
"<string>"
],
"stage": {
"name": "<string>",
"required": true,
"analyze": true
},
"content": "<string>",
"offScriptPolicy": {
"reaction": "STAY_SILENT",
"maxAttempts": 3,
"then": "HANG_UP",
"sayLine": "<string>",
"waitSeconds": 300
}
}
],
"systemKey": "<string>"
}
],
"description": "<string>",
"graph": [
{
"type": "AGENT_TURN",
"nodeId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"ref": "<string>",
"steps": "<array>",
"mergeIntoNodeIds": [
"<string>"
],
"stage": {
"name": "<string>",
"required": true,
"analyze": true
},
"content": "<string>",
"offScriptPolicy": {
"reaction": "STAY_SILENT",
"maxAttempts": 3,
"then": "HANG_UP",
"sayLine": "<string>",
"waitSeconds": 300
}
}
]
}
}{
"type": "validation",
"code": "invalid_parameter",
"message": "The request was invalid",
"param": "email"
}{
"type": "authentication",
"code": "unauthorized",
"message": "Authentication required"
}{
"type": "forbidden",
"code": "permission_denied",
"message": "You do not have permission to access this resource"
}{
"type": "not_found",
"code": "resource_not_found",
"message": "The requested resource could not be found"
}{
"type": "rate_limit",
"code": "too_many_requests",
"message": "Rate limit exceeded"
}{
"type": "internal",
"code": "internal_error",
"message": "Internal server error"
}Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
Path Parameters
Body
Options for duplicating a customer flow. Every field is optional.
Title for the copy. Defaults to "Copy of" the source flow.
1"Reschedule an appointment (v2)"
Agents to link on the copy. Omit to carry the source flow's agents over. Required when the source is a Roark-managed flow with no agents of its own.
Response
The duplicated customer flow
The conversation a simulated customer has with the agent under test.
- Scripted
- Improv
- Voicemail
Show child attributes
Show child attributes