- A Simple Pearl: a single opening sentence plus a flow script. Created with Create Pearl.
- A Pearl (the focus of this guide): a graph of nodes connected by transitions, giving you full control over the conversation, branching, integrations, and post-call automation.
Endpoints for node-graph Pearls:
- Voice: Create Voice Pearl, Update Voice Pearl
- Text: Create Text Pearl, Update Text Pearl
- Read back: Get Pearl Settings
The mental model
A Pearl flow is a directed graph:- Each node does one thing (say something, call an API, send an email, transfer, end the call, …).
- Each transition is a labeled edge from one node to another. The label is a plain-language condition that decides when that edge is taken.
- The conversation starts at a single entry point and every path eventually reaches the one EndCall node.
pearl.nodes array. You do not draw the graph visually, you describe it: every node lists its outgoing transitions, and each transition names the toNodeId it leads to. The nodes reference each other by ID, so the order inside the array does not matter.
The words “call” and “EndCall” are kept for both channels. On a Text Pearl they simply mean the conversation and the end-of-conversation node.
Node types
Every node has anodeType (an integer). This is the single most important field: it decides what the node does and which settings object it must carry.
Sending a node type that is not allowed for the channel is rejected. For example an SMS node (
50) or a TransferCall node (60) in a Text Pearl, or a HandoffChatToHuman node (31) in a Voice Pearl.Anatomy of a node
Only fields marked
🧩 May support variables accept the {variableId} syntax. See Flow Variables for the full variable system.Node IDs and transitions
This is the part people get wrong most often, so read it carefully. There are two kinds of IDs, and they behave differently.Node IDs: you provide them
- You choose
nodeId. It is how the graph wires itself together: a transition points at a node throughtoNodeId, which must equal that node’snodeId. - The
nodeIdmust be unique within the flow and is capped at 20 characters. Thenamedoes not have to be unique. - Pick short, stable, meaningful IDs (
opening,triage,booking,endCall). You will reuse them across every transition that leads to the node. - A node needs at least one of
nodeIdorname, and the platform derives the missing one. Send only anodeIdand thenameis generated from it (verifyCustomer→ “Verify Customer”,endCall→ “End Call”); send only anameand thenodeIdis generated from it in camelCase (“Verify Customer” →verifyCustomer). Send neither and the request is rejected.
Transition IDs: you do NOT provide them
A transition only needs two things from you:
You never send a transition ID. The platform generates it from the transition
name in camelCase (“is successful” becomes isSuccessful), adding a numeric suffix on collisions (isSuccessful1, isSuccessful2). This is why the transition name must be unique inside a node.
A single transition:
The opening
Every flow needs an entry point. In most flows that is a single OpeningSentence node (nodeType: 2).
The opening script is spoken as written. Whatever you put in an OpeningSentence node’s
script is what the agent says to open the conversation, close to verbatim. This is different from a Dialogue node, where the script is a guide that the agent adapts in real time to what the customer says.The entry point is derived, not sent
You do not tell the API which node is first. The entry point is resolved automatically:- If the flow contains a PreCallAPI node, that node is the entry point.
- Otherwise, the single OpeningSentence node is the entry point.
- Without a PreCallAPI: exactly one OpeningSentence node.
- With a PreCallAPI: one or two OpeningSentence nodes (see the next section).
Pre-call API
A PreCallAPI node (nodeType: 3) runs an API call before the conversation starts, typically to look the customer up so the opening can be personalized. A flow may contain at most one PreCallAPI node.
Its transitions are special: each one must set apiResult, and each one must lead to an OpeningSentence node.
apiResult is only valid on the transitions of a PreCallAPI node, and it is required there. It must not appear on any other node’s transitions.method: 1 is a GET (see the method codes under Action nodes). outputBody maps a field of the API response onto a flow variable so the opening can use {firstName}.
Connecting nodes into a sequence
A flow is only valid when it is fully connected. The rules:- Exactly one EndCall node (
nodeType: 100), and every path must be able to reach it. - Every non-entry node needs at least one incoming transition. A node nobody points to is unreachable and rejected. (The one exception is a floating TransferCall node, see below.)
- Transitions may only point at node IDs that exist in the flow.
toNodeId links do the wiring):
Action nodes
Action nodes do work instead of talking. Each carries the settings object that matches itsnodeType.
apiSettings (method codes: 1 GET, 2 POST, 3 PUT, 4 DELETE, 5 PATCH):
Action node settings on a node graph carry no trigger description: the transitions decide when an action runs, so there is nothing to describe. (The one exception is a floating TransferCall, see below.) For the full API body, headers, credentials, and output-schema options, see the API node guide and Flow Variables.
TransferCall: wired vs floating (Voice)
A TransferCall node behaves differently depending on how it is reached, and this changes whethertriggerDescription is required:
A TransferCall node does not need an outgoing transition. Once the call is handed off there is nothing left to branch on, so the platform connects it straight to the EndCall node on its own. This holds whether the transfer is wired (it has an incoming transition) or floating (it has none): in both cases you can leave its
transitions empty and the post-call flow still runs. The { "name": "Continue", "toNodeId": "endCall" } transition shown above is therefore optional.Post-call actions
Post-call actions run after the conversation ends. They are fire-and-forget: the platform sends them and moves on, so they never have transitions and their result is not captured. The structure has two parts:- A PostCallActions container node (
nodeType: 200) whosepostCallActionsarray holds the actual action nodes (API40, Email51, and on Voice also SMS50). These inner nodes have no transitions. - The EndCall node’s transitions, which point at those containers. This is the only place EndCall may transition to. Each transition
nameis the condition under which that container fires.
Post-call actions are the only place where post-call variables (
post_call_summary, post_call_transcript, post_call_recording, …) are available. See Flow Variables.Voice vs Text
The node logic above is identical for both channels. The differences are the node types allowed, the model, and a few channel fields.The Hand-Off node (Text)
The Text equivalent of a transfer. It hands the conversation to a human and can fire inline notifications through itshandOffAction array. Those sub-actions may be SMS (50), Email (51), or API (40), have no transitions of their own, and the Hand-Off node itself transitions to EndCall.
script on a Hand-Off is the last line the agent sends before it stops replying. Leave it empty for a silent hand-off.Creating vs updating
Create
Send the whole thing at once. The request wrapper is the same shape for both channels (only the settings variant differs):- Provide exactly one channel:
inboundoroutbound, never both. - For a Text Pearl, put the
textChannelIdon theinbound/outboundsettings. variablesdefines the flow variables; keep it minimal and only include what you reference. See Flow Variables.- The Pearl is created already published: the configuration you send becomes its live version.
Update: pearl is a full replace, settings are a patch
The update endpoints (Update Voice Pearl, Update Text Pearl) treat each part of the request differently. In every case the update applies to the published version of the Pearl: if several versions exist on the platform, only the currently published one is modified.
The channel patch works field by field: sending
{ "inbound": { "waitingSentence": "..." } } changes only the waiting sentence and preserves everything else. This is why inbound/outbound behave as a patch while pearl does not.Validation checklist
Before you send a flow, confirm:- Exactly one EndCall node, and every node can reach it.
- Exactly one OpeningSentence (or, with a PreCallAPI, one or two).
- At most one PreCallAPI; its transitions all set
apiResultand lead to OpeningSentence nodes. - Every
nodeIdis unique and everytoNodeIdpoints at an existing node. - Every non-entry node has an incoming transition (except a floating TransferCall).
- Each node carries the settings object for its
nodeType, and no forbidden node type for the channel. -
apiResultonly on PreCallAPI transitions; post-call and hand-off sub-actions have no transitions. - Transition names are unique within their node and written as plain-language conditions.
Related
Flow Variables
The
{variableId} syntax, variable groups, and built-in variables.API Node
Request body, headers, credentials, and response output schema.
Get Pearl Settings
Read the current flow back before updating it.
Hand-Off Node
Escalate a Text conversation to a human.

