Skip to content

client.flows

Call flows: drafts, published versions and simulation. These methods are on client.flows, where client is a MoreVoice client (see the Python SDK). On AsyncMoreVoice the same methods are awaited. Each one returns the response object and raises an exception when the API answers with an error.

Create a flow. Creates a flow with an empty draft, a template’s, or the graph you send. It runs on calls once published (POST /v1/flows/{id}/publish).

client.flows
def create(self, body: _m.FlowCreateParamsInput | Mapping[str, Any], *, more_voice_version: str | Unset = UNSET, idempotency_key: str | Unset = UNSET) -> _m.Flow

client.flows.create() · await async_client.flows.create() · POST /flows · API reference

Field Type Required Description
name string yes —
assistant_id string | null no asst_… ID.
description string no —
graph FlowGraphParamsInput no A whole graph to write. Nodes are matched to the stored draft by key.
kind "voice" | "agent_script" | "ivr" no —
language "he" | "en" no The template’s / empty flow’s language (default he).
template_id string no Start from a template instead of an empty flow.

Flow:

Field Type Description
id string The flow’s ID.
object "flow" Always flow.
livemode boolean true in live mode, false in test mode.
name string —
description string —
kind "voice" | "agent_script" | "ivr" voice: drives an AI assistant; agent_script: a human agent’s branching script; ivr: a phone menu.
status "draft" | "published" | "archived" —
published_version integer | null The version calls run (null: never published).
latest_version integer —
draft_rev integer The draft’s revision: send it as base_rev when you write the draft.
assistant_id string | null asst_… ID.
template_id string | null —
node_count integer —
updated string An ISO-8601 timestamp in UTC.
from morevoice import MoreVoice
client = MoreVoice() # MOREVOICE_API_KEY from the environment
flow = client.flows.create({
"kind": "voice",
"language": "en",
"name": "Reception",
})
print(flow)

Delete a flow. Deletes the flow and its versions. 409 while an assistant or a copilot profile uses it (details list them): detach it first.

client.flows
def delete(self, id: str, *, more_voice_version: str | Unset = UNSET, idempotency_key: str | Unset = UNSET) -> _m.DeletedFlow

client.flows.delete() · await async_client.flows.delete() · DELETE /flows/{id} · API reference

Name Type Required Description
id str yes A flow ID (flow_…).

DeletedFlow:

Field Type Description
id string A flow ID (prefix flow_).
object "flow" Always flow.
deleted true —
from morevoice import MoreVoice
client = MoreVoice() # MOREVOICE_API_KEY from the environment
deleted_flow = client.flows.delete("flow_7Hk2Lm9Qp")
print(deleted_flow)

Duplicate a flow. Creates a new flow from this one’s draft (unpublished, linked to no assistant).

client.flows
def duplicate(self, id: str, body: _m.DuplicateFlowParamsInput | Mapping[str, Any] | Unset = UNSET, *, more_voice_version: str | Unset = UNSET, idempotency_key: str | Unset = UNSET) -> _m.Flow

client.flows.duplicate() · await async_client.flows.duplicate() · POST /flows/{id}/duplicate · API reference

Name Type Required Description
id str yes A flow ID (flow_…).
Field Type Required Description
name string no Default: the original’s name with “(copy)”.

Flow:

Field Type Description
id string The flow’s ID.
object "flow" Always flow.
livemode boolean true in live mode, false in test mode.
name string —
description string —
kind "voice" | "agent_script" | "ivr" voice: drives an AI assistant; agent_script: a human agent’s branching script; ivr: a phone menu.
status "draft" | "published" | "archived" —
published_version integer | null The version calls run (null: never published).
latest_version integer —
draft_rev integer The draft’s revision: send it as base_rev when you write the draft.
assistant_id string | null asst_… ID.
template_id string | null —
node_count integer —
updated string An ISO-8601 timestamp in UTC.
from morevoice import MoreVoice
client = MoreVoice() # MOREVOICE_API_KEY from the environment
flow = client.flows.duplicate("flow_7Hk2Lm9Qp", {
"name": "Reception B",
})
print(flow)

List flows. Your flows, most recently changed first (archived ones only with include_archived=true).

client.flows
def list(self, *, limit: int | Unset = 20, starting_after: str | Unset = UNSET, ending_before: str | Unset = UNSET, kind: _m.FlowsListKind | Unset = UNSET, assistant_id: str | Unset = UNSET, include_archived: _m.FlowsListIncludeArchived | Unset = UNSET, more_voice_version: str | Unset = UNSET) -> AsyncPage[_m.Flow]

client.flows.list() · await async_client.flows.list() · GET /flows · API reference

Name Type Required Description
limit integer no How many objects to return, 1–100 (default 20).
starting_after string no A cursor (next_cursor) or object ID: return the objects after it (older).
ending_before string no A cursor or object ID: return the objects before it (newer).
kind "voice" | "agent_script" | "ivr" no Only flows of this kind.
assistant_id string no Only flows linked to this assistant.
include_archived "true" | "false" no Include archived flows (default false).

A page of results (FlowList): data, has_more and next_cursor.

from morevoice import MoreVoice
client = MoreVoice() # MOREVOICE_API_KEY from the environment
for flow in client.flows.list():
print(flow)

List a flow’s versions. Returns a page of FlowVersion objects, newest first. Pass next_cursor as starting_after for the next page; the SDKs iterate every page for you. Answers 404 with the code resource_missing when nothing has this ID in this organisation and mode.

client.flows
def list_versions(self, id: str, *, limit: int | Unset = 20, starting_after: str | Unset = UNSET, ending_before: str | Unset = UNSET, more_voice_version: str | Unset = UNSET) -> AsyncPage[_m.FlowVersion]

client.flows.list_versions() · await async_client.flows.list_versions() · GET /flows/{id}/versions · API reference

Name Type Required Description
id str yes A flow ID (flow_…).
limit integer no How many objects to return, 1–100 (default 20).
starting_after string no A cursor (next_cursor) or object ID: return the objects after it (older).
ending_before string no A cursor or object ID: return the objects before it (newer).

A page of results (FlowVersionList): data, has_more and next_cursor.

from morevoice import MoreVoice
client = MoreVoice() # MOREVOICE_API_KEY from the environment
for flow in client.flows.list_versions("flow_7Hk2Lm9Qp"):
print(flow)

Publish a flow. Publishes the draft as a new immutable version; calls start using it at once. A draft with errors is refused with 409 flow_invalid (details.issues: what to fix).

client.flows
def publish(self, id: str, body: _m.FlowPublishParamsInput | Mapping[str, Any] | Unset = UNSET, *, more_voice_version: str | Unset = UNSET, idempotency_key: str | Unset = UNSET) -> _m.Flow

client.flows.publish() · await async_client.flows.publish() · POST /flows/{id}/publish · API reference

Name Type Required Description
id str yes A flow ID (flow_…).
Field Type Required Description
note string no What changed (shown in the version history).

Flow:

Field Type Description
id string The flow’s ID.
object "flow" Always flow.
livemode boolean true in live mode, false in test mode.
name string —
description string —
kind "voice" | "agent_script" | "ivr" voice: drives an AI assistant; agent_script: a human agent’s branching script; ivr: a phone menu.
status "draft" | "published" | "archived" —
published_version integer | null The version calls run (null: never published).
latest_version integer —
draft_rev integer The draft’s revision: send it as base_rev when you write the draft.
assistant_id string | null asst_… ID.
template_id string | null —
node_count integer —
updated string An ISO-8601 timestamp in UTC.
from morevoice import MoreVoice
client = MoreVoice() # MOREVOICE_API_KEY from the environment
flow = client.flows.publish("flow_7Hk2Lm9Qp", {
"note": "New opening hours",
})
print(flow)

Restore a flow version into the draft. Copies the version’s graph into the draft (a new draft revision). It is not published: publish to run it.

client.flows.restore
def version(self, id: str, version: str, *, more_voice_version: str | Unset = UNSET, idempotency_key: str | Unset = UNSET) -> _m.FlowDraft

client.flows.restore.version() · await async_client.flows.restore.version() · POST /flows/{id}/versions/{version}/restore · API reference

Name Type Required Description
id str yes A flow ID (flow_…).
version str yes The version number.

FlowDraft:

Field Type Description
object "flow_draft" Always flow_draft.
flow_id string A flow ID (prefix flow_).
livemode boolean true in live mode, false in test mode.
rev integer Send as base_rev on the next write.
graph FlowGraph A flow’s graph: nodes (v1 node schema) wired by their transitions’ next, variables and settings.
updated string An ISO-8601 timestamp in UTC.
from morevoice import MoreVoice
client = MoreVoice() # MOREVOICE_API_KEY from the environment
flow_draft = client.flows.restore.version("flow_7Hk2Lm9Qp", "3")
print(flow_draft)

Retrieve a flow. The flow’s details. Its graph: GET /v1/flows/{id}/draft (editable) or /versions/{version} (published).

client.flows
def retrieve(self, id: str, *, more_voice_version: str | Unset = UNSET) -> _m.Flow

client.flows.retrieve() · await async_client.flows.retrieve() · GET /flows/{id} · API reference

Name Type Required Description
id str yes A flow ID (flow_…).

Flow:

Field Type Description
id string The flow’s ID.
object "flow" Always flow.
livemode boolean true in live mode, false in test mode.
name string —
description string —
kind "voice" | "agent_script" | "ivr" voice: drives an AI assistant; agent_script: a human agent’s branching script; ivr: a phone menu.
status "draft" | "published" | "archived" —
published_version integer | null The version calls run (null: never published).
latest_version integer —
draft_rev integer The draft’s revision: send it as base_rev when you write the draft.
assistant_id string | null asst_… ID.
template_id string | null —
node_count integer —
updated string An ISO-8601 timestamp in UTC.
from morevoice import MoreVoice
client = MoreVoice() # MOREVOICE_API_KEY from the environment
flow = client.flows.retrieve("flow_7Hk2Lm9Qp")
print(flow)

Retrieve a flow’s analytics. How this key’s mode’s calls went through the flow (the latest 5000 in the range): visits, calls, drop-off, caller turns and errors per node, how often each transition was taken, how calls ended, and IVR KPIs for IVR flows. Filter by from / to (start time) and a published version.

client.flows
def retrieve_analytics(self, id: str, *, from_: _dt.datetime | Unset = UNSET, to: _dt.datetime | Unset = UNSET, version: str | Unset = UNSET, more_voice_version: str | Unset = UNSET) -> _m.FlowAnalytics

client.flows.retrieve_analytics() · await async_client.flows.retrieve_analytics() · GET /flows/{id}/analytics · API reference

Name Type Required Description
id str yes A flow ID (flow_…).
from string no Calls that started at or after this time (ISO 8601).
to string no Calls that started at or before this time (ISO 8601).
version string no Only calls that ran this published version.

FlowAnalytics:

Field Type Description
object "flow_analytics" Always flow_analytics.
flow_id string A flow ID (prefix flow_).
livemode boolean true in live mode, false in test mode.
from string | null —
to string | null —
version integer | null —
calls integer Calls that ran the flow in the range (at most the latest 5000).
nodes object[] —
transitions object[] —
ends object[] —
ivr object | null IVR flows: containment, abandon rate, keypad vs speech, per menu.
from morevoice import MoreVoice
client = MoreVoice() # MOREVOICE_API_KEY from the environment
flow_analytics = client.flows.retrieve_analytics("flow_7Hk2Lm9Qp")
print(flow_analytics)

Retrieve a flow’s draft. The editable graph and its revision (rev: send it back as base_rev).

client.flows
def retrieve_draft(self, id: str, *, more_voice_version: str | Unset = UNSET) -> _m.FlowDraft

client.flows.retrieve_draft() · await async_client.flows.retrieve_draft() · GET /flows/{id}/draft · API reference

Name Type Required Description
id str yes A flow ID (flow_…).

FlowDraft:

Field Type Description
object "flow_draft" Always flow_draft.
flow_id string A flow ID (prefix flow_).
livemode boolean true in live mode, false in test mode.
rev integer Send as base_rev on the next write.
graph FlowGraph A flow’s graph: nodes (v1 node schema) wired by their transitions’ next, variables and settings.
updated string An ISO-8601 timestamp in UTC.
from morevoice import MoreVoice
client = MoreVoice() # MOREVOICE_API_KEY from the environment
flow_draft = client.flows.retrieve_draft("flow_7Hk2Lm9Qp")
print(flow_draft)

Retrieve what uses a flow. Returns the FlowUsage object. Answers 404 with the code resource_missing when nothing has this ID in this organisation and mode.

client.flows
def retrieve_usage(self, id: str, *, more_voice_version: str | Unset = UNSET) -> _m.FlowUsage

client.flows.retrieve_usage() · await async_client.flows.retrieve_usage() · GET /flows/{id}/usage · API reference

Name Type Required Description
id str yes A flow ID (flow_…).

FlowUsage:

Field Type Description
object "flow_usage" Always flow_usage.
flow_id string A flow ID (prefix flow_).
assistants object[] —
copilot_profiles object[] —
from morevoice import MoreVoice
client = MoreVoice() # MOREVOICE_API_KEY from the environment
flow_usage = client.flows.retrieve_usage("flow_7Hk2Lm9Qp")
print(flow_usage)

Retrieve a flow version. A published version, with its graph.

client.flows
def retrieve_version(self, id: str, version: str, *, more_voice_version: str | Unset = UNSET) -> _m.FlowVersion

client.flows.retrieve_version() · await async_client.flows.retrieve_version() · GET /flows/{id}/versions/{version} · API reference

Name Type Required Description
id str yes A flow ID (flow_…).
version str yes The version number.

FlowVersion:

Field Type Description
object "flow_version" Always flow_version.
flow_id string A flow ID (prefix flow_).
livemode boolean true in live mode, false in test mode.
version integer —
note string —
checksum string —
node_count integer —
edge_count integer —
created string An ISO-8601 timestamp in UTC.
graph FlowGraph A flow’s graph: nodes (v1 node schema) wired by their transitions’ next, variables and settings.
from morevoice import MoreVoice
client = MoreVoice() # MOREVOICE_API_KEY from the environment
flow_version = client.flows.retrieve_version("flow_7Hk2Lm9Qp", "3")
print(flow_version)

Simulate a call through a flow. Runs a text-only call through the flow’s draft (or a published version) with the real flow engine and the assistant’s model, and answers what happened: the turns, the nodes entered, the actions (dry runs: no API or tool request is sent) and where the call stands. Send the caller’s lines as messages / message, keys as dtmf, silence as no_response. Continue the same simulation with sim_id (it lives 15 minutes). With a test key the models are mocks.

Send Accept: text/event-stream to receive the same simulation as Server-Sent Events while it runs: sim.started (sim_id, resumed, kind), then sim.node, sim.turn and sim.action (each with the fields of the matching FlowSimulation entry) in order, and last sim.done, whose data is this endpoint’s JSON answer; error ends a failed run. Closing the connection stops the simulation. A streamed answer counts against the key’s stream limit and is not stored for Idempotency-Key replays.

client.flows
def simulate(self, id: str, body: _m.FlowSimulateParamsInput | Mapping[str, Any] | Unset = UNSET, *, more_voice_version: str | Unset = UNSET, idempotency_key: str | Unset = UNSET) -> _m.FlowSimulation

client.flows.simulate() · await async_client.flows.simulate() · POST /flows/{id}/simulate · API reference

Name Type Required Description
id str yes A flow ID (flow_…).
Field Type Required Description
dtmf string no Keys the caller presses, in order (after messages, before message); the entry then completes.
message string no One more caller line (after messages).
messages string[] no What the caller says, one line per turn, in order.
no_response boolean no The caller stays silent (a no-response timeout).
sim_id string no Continue this simulation (the id of an earlier answer; it lives 15 minutes after its last turn). Default: a new one.
variables Record<string, string | number | boolean | null> no Variables for the simulated call (merged over the flow’s sample values).
version integer no Simulate this published version. Default: the draft.

FlowSimulation:

Field Type Description
object "flow_simulation" Always flow_simulation.
id string The simulation’s ID: send it as sim_id to continue.
flow_id string A flow ID (prefix flow_).
livemode boolean true in live mode, false in test mode.
resumed boolean This request continued an existing simulation.
turns object[] What was said during this request, in order.
path object[] The nodes entered during this request, in order.
actions object[] Actions and tool calls during this request (dry runs).
ended boolean —
end_reason string | null —
current_node_key string | null —
variables object The call’s variables now (sensitive ones redacted).
coverage object —
from morevoice import MoreVoice
client = MoreVoice() # MOREVOICE_API_KEY from the environment
flow_simulation = client.flows.simulate("flow_7Hk2Lm9Qp", {
"messages": [
"Hi, I'd like to book an appointment",
"Tomorrow at 10",
],
})
print(flow_simulation)

Update a flow. Changes only the fields you send. Returns the updated Flow. Answers 404 with the code resource_missing when nothing has this ID in this organisation and mode.

client.flows
def update(self, id: str, body: _m.FlowUpdateParamsInput | Mapping[str, Any] | Unset = UNSET, *, more_voice_version: str | Unset = UNSET) -> _m.Flow

client.flows.update() · await async_client.flows.update() · PATCH /flows/{id} · API reference

Name Type Required Description
id str yes A flow ID (flow_…).
Field Type Required Description
archived boolean no true archives the flow (hidden from lists); false restores it.
assistant_id string | null no asst_… ID.
description string no —
name string no —

Flow:

Field Type Description
id string The flow’s ID.
object "flow" Always flow.
livemode boolean true in live mode, false in test mode.
name string —
description string —
kind "voice" | "agent_script" | "ivr" voice: drives an AI assistant; agent_script: a human agent’s branching script; ivr: a phone menu.
status "draft" | "published" | "archived" —
published_version integer | null The version calls run (null: never published).
latest_version integer —
draft_rev integer The draft’s revision: send it as base_rev when you write the draft.
assistant_id string | null asst_… ID.
template_id string | null —
node_count integer —
updated string An ISO-8601 timestamp in UTC.
from morevoice import MoreVoice
client = MoreVoice() # MOREVOICE_API_KEY from the environment
flow = client.flows.update("flow_7Hk2Lm9Qp", {
"name": "Reception (2026)",
})
print(flow)

Replace a flow’s draft. Replaces the draft graph. Nodes are matched to the stored ones by id: what the v1 schema does not carry (groups, notes, editor state) is kept, and internal nodes stay exactly as stored. base_rev must be the draft’s current revision, else 409 (details.draft_rev) and nothing is written — read the draft again and retry. Calls keep running the published version until you publish.

client.flows
def update_draft(self, id: str, body: _m.FlowDraftParamsInput | Mapping[str, Any], *, more_voice_version: str | Unset = UNSET) -> _m.FlowDraft

client.flows.update_draft() · await async_client.flows.update_draft() · PUT /flows/{id}/draft · API reference

Name Type Required Description
id str yes A flow ID (flow_…).
Field Type Required Description
graph FlowGraphParamsInput yes A whole graph to write. Nodes are matched to the stored draft by key.
base_rev integer yes The draft rev you read: a newer draft (changed elsewhere) answers 409 and nothing is written.

FlowDraft:

Field Type Description
object "flow_draft" Always flow_draft.
flow_id string A flow ID (prefix flow_).
livemode boolean true in live mode, false in test mode.
rev integer Send as base_rev on the next write.
graph FlowGraph A flow’s graph: nodes (v1 node schema) wired by their transitions’ next, variables and settings.
updated string An ISO-8601 timestamp in UTC.
from morevoice import MoreVoice
client = MoreVoice() # MOREVOICE_API_KEY from the environment
flow_draft = client.flows.update_draft("flow_7Hk2Lm9Qp", {
"base_rev": 17,
"graph": {
"nodes": [
{
"key": "start",
"start": {
"greeting": "Hello!",
},
"transitions": [
{
"condition": {
"kind": "always",
},
"next": "bye",
},
],
"type": "start",
},
{
"end": {
"message": "Goodbye.",
},
"key": "bye",
"type": "end",
},
],
},
})
print(flow_draft)

Validate a flow graph. Checks a graph without saving it: the errors that would block publishing, plus warnings and tasks. A malformed graph answers 400.

client.flows
def validate(self, body: _m.FlowValidateParamsInput | Mapping[str, Any], *, more_voice_version: str | Unset = UNSET, idempotency_key: str | Unset = UNSET) -> _m.FlowValidation

client.flows.validate() · await async_client.flows.validate() · POST /flows/validate · API reference

Field Type Required Description
graph FlowGraphParamsInput yes A whole graph to write. Nodes are matched to the stored draft by key.

FlowValidation:

Field Type Description
object "flow_validation" Always flow_validation.
valid boolean No errors: it can be published.
issues object[] —
from morevoice import MoreVoice
client = MoreVoice() # MOREVOICE_API_KEY from the environment
flow_validation = client.flows.validate({
"graph": {
"kind": "voice",
"nodes": [
{
"key": "start",
"transitions": [
{
"condition": {
"kind": "always",
},
"next": None,
},
],
"type": "start",
},
],
},
})
print(flow_validation)