---
title: "Duplicate Digital Human"
method: POST
path: "/v1/digital-human/{digital_human_id}/duplicate"
tags: ["Digital Humans"]
---

# Duplicate Digital Human

`POST /v1/digital-human/{digital_human_id}/duplicate`

Duplicate a digital human at the database level.

Copies every column of the source row (cloned voice, custom background noise,
interruption/speaks-first configs, transcripts, audio quirks) plus its traits,
scripted responses and expected tool calls — without re-validating stored
values, so copies of voice-ambience or custom-noise digital humans always
succeed. The copy starts without a phone number and always-on inactive.

## Path parameters

- `digital_human_id` integer, required

## Headers

- `X-API-Key` string, required

## Request body

- DuplicateDigitalHumanRequest — Options for duplicating a digital human.
  - `name` string, nullable — Name for the copy; defaults to "<source name> (Copy)"
  - `simulation_ids` integer[], nullable — Simulations to attach the copy to. Omit to copy the source's associations; pass [] for none.

## Response `200`

Successful Response

- SrcModelsDigitalHumansDigitalHumanResponseDigitalHumanResponse — Response model for digital human operations with clear separation of digital human data and simulation context.
  - `digital_human` DigitalHumanResponseData, required — Response model for digital human data.
    - `id` integer, nullable — Unique identifier for the digital human
    - `bluejay_as_code_id` string, uuid, nullable — Stable code-addressable identifier
    - `intent` string, required — Description of the digital human
    - `success_criteria` string, required — Success criteria for the digital human
    - `tag` string, nullable — Tag for categorizing the digital human
    - `tags` string[], nullable — All tags associated with the digital human
    - `name` string, nullable — Name of the digital human
    - `language` 'en' | 'es' | 'pt' | 'ja' | 'tr' | 'hi' | 'ar' | 'he' | 'ru' | 'zh' | 'ml' | 'fr' | 'yue' | 'vi' | 'de' | 'ko' | 'ur' | 'te' | 'ta' | 'mal' | 'kn' | 'mr' | 'gu' | 'tl' | 'ad' — Enum for supported language types.
    - `accent` 'multilingual' | 'american' | 'american2' | 'mature' | 'southern' | 'italian' | 'indian' | 'british' | 'australian' | 'scottish' | 'irish' | 'welsh' | 'mexican' | 'spanish' | 'portuguese' | 'french' | 'turkish' | 'japanese' | 'hindi' | 'arabic' | 'egyptian' | 'levantine' | 'hebrew' | 'russian' | 'chinese' | 'german' | 'korean' | 'urdu' | 'telugu' | 'tamil' | 'malayalam' | 'kannada' | 'marathi' | 'gujarati' | 'vietnamese' | 'cantonese' | 'tagalog' | 'autodetect' | 'watson' | 'watsonbritish' | 'watsonaustralian' | 'watsoncanadian' — Enum for accent options.
    - `gender` 'male' | 'female' — Enum for gender options.
    - `custom_voice_id` string, nullable — ElevenLabs voice_id of a cloned voice used for TTS, if assigned
    - `background_noise` string, nullable — Type of background noise
    - `custom_background_noise_url` string, nullable — Bucket-relative path of the uploaded custom background noise audio when background_noise is 'custom'
    - `voice_speed` string, nullable — Speed of the digital human's voice
    - `audio_quality` string, nullable — Audio quality of the digital human's voice
    - `fluency` string, nullable — Fluency level of the digital human's speech
    - `verbosity` string, nullable — Verbosity level of the digital human's responses
    - `phone_number` string, nullable — Phone number for the digital human
    - `extension` string, nullable — Extension dialed as DTMF after connecting when this DH calls an inbound agent
    - `outbound_text_number` string, nullable — Outbound text number
    - `follow_up_sms_success_criteria` string, nullable — Criteria the captured follow-up SMS is graded against
    - `websocket_url` string, nullable — WebSocket URL for real-time communication
    - `background_noise_volume` number, nullable — Volume of background noise
    - `expected_tool_calls` ExpectedToolCall[], nullable — Expected tool calls
      - `name` string, required — Name of the expected tool call
      - `parameters` object, nullable — Expected parameters passed to the tool call
      - `output` unknown
    - `allow_end_call_tool` boolean, nullable — Allow the digital human to end the tool call
    - `allow_silence_tool` boolean, nullable — Allow the digital human to use the silence tool
    - `allow_dtmf_tool` boolean, nullable — Allow the digital human to use the DTMF tool
    - `default_dtmf_or_voiced` string, nullable
    - `silence_tool_instructions` string, nullable — Tool instructions; "default" or custom text
    - `endpointing_delay` number, nullable — Delay for endpointing
    - `creativity` number, nullable — Temperature setting
    - `hangup_phrases` string[], nullable — Phrases that trigger hangup
    - `hangup_instructions` string, nullable — Freeform instructions for how/when to hang up
    - `silence_timeout` integer, nullable — Silence timeout in seconds
    - `role_description` string, nullable — Description of the role for the digital human
    - `created_at` string, date-time, nullable — When this digital human was created
    - `traits` TraitOutput[], nullable — List of traits associated with this digital human
      - `trait_name` string, required — Name of the trait
      - `trait_data_type` 'BOOLEAN' | 'STRING' | 'DATE' | 'NUMBER', required — Enum for trait data types.
      - `value` unknown, required
      - `is_sip_header` boolean — Whether this trait is a SIP header
    - `interruptions` object, nullable — Interruption configuration for the digital human
    - `scripted_responses` ScriptedResponse[], nullable — List of scripted responses for the digital human, in the order they were saved
      - `match_type` 'exact' | 'context', required — Enum for scripted response match types.
      - `match_phrase` string, required — An utterance the AGENT would say, which releases this response, e.g. 'Can I have your account number?'. Matching compares utterance to utterance, so a description of what the agent is doing ('the agent finished answering and is inviting another question') never matches anything: the rule saves and silently never fires. Write the line you expect to hear. Empty string is only meaningful when the digital human has scripted_responses_ordered set, where it fires on the digital human's next turn regardless of what the agent said.
      - `response_type` 'phrase' | 'silence' | 'dtmf' | 'audio', required — Enum for scripted response types.
      - `response_value` string, nullable — The response text (required for 'phrase' and 'dtmf', optional for 'silence', unused for 'audio')
      - `scripted_response_audio_snippet_url` string, nullable — Skywatch bucket path of an uploaded audio file. AUDIO rows only — the agent downloads and plays this verbatim.
      - `occurrence_mode` 'always' | 'first_n', required — Enum for scripted response occurrence modes.
      - `occurrence_n` integer, nullable — Number of times to apply (required if occurrence_mode is 'first_n', must be > 0)
      - `silence_duration` integer, nullable — Duration in seconds for silence period (only used when response_type is 'silence', must be > 0 if provided)
    - `scripted_responses_ordered` boolean, nullable — When true, scripted_responses run as a script in list order (each fires once, next one arms); when false any one fires whenever its match_phrase comes up
    - `speaks_first_config` SpeaksFirstConfig — Configuration for whether the digital human speaks first and how. Stored as JSONB in Supabase (speaks_first_config).
      - `speaks_first` boolean, required — Whether the digital human speaks first in the call
      - `mode` 'custom' | 'ai_generated', nullable — When speaks_first is true: 'custom' (user-provided message) or 'ai_generated' (no message)
      - `message` string, nullable — When mode is 'custom', the message the digital human says first
      - `dynamic` boolean — When speaks_first is true: wait up to 5s for the agent to open; speak first only if it stays quiet. If the agent does open, the digital human yields and a mode='custom' message is DISCARDED, not spoken after the greeting, so on any agent that greets callers, a dynamic custom opener is never heard. Set false to speak it every time, at the top of the call and possibly over the greeting. Defaults on, so configs saved before this field existed become dynamic
    - `original_transcript` string, nullable — The original transcript text attached to this digital human
    - `formatted_transcript` object[], nullable — Structured transcript as [{"role": "USER"|"AGENT", "utterance": "..."}]
    - `enriched_playback` object[], nullable — Optional enriched playback stored as JSONB: a list of turn objects
    - `workflow_v2_id` string, uuid, nullable — Source workflow_v2 UUID — set when this DH is generated from a workflow
    - `workflow_path_index` integer, nullable — 0-based path index within enumerate_workflow_v2_paths output
    - `tested_path` string[], nullable — Ordered names of the workflow path steps this DH was generated from (Generate-From-Workflow only).
    - `livekit_metadata` object, nullable — LiveKit-specific configuration and metadata for this digital human
    - `test_name` string, nullable — User-facing label for this digital human
    - `journey_steps` JourneyStep[], nullable — Ordered journey steps for a multi-step (Customer Journey) digital human
      - `step` integer, required
      - `intent` string
      - `success_criteria` string
      - `modality` 'voice' | 'sms'
      - `direction` 'inbound' | 'outbound', nullable
      - `wait_seconds` integer, nullable
      - `response_window_seconds` integer, nullable
      - `unresponsive` boolean
      - `phone_number` string, nullable
    - `always_on_mode` boolean, nullable — Whether always-on mode is enabled
    - `always_on_active` boolean, nullable — When true, this DH actively receives inbound calls on phone_number
    - `num_runs` integer, nullable — Number of times this digital human is run per simulation run
    - `attack_vector` string, nullable — Attack tactic key from VECTOR_CATALOG. NULL for non-red-team.
    - `attack_type` string, nullable — Umbrella attack category. NULL for non-red-team.
    - `attack_plan` object, nullable — Crescendo escalation ladder. NULL for non-red-team.
  - `simulation_ids` integer[], nullable — List of simulation IDs associated with this digital human
  - `simulation_id` integer, nullable — ID of the associated simulation. Use simulation_ids instead.

## Other responses

- `422` — Validation Error

## Changes

- **2026-08-26** `b1479366b173` — 1 info
  - added the optional property `digital_human/journey_steps/anyOf[subschema #1]/items/phone_number` to the response with the `200` status
- **2026-08-22** `b5daa886f4ee` — 1 info
  - added the optional property `digital_human/speaks_first_config/anyOf[subschema #1: SpeaksFirstConfig]/dynamic` to the response with the `200` status
- **2026-08-21** `b29e1840a386` — 6 info
  - added the optional property `digital_human/always_on_active` to the response with the `200` status
  - added the optional property `digital_human/always_on_mode` to the response with the `200` status
  - added the optional property `digital_human/attack_plan` to the response with the `200` status
  - added the optional property `digital_human/attack_type` to the response with the `200` status
  - …2 more
- …earlier changes not shown

[Full history](https://skmtc.dev/getbluejay/apis/bluejay-api/changes/v1/digital-human/:digital_human_id/duplicate/post.md)

---

[API](https://skmtc.dev/getbluejay/apis/bluejay-api.md) · [All operations](https://skmtc.dev/getbluejay/apis/bluejay-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/getbluejay/bluejay-api/revisions/84e25a31d733/schema)
