# Quick Start Source: https://developers.nlpearl.ai/api-reference/api_quickstart Get started with the NLPearl.AI API by following these simple steps to set up your subscription, API secret key, and authentication.
NLPearl.AI API cover
NLPearl.AI API cover
## Quick Start with NLPearl.AI API Getting started with the NLPearl.AI API is straightforward. Follow these steps to set up your subscription, create an API secret key, and authenticate your API requests. ### Step 1: Choose a Subscription Before you can use the NLPearl.AI API, you need to select a subscription plan that suits your needs. See [Billing](/pages/billing) to view and choose the plan that best fits your requirements. ### Step 2: Create Your Credentials To interact with the NLPearl.AI API, you need credentials. Open **Settings** on the platform, select the **API Access** page, and create one of the two: * An [**API secret key**](/api-reference/api_secret_key) - full access to your workspace, for code you own and run yourself. Store it securely. * An [**OAuth 2.0 app**](/api-reference/oauth) - a Client ID and Client Secret with only the [scopes](/api-reference/oauth#scopes) you select, for a third-party integration or an app that should reach only part of your workspace. If you are not sure, start with an API secret key and follow the steps below. ### Step 3: Find Your Account ID Your Account ID is required to authenticate with an API secret key. Open **Settings**, then **General Settings**, and copy it from the **Account ID** field. (An OAuth 2.0 app does not need it - the workspace is already part of its access token.) ### Step 4: Set Up API Authentication To authenticate your API requests, include your credentials in the header of each request. Check the guide that matches the credentials you created: Send your Account ID and secret key as a bearer token. Request an access token and scope what an integration can reach. ## Conclusion Starting with the NLPearl.AI API is easy and straightforward. By following these steps, you can quickly set up your account and begin integrating powerful AI capabilities into your applications. # API Secret Key Source: https://developers.nlpearl.ai/api-reference/api_secret_key Authenticate your own backend code with one key: your Account ID and a secret key, sent as a bearer token. Handing access to someone else? An **OAuth 2.0 app** has its own client ID and secret, reaches only the scopes you grant it, and can be rotated on its own - see [OAuth 2.0](/api-reference/oauth). ## Overview An API secret key is the simplest way to call the NLPearl API: one key, created in your workspace settings, sent on every request. It carries **full access** to the workspace, which makes it the right credential for code you own and run yourself, and the wrong one to give to a third party. API keys live on the **API Access** page of your workspace settings. Creating one requires an active subscription. *** ## Creating an API Key Click your **profile card** at the bottom-left corner of the sidebar, open **Settings**, then select **API Access** in the settings menu. You can also go there directly: [platform.nlpearl.ai/app/settings/api](https://platform.nlpearl.ai/app/settings/api). Click **Create API Key**. The window that opens holds a **Name** and the **Secret Key** itself. Give it a name that identifies where the key will be used - up to 15 characters - then copy the secret key with the button at the end of the field. Click **Create Key**. The key appears in the credentials list, marked with a key glyph and showing its first characters. You can copy a key again at any time with the **copy** button on its row, and the **delete** button revokes it immediately. A secret key carries **full access** to your workspace and cannot be restricted to part of it. Keep it server-side, never ship it in a browser, a mobile app or a public repository, and never share it with a third party - create an [OAuth 2.0 app](/api-reference/oauth) for that instead. *** ## Finding Your Account ID The header carries two values: your Account ID and the secret key. The **Account ID** identifies your workspace and is on the **General Settings** page of your workspace settings, under that name. It is also shown, with a copy button, in the workspace switcher. *** ## Authorization Header Send both values as a bearer token, separated by a colon: ```http theme={null} Authorization: Bearer AccountId:SecretKey ``` For example: ```http theme={null} Authorization: Bearer 66552698d60e456235eae520:tWPqr5EEZv2dxqutv58NsCg7NuqGc1tX ``` ### Example request ```bash theme={null} curl -X GET "https://api.nlpearl.ai/v2/Pearl" \ -H "Authorization: Bearer 66552698d60e456235eae520:tWPqr5EEZv2dxqutv58NsCg7NuqGc1tX" ``` Replace `66552698d60e456235eae520` with your Account ID and `tWPqr5EEZv2dxqutv58NsCg7NuqGc1tX` with your secret key. The key does not expire and there is no token to request first: send the same header on every call. Deleting the key on the API Access page is what ends its access. *** ## Errors | Status | Meaning | | ------ | -------------------------------------------------------------------------------------------------------------------------- | | `401` | The `Authorization` header is missing or malformed, the Account ID and key do not belong together, or the key was deleted. | # API Authorization Source: https://developers.nlpearl.ai/api-reference/authorization Every API request carries an Authorization header. Choose the credential that matches who is making the calls. ## API Authorization Guide Every request to the NLPearl API must carry an `Authorization` header. There are two kinds of credential behind it, and both are accepted on every `/v2` endpoint - so an integration built against one works against the other without changing a single call. One key with full access to your workspace. Best for **your own** backend code. An app with its own client ID and secret, limited to the **scopes** you grant and rotatable on its own. Best for a **third-party** integration. *** ## Choosing Between Them | | API secret key | OAuth 2.0 app | | -------------------- | ------------------------------------------ | ------------------------------------------------------------------ | | What you send | `Bearer AccountId:SecretKey` on every call | `Bearer `, after requesting a token | | Reach | The whole workspace, always | Only the scopes you granted the app | | Lifetime | The key does not expire | Access tokens last one hour; request a new one when they expire | | If the secret leaks | Delete the key and create a new one | Rotate the app's secret; its client ID and scopes stay as they are | | Readable again later | Yes, copy it from the credentials list | No, the client secret is shown once | Both are created on the **API Access** page of your workspace settings, and creating either one requires an active subscription. *** ## Next Steps Set up your account and make your first API call. Call the API from Python without writing the HTTP layer yourself. # Building a Pearl Flow Source: https://developers.nlpearl.ai/api-reference/building_a_flow How to build a Pearl as a graph of nodes and transitions through the API, for both Voice and Text. A **Pearl** can be driven in one of two ways: * A **Simple Pearl**: a single opening sentence plus a flow script. Created with [Create Pearl](/api-reference/v2/pearlFlow/add-pearl-flow). * 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. This page explains the node logic: how nodes connect, how the entry point and IDs work, how transitions branch, and what differs between the **Voice** and **Text** channels. Endpoints for node-graph Pearls: * **Voice**: [Create Voice Pearl](/api-reference/v2/pearlFlow/add-voice-pearl), [Update Voice Pearl](/api-reference/v2/pearlFlow/update-voice-pearl) * **Text**: [Create Text Pearl](/api-reference/v2/pearlFlow/add-text-pearl), [Update Text Pearl](/api-reference/v2/pearlFlow/update-text-pearl) * **Read back**: [Get Pearl Settings](/api-reference/v2/pearlFlow/get-pearl-flow) *** ## 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. You send the whole graph in the `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 a `nodeType` (an integer). This is the single most important field: it decides what the node does and which settings object it must carry. | `nodeType` | Name | Channel | Carries | | ---------- | ------------------- | -------------------------- | --------------------------------------------------- | | `2` | OpeningSentence | Both | `script` (+ optional `instructions`) | | `3` | PreCallAPI | Both | `apiSettings` | | `10` | Dialogue | Both | `script` (+ optional `instructions`) | | `31` | HandoffChatToHuman | **Text only** | `handOffAction` (+ optional `script`) | | `40` | API | Both | `apiSettings` | | `50` | SMS | **Voice only** (as a node) | `smsSettings` | | `51` | Email | Both | `emailSettings` | | `60` | TransferCall | **Voice only** | `transferCallSettings` | | `65` | StartCallRecording | **Voice only** | nothing (its presence is the whole configuration) | | `80` | SearchKnowledgeBase | Both | searches the knowledge base, branches on the result | | `100` | EndCall | Both | transitions to post-call containers only | | `200` | PostCallActions | Both | `postCallActions` (a container of actions) | 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 ```json theme={null} { "nodeId": "triage", "name": "Triage the caller", "nodeType": 10, "script": "Are you calling to book a new appointment or to reschedule an existing one?", "instructions": "Stay friendly. If the caller is unsure, briefly explain both options.", "transitions": [ { "name": "Wants to book", "toNodeId": "booking" }, { "name": "Wants to reschedule", "toNodeId": "reschedule" } ] } ``` | Field | Meaning | | ------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------- | | `nodeId` | **You choose it.** A unique ID for the node within the flow. Transitions reference it. | | `name` | A human-readable label for the node (shown in the editor). | | `nodeType` | What the node does (see the table above). | | `transitions` | The outgoing edges. Each has a `name` (the condition) and a `toNodeId` (the target). | | `script` | `🧩 May support variables` The text for OpeningSentence and Dialogue nodes. | | `instructions` | `🧩 May support variables` Optional guidance on tone, exceptions, and how closely to follow the script. | | `apiSettings` / `smsSettings` / `emailSettings` / `transferCallSettings` | The settings object matching the node type. | | `handOffAction` / `postCallActions` | Nested lists of action nodes (see below). | Only fields marked `🧩 May support variables` accept the `{variableId}` syntax. See [Flow Variables](/api-reference/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 through `toNodeId`, which must equal that node's `nodeId`. * The `nodeId` must be **unique** within the flow and is capped at **20 characters**. The `name` does **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 `nodeId` or `name`, and the platform derives the missing one.** Send only a `nodeId` and the `name` is generated from it (`verifyCustomer` → "Verify Customer", `endCall` → "End Call"); send only a `name` and the `nodeId` is generated from it in camelCase ("Verify Customer" → `verifyCustomer`). Send neither and the request is rejected. A name-only node gets an **auto-generated `nodeId`** (the camelCase of its `name`, made unique). Because a transition's `toNodeId` must match that id, any node another node points to should carry an explicit `nodeId`, it is the robust path and you still get the `name` for free. Deriving the id from the name is most convenient for nodes nothing transitions to (post-call actions, hand-off sub-actions). ### Transition IDs: you do NOT provide them A transition only needs two things from you: | Field | Meaning | | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | | `name` | `🧩 May support variables` The condition, written in plain language ("Caller is a VIP", "Wants to reschedule", "Always"). Must be unique within the node. | | `toNodeId` | The `nodeId` this transition leads to. | 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. Write transition names as readable **conditions**, not code. Use "Age greater than 60", not `{customerAge} > 60`. **A single transition:** ```json theme={null} { "name": "Wants to reschedule", "toNodeId": "reschedule" } ``` *** ## The opening Every flow needs an entry point. In most flows that is a single **OpeningSentence** node (`nodeType: 2`). ```json theme={null} { "nodeId": "opening", "name": "Greeting", "nodeType": 2, "script": "Hi {firstName}, this is {agentName} from Bright Dental. How can I help you today?", "transitions": [ { "name": "Caller states their reason", "toNodeId": "triage" } ] } ``` **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. Because of this, the opening rules are strict: * **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` | Meaning | Generated transition ID | | ----------- | --------------------------------------------- | ----------------------- | | `1` | Success (the API call succeeded) | `sapisuccess` | | `2` | Failure (the call failed or returned nothing) | `sapinotsuccess` | `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. **One opening (continue on both outcomes):** the Success transition leads to the opening. A Failure transition, if present, must point at that same opening. **Two openings (branch on the outcome):** the Success transition leads to the "known customer" opening, the Failure transition to the "unknown customer" opening. They must point at two different OpeningSentence nodes. ```json theme={null} { "nodeId": "lookup", "name": "Customer lookup", "nodeType": 3, "apiSettings": { "name": "Find customer", "method": 1, "endpointUrl": "https://crm.example.com/customers?phone={phoneNumber}", "description": "Looks up the caller by phone number before greeting.", "outputBody": [ { "key": "firstName", "variableId": "firstName" } ] }, "transitions": [ { "name": "Customer found", "toNodeId": "openingKnown", "apiResult": 1 }, { "name": "Customer not found", "toNodeId": "openingUnknown", "apiResult": 2 } ] } ``` Here `method: 1` is a GET (see the method codes under [Action nodes](#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. A simple linear chain looks like this (order in the array does not matter, the `toNodeId` links do the wiring): ```json theme={null} "nodes": [ { "nodeId": "opening", "name": "Greeting", "nodeType": 2, "script": "Hi {firstName}, how can I help?", "transitions": [ { "name": "Continue", "toNodeId": "triage" } ] }, { "nodeId": "triage", "name": "Triage", "nodeType": 10, "script": "Do you want to book or reschedule?", "transitions": [ { "name": "Wants to book", "toNodeId": "booking" }, { "name": "Wants to reschedule", "toNodeId": "endCall" } ] }, { "nodeId": "booking", "name": "Take the booking", "nodeType": 10, "script": "Great, what day works best for you?", "transitions": [ { "name": "Continue", "toNodeId": "endCall" } ] }, { "nodeId": "endCall", "name": "End", "nodeType": 100, "transitions": [] } ] ``` Give the EndCall node a stable ID like `endCall` and point every terminal branch at it. It keeps the graph easy to reason about, and every action node (transfer, SMS, email) should ultimately continue to it. *** ## Action nodes Action nodes do work instead of talking. Each carries the settings object that matches its `nodeType`. | Node | `nodeType` | Settings object | Notes | | ------------------ | ---------- | ---------------------- | ---------------------------------------------------------- | | API | `40` | `apiSettings` | Calls an HTTP endpoint mid-conversation. | | SMS | `50` | `smsSettings` | Voice only as a standalone node. | | Email | `51` | `emailSettings` | Sends an email. | | TransferCall | `60` | `transferCallSettings` | Voice only. Hands the call to a phone number. | | StartCallRecording | `65` | none | Voice only. Its presence starts recording from that point. | `apiSettings` (`method` codes: `1` GET, `2` POST, `3` PUT, `4` DELETE, `5` PATCH): ```json theme={null} { "nodeId": "checkAvail", "name": "Check availability", "nodeType": 40, "apiSettings": { "name": "Availability", "method": 1, "endpointUrl": "https://booking.example.com/slots?day={preferredDay}", "description": "Returns open appointment slots for the requested day.", "outputBody": [ { "key": "slots", "variableId": "availableSlots" } ] }, "transitions": [ { "name": "Slots available", "toNodeId": "confirm" }, { "name": "No slots", "toNodeId": "offerCallback" } ] } ``` 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](/pages/api_action) guide and [Flow Variables](/api-reference/flow_variables). ### TransferCall: wired vs floating (Voice) A TransferCall node behaves differently depending on how it is reached, and this changes whether `triggerDescription` is required: | The transfer node is... | `triggerDescription` | Behavior | | ------------------------------------------------- | -------------------- | --------------------------------------------------------------------------------------------- | | **Wired** (another node has a transition into it) | **Not allowed** | The flow decides when the transfer happens. | | **Floating** (no incoming transition) | **Required** | The agent fires the transfer on its own, based on the description, from anywhere in the call. | ```json theme={null} { "nodeId": "toBilling", "name": "Transfer to billing", "nodeType": 60, "transferCallSettings": { "transferCallPhoneNumber": "+12125551234" }, "transitions": [ { "name": "Continue", "toNodeId": "endCall" } ] } ``` 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: 1. A **PostCallActions container** node (`nodeType: 200`) whose `postCallActions` array holds the actual action nodes (API `40`, Email `51`, and on Voice also SMS `50`). These inner nodes have **no transitions**. 2. The **EndCall** node's transitions, which point at those containers. **This is the only place EndCall may transition to.** Each transition `name` is the **condition** under which that container fires. When the call ends, the platform evaluates all of EndCall's transitions at once. Each condition that is true triggers its container, and multiple containers can fire in parallel (logical OR). Use a transition named "Always" for a container that should run on every call. ```json theme={null} "nodes": [ { "nodeId": "endCall", "name": "End", "nodeType": 100, "transitions": [ { "name": "Appointment booked", "toNodeId": "postBooked" }, { "name": "Always", "toNodeId": "postLog" } ] }, { "nodeId": "postBooked", "name": "Booking actions", "nodeType": 200, "postCallActions": [ { "nodeId": "crmLog", "name": "Update CRM", "nodeType": 40, "apiSettings": { "name": "Log booking", "method": 2, "endpointUrl": "https://crm.example.com/bookings", "description": "Records the booking after the call.", "body": [ { "key": "phone", "variableId": "phoneNumber" }, { "key": "summary", "variableId": "post_call_summary" } ] } } ] }, { "nodeId": "postLog", "name": "Always-on recap", "nodeType": 200, "postCallActions": [ { "nodeId": "emailRecap", "name": "Email recap", "nodeType": 51, "emailSettings": { "to": ["ops@example.com"], "subject": "Call recap for {firstName}", "body": "Summary: {post_call_summary}" } } ] } ] ``` 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](/api-reference/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. | | Voice Pearl | Text Pearl | | ------------------- | ----------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | | Endpoint | [Create Voice Pearl](/api-reference/v2/pearlFlow/add-voice-pearl) | [Create Text Pearl](/api-reference/v2/pearlFlow/add-text-pearl) | | Model (`modelType`) | `1` Trident, `2` Oyster, `3` Arrow, `4` Hydra (defaults to Arrow) | `11` Swan only | | Agent identity | `agents` (voice agents, one per language) + `speechRecognitionKeywords` | `agentName` (single text agent, all languages natively) | | Human escalation | TransferCall node (`60`) to a phone number | HandoffChatToHuman node (`31`) | | Voice-only nodes | SMS (`50`), TransferCall (`60`), StartCallRecording (`65`) | not available | | Text-only nodes | not available | HandoffChatToHuman (`31`) | | SMS | a standalone SMS node (`50`) | **only inside a Hand-Off** (as a sub-action), never as a standalone node or post-call action | | Channel binding | phone number is assigned on the platform | `textChannelId` on the inbound/outbound settings (from [Get Text Channels](/api-reference/v2/pearlSettings/get-text-channels)) | ### The Hand-Off node (Text) The Text equivalent of a transfer. It hands the conversation to a human and can fire inline notifications through its `handOffAction` 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. ```json theme={null} { "nodeId": "handoff", "name": "Escalate to a human", "nodeType": 31, "script": "Connecting you with a teammate now, one moment.", "transitions": [ { "name": "Continue", "toNodeId": "endCall" } ], "handOffAction": [ { "nodeId": "notifyTeam", "name": "Email the team", "nodeType": 51, "emailSettings": { "to": ["support@example.com"], "subject": "Human requested in chat", "body": "Customer {firstName} asked for a human." } } ] } ``` `script` on a Hand-Off is the last line the agent sends before it stops replying. Leave it empty for a silent hand-off. See the [Hand-Off node](/pages/text/handoff_action) guide for the full behavior. *** ## 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): ```json theme={null} { "name": "Bright Dental Reception", "pearl": { "companyName": "Bright Dental", "agentPersonality": "Warm and professional", "modelType": 3, "agents": [ /* voice agents (Voice), or use agentName for Text */ ], "nodes": [ /* the full node graph */ ] }, "variables": [ /* your flow variables, see Flow Variables */ ], "inbound": { /* OR "outbound": provide exactly one */ } } ``` * Provide **exactly one** channel: `inbound` **or** `outbound`, never both. * For a Text Pearl, put the `textChannelId` on the `inbound`/`outbound` settings. * `variables` defines the flow variables; keep it minimal and only include what you reference. See [Flow Variables](/api-reference/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](/api-reference/v2/pearlFlow/update-voice-pearl), [Update Text Pearl](/api-reference/v2/pearlFlow/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. | Part of the request | Behavior on update | | ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `pearl` | **Full replacement.** If you send `pearl`, you send the **complete node graph**, it replaces the existing one entirely. Omit `pearl` to leave the flow untouched. | | `inbound` / `outbound` | **Partial patch.** Only the fields you include are changed; every field you omit keeps its current value. | | `name`, `variables` | Applied when provided. | There is no partial edit of a single node. To change one node you resend the entire `pearl.nodes` graph. Fetch the current graph first with [Get Pearl Settings](/api-reference/v2/pearlFlow/get-pearl-flow), modify it, and send it back. 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 `apiResult` and lead to OpeningSentence nodes. * [ ] Every `nodeId` is **unique** and every `toNodeId` points 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. * [ ] `apiResult` only 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 The `{variableId}` syntax, variable groups, and built-in variables. Request body, headers, credentials, and response output schema. Read the current flow back before updating it. Escalate a Text conversation to a human. # Pearl Flow Variables Guidance Source: https://developers.nlpearl.ai/api-reference/flow_variables API variables are placeholders you can embed in specific Pearl Flow fields to make your configuration dynamic (scripts, endpoints, messages, and notifications). Whenever a field is labeled: `🧩 May support variables` you can insert variables using this syntax: ```text theme={null} {variableId} ``` Example: ```text theme={null} Hello {firstName}, this is {agentName}. ``` *** ## Variable Groups Variables belong to one of three groups. ### Pre-call variables (Group = `PreCall`) Pre-call variables are expected to be available **before** the call starts (for example from your lead import, CSV mapping, or an API integration). If a pre-call value is missing, it’s not always blocking, depending on your flow, the agent may still collect it during the call. Common usage: * Opening sentence * Pre-call API actions * Endpoint URLs and message templates (when supported) **Opening sentence example (pre-call only):** ```text theme={null} Hello, I’m {agentName}. Am I speaking with {firstName}? ``` *** ### In-call variables (Group = `InCall`) In-call variables are collected or updated **during** the call. Common usage: * In-call API actions * Email/SMS templates (when supported) * Flow scripts (when supported) **Script example (collecting an in-call variable):** ```text theme={null} Please tell me your address. I will store it as {customerAddress}. ``` *** ### Post-call variables (Group = `PostCall`) Post-call variables are generated **after** the call ends (transcript, summary, duration, etc.). You **cannot create** post-call variables manually, as they are pre-defined by the platform. Common usage: * End-call notifications (Email / API) *** ## Built-in Variables (Reserved IDs) Some variables are built into the platform and already exist by default. Because they are reserved, \*\*you cannot create a new variable using the same `id**` as a built-in variable. If you try, the API will reject it as a duplicate ID. ### Built-in Pre-call Variables | ID | Name | Description | | ------------------ | ------------------ | ------------------------------------------------------------------------------------------------------------- | | `agentName` | Agent Name | The name of the agent. | | `agentPhoneNumber` | Agent Phone Number | The Pearl's own phone line for the current conversation. Read-only; empty on channels without a phone number. | | `firstName` | First Name | The customer's first name formatted as a proper first name. | | `lastName` | Last Name | The customer's last name formatted as a proper last name. | | `emailAddress` | Email Address | The customer's email address in a standard format (RFC 5321 / RFC 5322). | | `phoneNumber` | Phone Number | The customer's phone number with country code (digits + optional `+`). | | `callId` | Call ID | The identifier of the call. | `agentPhoneNumber` is empty on channels without a phone number, including Telegram and browser Test Chat. An API node does not execute when it references an empty required pre-call variable, so only use this variable in API nodes for channels that have a phone number. ### Built-in In-call Variables There are currently **no built-in in-call variables**. In-call variables are typically created per Pearl to match what you want to collect during the conversation. ### Built-in Post-call Variables | ID | Name | Description | | ---------------------- | --------------- | -------------------------------------------- | | `post_call_duration` | Call Duration | Duration of the call. | | `post_call_summary` | Call Summary | Summary generated after the call concludes. | | `post_call_transcript` | Call Transcript | Transcript of the call for reference. | | `post_call_call_time` | Call Time | Timestamp indicating when the call occurred. | | `post_call_recording` | Recording Link | Link to the call recording. | *** ## Where Variables Are Supported Only fields explicitly marked with: `🧩 May support variables` support the `{variableId}` syntax. Typical examples include: * Flow scripts (when enabled) * API endpoint URLs * API body values (when the body field is a string) * API response output paths (the **JSON Path** column of a Response Output Schema) — not labeled, see the note below * SMS / Email templates (depending on the action timing) * End-call notifications (supports post-call variables) Only fields that support variables will be labeled with `🧩 May support variables`. If the field is not labeled, assume it is static-only. The one exception is the **JSON Path** column of an API action's Response Output Schema: it carries no label, but it does accept `{variableId}` placeholders. See [Using variables in API response output paths](#4-use-variables-in-api-response-output-paths). *** ## Using Variables in API Requests ### 1) Use variables inside scripts Example script snippet: ```text theme={null} Ask the caller for their address and store it in {customerAddress}. If {customerAddress} is empty, ask again politely. ``` *** ### 2) Use variables in API action endpoint URLs Example: ```text theme={null} https://example-crm.com/leads?phone={phoneNumber}&name={firstName} ``` *** ### 3) Use variables in API action body values (string) If a body field is a string value, it can include variables: ```json theme={null} { "key": "message", "type": "String", "value": "New call completed for {firstName} {lastName}." } ``` **API Body Exception (VariableId field)** When configuring an API action body, the `VariableId` property must contain the **raw variable ID without brackets**. Example: use `firstName` (not `{firstName}`). This is a special case for the API body schema only. Everywhere else, variables are inserted using `{variableId}`. *** ### 4) Use variables in API response output paths The **JSON Path** column of a [Response Output Schema](/pages/api_action#path-syntax) accepts variables, so the value you extract can depend on what the conversation has already collected. Example path: ```text theme={null} collection[?(@.start_time startswith '{preferredDateIso}')][0].start_time ``` The placeholder is replaced with the variable's current value before the API response is read. *** ### 5) Use post-call variables in End-call notifications Example email body: ```text theme={null} Call ended for {firstName} {lastName}. Summary: {post_call_summary} Transcript: {post_call_transcript} Recording: {post_call_recording} Duration: {post_call_duration} ``` *** ## Best Practices * Use short, stable variable IDs (e.g., `customerAddress`, `membershipStatus`). * Treat built-in variable IDs as reserved keywords. * Use post-call variables only in end-call notifications. * Avoid defining variables you never reference in your flow. *** ## Quick Reference * **Syntax:** `{variableId}` * **Groups:** `PreCall` / `InCall` / `PostCall` * **Built-in InCall variables:** none * **Post-call variables:** available inside end-call notifications only # OAuth 2.0 Source: https://developers.nlpearl.ai/api-reference/oauth Give an integration its own credential: a client ID and secret, only the scopes you grant it, and a secret you can rotate on your own. Looking for the simpler scheme? An **API key** is one secret with full access to your workspace, best for your own backend code - see [API Secret Key](/api-reference/api_secret_key). ## Overview An **OAuth 2.0 app** is a credential with a client ID, a client secret you can rotate, and a set of scopes that decide exactly what it may reach. NLPearl implements the **client credentials** grant: the app authenticates with its own credentials and receives an access token limited to the scopes you granted it. There is no redirect, no login screen and no end user in the loop - it is machine-to-machine authentication. OAuth 2.0 apps and API keys both live on the **API Access** page of your workspace settings. Creating either one requires an active subscription. *** ## Creating an OAuth 2.0 App Click your **profile card** at the bottom-left corner of the sidebar, open **Settings**, then select **API Access** in the settings menu. You can also go there directly: [platform.nlpearl.ai/app/settings/api](https://platform.nlpearl.ai/app/settings/api). API Access page with the Create OAuth 2.0 App button Click **Create OAuth 2.0 App**. The window that opens holds everything the app is made of: a **Name**, its **Client ID** and **Client Secret**, and the **Scopes** it is allowed to use. Create OAuth 2.0 App dialog Give it a name that identifies the integration. Then select its scopes, grouped under **Pearls**, **Account** and **Billing**. Grant the fewest the integration actually needs. Both are already filled in, above the scopes - copy them and only then click **Create App**. **The client secret is shown once, in that window** - reopening the app later shows only its first characters. Treat it as a password: keep it server-side, never ship it in a browser, a mobile app or a public repository. If you lose it or it leaks, [rotate it](#rotating-the-client-secret). *** ## Requesting an Access Token ```http theme={null} POST https://api.nlpearl.ai/oauth/token Content-Type: application/x-www-form-urlencoded ``` The token endpoint sits at the **root** of the API host. Unlike every other Client API route, it is **not** under `/v2`. ### Request parameters | Parameter | Required | Description | | --------------- | -------- | --------------------------------------------------------------------------------------------- | | `grant_type` | Yes | Must be `client_credentials`. No other grant type is supported. | | `client_id` | Yes | Your app's Client ID. | | `client_secret` | Yes | Your app's Client Secret. | | `scope` | No | Space-separated list of scopes to request. Omit it to receive every scope granted to the app. | Your credentials can be sent either in the request body or in an HTTP Basic header. Both methods are supported and issue the same token. Also known as `client_secret_post`. ```bash theme={null} curl -X POST "https://api.nlpearl.ai/oauth/token" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "grant_type=client_credentials" \ -d "client_id=6a6c72b69b39e6add21204e7" \ -d "client_secret=YOUR_CLIENT_SECRET" ``` Also known as `client_secret_basic`. The header value is `base64(client_id:client_secret)`. ```bash theme={null} curl -X POST "https://api.nlpearl.ai/oauth/token" \ -H "Content-Type: application/x-www-form-urlencoded" \ -u "6a6c72b69b39e6add21204e7:YOUR_CLIENT_SECRET" \ -d "grant_type=client_credentials" ``` Send your credentials **one way or the other, never both**. A request carrying a Basic header *and* a `client_secret` in the body is rejected with `400 invalid_request`. ### Response ```json theme={null} { "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...", "token_type": "Bearer", "expires_in": 3600, "scope": "pearls:read pearls:calls pearls:analytics" } ``` | Field | Description | | -------------- | --------------------------------------------------------------------------------- | | `access_token` | The token to send on your API calls. | | `token_type` | Always `Bearer`. | | `expires_in` | Token lifetime in seconds - **3600**, one hour. | | `scope` | The scopes actually granted to this token. Read it to know what the token can do. | There is **no refresh token**. When a token expires, request a new one with the same credentials. **Cache the token and reuse it** for its whole lifetime. Do not request a new one on every API call. *** ## Calling the API Send the access token as a bearer token on any `/v2` endpoint: ```bash theme={null} curl -X GET "https://api.nlpearl.ai/v2/Pearl" \ -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..." ``` There is no `AccountId:` prefix here, unlike the [secret key scheme](/api-reference/api_secret_key) - the workspace the token belongs to is already part of the token. *** ## Scopes A scope is a permission. An app only reaches what its scopes allow; everything else is refused with `403`. The tables below map every checkbox in the **OAuth 2.0 App** window - grouped **Pearls**, **Account** and **Billing**, exactly as the platform groups them - to the scope string it produces in the token. ### Pearls | In the platform | Scope | What it reaches | | ------------------------------------------------------ | ------------------ | --------------------------------------------------------------------------------------------- | | View pearls | `pearls:read` | Listing Pearls, inbounds and campaigns, and reading one of them | | Create and edit, including access to PearlVibe | `pearls:write` | Creating and updating Pearls, conversation flows, voice and text settings, and the voice list | | Moderate activity status - Allow changing pearl status | `pearls:moderate` | Running and pausing a Pearl, resetting customer memory | | View analytics | `pearls:analytics` | Pearl, inbound and outbound analytics | | View and moderate leads | `pearls:leads` | Reading, adding, updating and deleting outbound leads | | View calls and post-call information | `pearls:calls` | Calls and recordings, placing and deleting calls, call requests | **Any Pearls scope also grants `pearls:read`.** Every integration needs to list Pearls to resolve their ids, so selecting *View calls* alone still yields `pearls:read pearls:calls` - you will see it in the token's `scope`. ### Account | In the platform | Scope | What it reaches | | --------------------------------------------------- | ----------------------- | --------------------------------------------- | | Manage phone numbers | `account:phone_numbers` | The account's phone numbers and text channels | | Manage users | `account:users` | The account's users | | Manage advanced settings - security, sessions, etc. | `account:advanced` | The account blacklist: search, add, remove | | View audit log | `account:audit_log` | The audit log | `GET /v2/Account/Voices` sits under `pearls:write`, not under an account scope: the list of voices is part of building a Pearl. ### Billing | In the platform | Scope | What it reaches | | ---------------------- | ----------------- | ---------------------------------------------------------- | | Manage account billing | `account:billing` | Account information and credit balance - `GET /v2/Account` | ### Changing an app's scopes Open the app with the **edit** button, tick or untick scopes, then click **Save Scopes**. Edit OAuth 2.0 App scopes Scope changes apply to **newly issued tokens**. A token issued before the change keeps the scopes it was created with until it expires. *** ## Errors ### Token endpoint | Status | `error` | When | | ------ | ------------------------ | --------------------------------------------------------------------------------------- | | `400` | `invalid_request` | `grant_type` is missing, or credentials were sent in the Basic header **and** the body. | | `400` | `unsupported_grant_type` | `grant_type` is anything other than `client_credentials`. | | `400` | `invalid_scope` | A requested `scope` is not a known scope string, or is one the app was not granted. | | `401` | `invalid_client` | Unknown `client_id`, wrong `client_secret`, or the app was deleted. | | `405` | - | The endpoint only accepts `POST`. | Every error comes back as JSON: ```json theme={null} { "error": "invalid_client", "error_description": "Client authentication failed" } ``` ### API endpoints | Status | Meaning | | ------ | ------------------------------------------------------------------ | | `401` | The token is missing, malformed, or expired. Request a new token. | | `403` | The token is valid but **lacks the scope** this endpoint requires. | A `403` carries a challenge header and a machine-readable body: ```http theme={null} HTTP/1.1 403 Forbidden WWW-Authenticate: Bearer error="insufficient_scope", error_description="The token does not carry the scope required by this endpoint" ``` ```json theme={null} { "error": "insufficient_scope", "error_description": "The token does not carry the scope required by this endpoint" } ``` Handle `403` and `401` differently. A `401` means *get a new token*; a `403` means *this app was never granted the scope* - requesting another token will return the same result. Retrying a `403` in a loop will never succeed. *** ## Rotating the Client Secret Rotation replaces an app's secret without changing its Client ID, its scopes, or anything else about it. Use it when a secret may have been exposed, or as routine hygiene. On the **API Access** page, open the OAuth 2.0 app with the **edit** button. Click the **rotate** button next to **Client Secret**. The new secret replaces the masked one in the field - copy it before closing the window. The previous secret stops working as soon as you rotate. Every integration using it must be updated with the new secret, or it will start receiving `401 invalid_client`. Access tokens that were already issued stay valid until they expire - rotation blocks new tokens, it does not revoke the ones already in circulation. To cut an integration off immediately, delete the app with the **delete** button on the API Access page. *** ## Token Format and Discovery You do not need any of this to call the API, but it is there if your OAuth client expects it. Access tokens are **RS256-signed JWTs**. You can verify a token's signature against the public keys published in the JWKS below. | Claim | Value | | -------------------------- | ---------------------------------------------------- | | `iss`, `aud` | Both `https://api.nlpearl.ai` | | `sub` | The **Client ID** of the app the token was issued to | | `account_id` | The **Account ID** of your workspace | | `scope` | The granted scopes, space separated | | `jti`, `iat`, `nbf`, `exp` | Token id, issued-at, not-before and expiry | | Endpoint | Purpose | | -------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- | | [`https://api.nlpearl.ai/.well-known/oauth-authorization-server`](https://api.nlpearl.ai/.well-known/oauth-authorization-server) | Authorization server metadata: token endpoint, supported grant types and auth methods, full scope list. | | [`https://api.nlpearl.ai/.well-known/jwks.json`](https://api.nlpearl.ai/.well-known/jwks.json) | Public keys used to verify token signatures. | Both are public and require no authentication. # Python Wrapper Source: https://developers.nlpearl.ai/api-reference/python_wrapper Learn how to use the NLPearl Python wrapper to interact with the NLPearl API effortlessly. # NLPearl Python Wrapper The NLPearl Python wrapper provides a simple and intuitive way to interact with the NLPearl API directly from your Python applications. This package simplifies the integration of NLPearl's conversational AI capabilities into your projects. ## Installation Install the package via pip: ```bash theme={null} pip install nlpearl ``` You can find the package on PyPI: [NLPearl Python Wrapper on PyPI](https://pypi.org/project/nlpearl/) ## Getting Started Before using the `nlpearl` package, you need to obtain an API key from NLPearl. You can request one by contacting our support team. ### Setting Your API Key Set your API key before making any API calls: ```python theme={null} import nlpearl as pearl # Set your API key pearl.api_key = "your_api_key_here" ``` ## Usage Examples ### Retrieve Account Information ```python theme={null} import nlpearl as pearl # Set your API key pearl.api_key = "your_api_key_here" # Retrieve account information account_info = pearl.Account.get_account() print(account_info) ``` ### Make an Outbound Call ```python theme={null} import nlpearl as pearl # Set your API key pearl.api_key = "your_api_key_here" # Define the outbound ID and the phone number to call outbound_id = "your_outbound_id" phone_number = "+1234567890" # Make an outbound call call_response = pearl.Outbound.make_call( outbound_id, to=phone_number, call_data={"firstName": "John", "lastName": "Doe"} ) print(call_response) ``` These examples demonstrate how easy it is to integrate NLPearl's services into your Python applications using the `nlpearl` package. ## Additional Resources * [NLPearl Python Wrapper on PyPI](https://pypi.org/project/nlpearl/) * For detailed documentation on all available endpoints and functionalities, please refer to the endpoints documentation below. *** # Get Account Source: https://developers.nlpearl.ai/api-reference/v1/account/get-account get /v1/Account Retrieves account details # Delete Calls Source: https://developers.nlpearl.ai/api-reference/v1/call/delete-call delete /v1/Call Deletes one or more calls # Get Call Source: https://developers.nlpearl.ai/api-reference/v1/call/get-call get /v1/Call/{callId} Retrieves all the information about a call # Get Analytics Source: https://developers.nlpearl.ai/api-reference/v1/inbound/get-analytics post /v1/Inbound/{inboundId}/Analytics Retrieves analytics data for a specific inbound campaign within a given date range. # Get Inbound Source: https://developers.nlpearl.ai/api-reference/v1/inbound/get-inbound get /v1/Inbound/{inboundId} Retrieves a specific inbound by its ID # Get Inbound Ongoing Calls Source: https://developers.nlpearl.ai/api-reference/v1/inbound/get-inbound-ongoing-calls get /v1/Inbound/{inboundId}/OngoingCalls Returns the number of active calls currently in progress and in queue for the specified inbound ID. # Get Inbounds Source: https://developers.nlpearl.ai/api-reference/v1/inbound/get-inbounds get /v1/Inbound Retrieves all inbounds # Search Calls Source: https://developers.nlpearl.ai/api-reference/v1/inbound/search-calls post /v1/Inbound/{inboundId}/Calls Retrieves the calls within a specific date range of inbound # Set Activity State Source: https://developers.nlpearl.ai/api-reference/v1/inbound/set-activity-state post /v1/Inbound/{inboundId}/Active Run or Pause a specific inbound # Add Lead Source: https://developers.nlpearl.ai/api-reference/v1/outbound/add-lead put /v1/Outbound/{outboundId}/Lead Adds a new lead to a specified outbound # Delete Leads Source: https://developers.nlpearl.ai/api-reference/v1/outbound/delete-leads delete /v1/Outbound/{outboundId}/Leads Deletes one or more leads associated with a specific outbound campaign. # Delete leads Via External Source: https://developers.nlpearl.ai/api-reference/v1/outbound/delete-leads-external-id delete /v1/Outbound/{outboundId}/Leads/External Deletes one or more leads associated with a specific outbound campaign. # Get Analytics Source: https://developers.nlpearl.ai/api-reference/v1/outbound/get-analytics post /v1/Outbound/{outboundId}/Analytics Retrieves analytics data for a specific outbound campaign within a given date range. # Get Call Request Source: https://developers.nlpearl.ai/api-reference/v1/outbound/get-call-request get /v1/Outbound/CallRequest/{requestId} Fetches detailed information about a specific API request identified by its unique requestId. # Get Lead Source: https://developers.nlpearl.ai/api-reference/v1/outbound/get-lead get /v1/Outbound/{outboundId}/Lead/{leadId} Retrieves details of a specific lead within a outbound # Get Lead via External ID Source: https://developers.nlpearl.ai/api-reference/v1/outbound/get-lead-via-external-id get /v1/Outbound/{outboundId}/Lead/External/{externalId} Retrieves details of a specific lead within an outbound # Get Lead via Phone Number Source: https://developers.nlpearl.ai/api-reference/v1/outbound/get-lead-via-phone-number get /v1/Outbound/{outboundId}/Lead/PhoneNumber/{phoneNumber} Retrieves details of a specific lead within an outbound via phone number # Get Outbound Source: https://developers.nlpearl.ai/api-reference/v1/outbound/get-outbound get /v1/Outbound/{outboundId} Retrieve a specific outbound by its ID # Get Outbounds Source: https://developers.nlpearl.ai/api-reference/v1/outbound/get-outbounds get /v1/Outbound Retreive all the Outbounds # Make Call Source: https://developers.nlpearl.ai/api-reference/v1/outbound/make-call post /v1/Outbound/{outboundId}/Call Initiates an outbound phone call associated with the specified outbound ID. The request body must contain the necessary details for making the call. Once initiated, the call will be routed to the first available agent. # Search Call Requests Source: https://developers.nlpearl.ai/api-reference/v1/outbound/search-call-requests post /v1/Outbound/{outboundId}/CallRequest Fetches a list of API call requests associated with a specific outbound identifier. The search criteria, such as filters or pagination options, should be provided in the request body. # Search Calls Source: https://developers.nlpearl.ai/api-reference/v1/outbound/search-calls post /v1/Outbound/{outboundId}/Calls Retrieves the calls within a specific date range for a given outbound # Search Leads Source: https://developers.nlpearl.ai/api-reference/v1/outbound/search-leads post /v1/Outbound/{outboundId}/Leads Retrieves the leads associated with a specific outbound # Set Activity State Source: https://developers.nlpearl.ai/api-reference/v1/outbound/set-activity-state post /v1/Outbound/{outboundId}/Active Activates or deactivates a specified outbound # Update Lead Source: https://developers.nlpearl.ai/api-reference/v1/outbound/update-lead put /v1/Outbound/{outboundId}/Lead/{leadId} Updates the details of an existing lead associated with a specific outbound campaign. # Reset Customer Memory Source: https://developers.nlpearl.ai/api-reference/v1/pearl/reset-memory put /v1/Pearl/{pearlId}/Memory/{phoneNumber}/Reset Resets stored memory associated with a specific customer's phone number for a given Pearl. # Add Phone Numbers To Blacklist Source: https://developers.nlpearl.ai/api-reference/v2/account/add-to-blacklist post /v2/Account/Blacklist Adds one or more phone numbers to the account blacklist. # Get Account Source: https://developers.nlpearl.ai/api-reference/v2/account/get-account get /v2/Account Retrieves account details # Get Users Source: https://developers.nlpearl.ai/api-reference/v2/account/get-account-users get /v2/Account/Users Retrieves the list of users for the account # Get Audit Log Source: https://developers.nlpearl.ai/api-reference/v2/account/get-audit-log post /v2/Account/AuditLog Retrieves the audit log. # Remove Phone Numbers From Blacklist Source: https://developers.nlpearl.ai/api-reference/v2/account/remove-from-blacklist post /v2/Account/Blacklist/Remove Removes one or more phone numbers from the account blacklist. # Search Blacklist Source: https://developers.nlpearl.ai/api-reference/v2/account/search-blacklist post /v2/Account/Blacklist/Search Retrieves the paginated blacklist phone numbers of the account. # Delete Calls Source: https://developers.nlpearl.ai/api-reference/v2/call/delete-call delete /v2/Call Deletes one or more calls # Get Call Source: https://developers.nlpearl.ai/api-reference/v2/call/get-call get /v2/Call/{callId} Retrieves all the information about a call # Get Call Recording Source: https://developers.nlpearl.ai/api-reference/v2/call/get-recording get /v2/Recording/{clientId}/{pearlId}/{callId} Retrieves the audio recording for a specific call. If the client has public recordings enabled, the endpoint can be accessed anonymously; otherwise, a valid Authorization header matching the client is required. Recordings hosted on Twilio are returned as a permanent redirect, while recordings stored internally are converted from WAV to Opus (audio/ogg) and streamed back with range processing enabled for browser seeking. # Add Lead Source: https://developers.nlpearl.ai/api-reference/v2/outbound/add-lead post /v2/Outbound/{pearlId}/Lead Adds a new lead to a specified outbound # Add Leads Source: https://developers.nlpearl.ai/api-reference/v2/outbound/add-leads post /v2/Outbound/{pearlId}/Leads/Add Adds new leads to a specified outbound # Delete Leads Source: https://developers.nlpearl.ai/api-reference/v2/outbound/delete-leads delete /v2/Outbound/{pearlId}/Leads Deletes one or more leads associated with a specific outbound campaign. # Delete leads Via External Source: https://developers.nlpearl.ai/api-reference/v2/outbound/delete-leads-external-id delete /v2/Outbound/{pearlId}/Leads/External Deletes one or more leads associated with a specific outbound campaign. # Get Lead Source: https://developers.nlpearl.ai/api-reference/v2/outbound/get-lead get /v2/Outbound/{pearlId}/Lead/{leadId} Retrieves details of a specific lead within a outbound # Get Lead Via External ID Source: https://developers.nlpearl.ai/api-reference/v2/outbound/get-lead-via-external-id get /v2/Outbound/{pearlId}/Lead/External/{externalId} Retrieves details of a specific lead within an outbound # Find Lead Via Phone Number Source: https://developers.nlpearl.ai/api-reference/v2/outbound/get-lead-via-phone-number get /v2/Outbound/{pearlId}/Lead/PhoneNumber/{phoneNumber} Retrieves details of a specific lead within an outbound via phone number # Search Leads Source: https://developers.nlpearl.ai/api-reference/v2/outbound/search-leads post /v2/Outbound/{pearlId}/Leads Retrieves the leads associated with a specific outbound # Update Lead Source: https://developers.nlpearl.ai/api-reference/v2/outbound/update-lead put /v2/Outbound/{pearlId}/Lead/{leadId} Updates the details of an existing lead associated with a specific outbound campaign. # Get analytics Source: https://developers.nlpearl.ai/api-reference/v2/pearl/get-analytics post /v2/Pearl/{pearlId}/Analytics # Get Calls Source: https://developers.nlpearl.ai/api-reference/v2/pearl/get-calls post /v2/Pearl/{pearlId}/Calls Retrieves the calls within a specific date range of a pearl # Get Calls Bulk Source: https://developers.nlpearl.ai/api-reference/v2/pearl/get-calls-bulk post /v2/Pearl/{pearlId}/Calls/Bulk Retrieves calls within a date range like Get Calls, but lets the caller opt into additional fields (transcript, collected info, summary, recording, sentiment, credits, ...) via the Fields property. Only the requested fields are returned. # Get Ongoing Calls Source: https://developers.nlpearl.ai/api-reference/v2/pearl/get-ongoing-calls get /v2/Pearl/{pearlId}/OngoingCalls Returns the number of active calls currently in progress for the specified Pearl. If the Pearl has inbound configurations, it also returns the number of calls currently in queue. # Get Pearl Source: https://developers.nlpearl.ai/api-reference/v2/pearl/get-pearl get /v2/Pearl/{pearlId} Retrieves a specific Pearl by its ID # Get Pearls Source: https://developers.nlpearl.ai/api-reference/v2/pearl/get-pearls get /v2/Pearl Retrieves all Pearls # Reset Customer Memory Source: https://developers.nlpearl.ai/api-reference/v2/pearl/reset-memory put /v2/Pearl/{pearlId}/ResetMemory Resets stored memory associated with a specific customer's phone number for a given Pearl. # Set Activity State Source: https://developers.nlpearl.ai/api-reference/v2/pearl/set-activity-state put /v2/Pearl/{pearlId}/Active Run or Pause a specific Pearl # Create Pearl Source: https://developers.nlpearl.ai/api-reference/v2/pearlFlow/add-pearl-flow post /v2/Pearl Creates a new Simple Pearl, driven by an opening sentence and a flow script. Provide exactly one channel: inbound settings OR outbound settings. The Pearl is created already published: the configuration you send becomes its live (published) version. To create a Pearl (node graph), use Create Voice Pearl or Create Text Pearl instead. # Create Text Pearl Source: https://developers.nlpearl.ai/api-reference/v2/pearlFlow/add-text-pearl post /v2/Pearl/Text Creates a new text Pearl: the conversation is driven by a graph of nodes connected by transitions, and messages are exchanged over a text channel. Provide exactly one channel: inbound settings OR outbound settings, with the TextChannelId of the channel to use. To retrieve available text channels, use the Get Text Channels endpoint (GET /v2/Account/TextChannels). The Pearl is created already published: the configuration you send becomes its live (published) version. For more details, click [here](/api-reference/building_a_flow). # Create Voice Pearl Source: https://developers.nlpearl.ai/api-reference/v2/pearlFlow/add-voice-pearl post /v2/Pearl/Voice Creates a new voice Pearl: the conversation is driven by a graph of nodes connected by transitions. The graph must contain one OpeningSentence node (or a PreCallAPI leading to one or two OpeningSentence nodes), one EndCall node, and every node must be reachable. Provide exactly one channel: inbound settings OR outbound settings. At least one agent voice is required; to retrieve available voices, use the Get Voices endpoint (GET /v2/Account/Voices). The Pearl is created already published: the configuration you send becomes its live (published) version. For more details, click [here](/api-reference/building_a_flow). # Get Pearl Credentials Source: https://developers.nlpearl.ai/api-reference/v2/pearlFlow/get-pearl-credentials get /v2/Pearl/Credential/{pearlId} Retrieves the API credentials (Id and Name only) available to the specified Pearl. Use a returned Id as the CredentialId of an API action in the Pearl flow. # Get Pearl Settings Source: https://developers.nlpearl.ai/api-reference/v2/pearlFlow/get-pearl-flow get /v2/Pearl/{pearlId}/Settings Retrieves the Settings for the specified Pearl. The shape of the response depends on the Pearl: the Pearl section is a Simple Pearl configuration (opening sentence + flow script) or a Pearl configuration (node graph), and the Inbound/Outbound section carries the voice or the text settings according to the AgentType field (1 = Voice, 2 = Text). AgentType also tells you which update endpoint to use: Update Pearl (Simple Pearl), Update Voice Pearl, or Update Text Pearl. # Update Pearl Source: https://developers.nlpearl.ai/api-reference/v2/pearlFlow/update-pearl-flow put /v2/Pearl/{pearlId} Updates the configuration of a Simple Pearl (name, pearl settings and variables). The update applies to the published version of the Pearl: if several versions exist on the platform, only the currently published one is modified. For Pearls, use Update Voice Pearl or Update Text Pearl instead. # Update Inbound Settings Source: https://developers.nlpearl.ai/api-reference/v2/pearlFlow/update-pearl-inbound put /v2/Pearl/{pearlId}/Settings/Inbound Updates the inbound settings for the specified Pearl. The update applies to the published version of the Pearl: if several versions exist on the platform, only the currently published one is modified. # Update Outbound Settings Source: https://developers.nlpearl.ai/api-reference/v2/pearlFlow/update-pearl-outbound put /v2/Pearl/{pearlId}/Settings/Outbound Updates the outbound settings for the specified Pearl. The update applies to the published version of the Pearl: if several versions exist on the platform, only the currently published one is modified. # Update Text Pearl Source: https://developers.nlpearl.ai/api-reference/v2/pearlFlow/update-text-pearl put /v2/Pearl/Text/{pearlId} Updates a text Pearl. Only the provided parts are updated: pearl replaces the whole conversation flow (send the complete node graph), inbound/outbound partially update the channel settings (only the fields present in the JSON are applied; when TextChannelId is omitted, the current channel is kept). Omitted parts are kept unchanged. The Pearl must be a text Pearl (AgentType = Text). The update applies to the published version of the Pearl: if several versions exist on the platform, only the currently published one is modified. For more details, click [here](/api-reference/building_a_flow). # Update Voice Pearl Source: https://developers.nlpearl.ai/api-reference/v2/pearlFlow/update-voice-pearl put /v2/Pearl/Voice/{pearlId} Updates a voice Pearl. Only the provided parts are updated: pearl replaces the whole conversation flow (send the complete node graph), inbound/outbound partially update the channel settings (only the fields present in the JSON are applied). Omitted parts are kept unchanged. The Pearl must be a voice Pearl (AgentType = Voice). The update applies to the published version of the Pearl: if several versions exist on the platform, only the currently published one is modified. For more details, click [here](/api-reference/building_a_flow). # Get Phone Numbers Source: https://developers.nlpearl.ai/api-reference/v2/pearlSettings/get-phones get /v2/Account/PhoneNumbers Retrieves all active phone numbers of the account. # Get Text Channels Source: https://developers.nlpearl.ai/api-reference/v2/pearlSettings/get-text-channels get /v2/Account/TextChannels Retrieves the text channels available on the account (for example SMS-capable numbers or WhatsApp accounts). Use a returned channelId as the TextChannelId of the inbound/outbound settings when creating or updating a text Pearl. # Get Voices Source: https://developers.nlpearl.ai/api-reference/v2/pearlSettings/get-voices get /v2/Account/Voices Retrieves the available voices grouped by language. # Pearl Settings Source: https://developers.nlpearl.ai/pages/agent_customization
Pearl Settings cover
Pearl Settings cover
In this step, you can customize your voice agent's identity and behavior by setting its **name**, **language**, **voice**, **personality**, and **timezone**. *** ## Agent Names, Languages & Voices To define your agent's identity: * **(1) Agent Name** – Give your agent a name (e.g., *Joa*, *Victoria*). This name helps humanize the interaction and reflect your brand identity. * **(2) Language** – Select the default language your agent will speak. This ensures accurate pronunciation and localized expressions. * **(3) Voice** – Choose the voice that will represent your agent. You can preview voices and select the one that fits your tone. Agent Names, Languages & Voices section You can set up your Pearl to support multiple languages by adding several agent configurations, each with its own **name**, **language**, and **voice**. When a caller asks to switch language mid-conversation, Pearl automatically reroutes the call to the agent for that language. The **first agent** you create is the **Default Agent** and always opens the conversation, unless another language is requested. You can add more agents directly in the table. Explore [Voice and Language](/pages/languages) to view all the language options available. *** ## Pearl Model The **Pearl Model** defines the intelligence, speed, and cost profile of your agent. Voice agents can choose from four models. Pearl Model selection in Pearl Settings | Model | Quality | Speed | Cost | | ----------------- | --------------- | -------------- | -------------- | | **Pearl Hydra** | Highest Quality | Higher latency | +2 credits/min | | **Pearl Arrow** | Best Quality | Fastest | +2 credits/min | | **Pearl Trident** | Best Quality | Standard | Standard Rate | | **Pearl Oyster** | Good Quality | Standard | -2 credits/min | **Highest Quality · Higher latency · +2 credits/min** Our smartest model, built for demanding use cases that require deeper reasoning, stronger understanding, and the highest-quality responses. Use it when you need: * The deepest reasoning for complex, multi-step conversations. * Maximum nuance and understanding on high-stakes or ambiguous calls. * The best possible answer quality, even if it means slightly higher latency. **Best Quality · Fastest · +2 credits/min** Our high-intelligence model, offering the same depth as Pearl Trident but tuned for ultra-low latency. Use it when you need: * The snappiest real-time experience for callers. * Highly nuanced, human-like conversations. * VIP lines, complex sales calls, or high-stakes negotiations where every second of silence matters. **Best Quality · Standard Rate** Our most intelligent general-purpose model, designed for human-like conversations and handling complex use cases. Use it when you want: * A strong balance of quality vs cost. * Rich dialogues with multi-step reasoning and edge-case handling. * Your main production Pearl for most inbound and outbound flows. In most cases, Pearl Trident is the recommended default for production. **2 credits cheaper/min** Our most cost-effective model for straightforward cases, prioritizing simplicity and efficiency. Use it when you need: * High-volume or bulk campaigns (e.g. reminders, notifications, simple surveys). * Flows with predictable, scripted logic and limited branching. * To minimize cost while maintaining a solid conversational baseline. **Choosing the right model for your Pearl** When selecting a model, consider three main dimensions: | Dimension | Recommendation | | ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Speed** | If the caller experience must feel instant (no awkward silences, rapid back-and-forth), prefer Pearl Arrow. For standard conversational latency, Pearl Trident and Pearl Oyster are usually enough. | | **Reasoning / intelligence** | For the most demanding use cases that need the deepest reasoning, choose Pearl Hydra. For complex qualification, multi-step troubleshooting, or situations where the agent needs to "think", Pearl Trident or Pearl Arrow are strong choices. For simple flows with clear scripts and few edge cases, Pearl Oyster is more than sufficient. | | **Cost** | Pearl Arrow delivers top experience at a higher per-minute cost (+2 credits/min vs Trident). Pearl Trident offers best quality at a standard rate. Pearl Oyster is cheaper per minute (–2 credits/min vs Trident), ideal when cost per call is the main constraint. | You can use different models for different Pearls depending on their role, volume, and business impact (for example: Hydra for the most complex high-stakes calls, Arrow for VIP inbound support, Trident for main support, Oyster for large reminder campaigns). Start with Pearl Trident as a balanced default, then use Analytics to compare performance and cost. If you need more speed or nuance, move to Pearl Arrow; if you need to optimize budget for simple flows, switch to Pearl Oyster. *** ## Personality Your AI agent can take on a wide range of personalities, from natural and professional to wild, fictional, or downright iconic. Personality selection in Pearl Settings **Create your own personality.** You're not limited to the predefined list. Type any description in the **Personality** field and select **Use "\" as a custom personality** to define your own. Choose wisely. Your agent's personality will shape how it sounds and behaves in every interaction. Personality is optional, only **Agent Name** and **Timezone** are required. The personalities below are **examples** to give you a feel for the range available. The full list is loaded in the app and may evolve over time. | Personality Name | Description (vibe / reference) | | --------------------------- | ------------------------------------------------------- | | Natural | Neutral and balanced, default tone. | | Friendly Consultant | Warm, helpful, and a touch conversational. | | Aggressive Closer | Direct, assertive, always aiming for a "yes." | | Donald Trump | Bold, confident, and controversial. | | Joe Biden | Soft-spoken, empathetic, with a hint of grandpa energy. | | Wolf of Wall Street | Energetic, persuasive, and money-focused. | | Elon Musk | Visionary, quirky, and matter-of-fact. | | Kevin Hart | Fast-talking and hilarious. | | The Rock | Charismatic and full of hype. | | Jar Jar Binks | Clumsy comic relief with a chaotic syntax. | | Yoda | Wise, reversed sentence order, it has. | | Tommy Shelby | Cold, calculated, Peaky Blinders style. | | Saul Goodman | Slick, legal hustler energy. | | Heisenberg (Walter White) | Dark, serious, calculated: "I am the danger." | | Jesse Pinkman | Street-smart, informal, frequent "yo." | | Optimus Prime | Heroic, formal, and noble. | | Megatron | Villainous and authoritarian. | | Son Goku | Cheerful and battle-ready. | | Daenerys Targaryen | Regal, determined, breaker of chains. | | Hermione Granger | Book-smart, precise, articulate. | | Mulan | Brave, focused, honorable. | | Lady Gaga | Glamorous and creatively intense. | | Tony Stark (Iron Man) | Witty, tech-savvy, and full of sarcasm. | | Elsa (Frozen) | Calm, regal, with an icy edge. | | Michael Scott (The Office) | Awkward, unpredictable, tries to be funny. | | Moana | Adventurous, optimistic, and kind. | | Frida Kahlo | Artistic, deep, and passionate. | | Jack Sparrow | Eccentric and unpredictable. | | Indiana Jones | Adventurous and confident. | | Beyoncé | Empowered, elegant, and commanding. | | Sherlock Holmes | Analytical, detached, brilliant. | | Tiana (The Princess & Frog) | Driven, grounded, and focused. | | Charlie Chaplin | Silent-era charm with expressive tone. | | Katniss Everdeen | Stoic, focused, and fiercely independent. | | Groot | Repetitive but expressive ("I am Groot"). | | Deadpool | Chaotic, irreverent, 4th-wall-breaking. | | The Joker | Unhinged, theatrical, and darkly funny. | | Loki | Mischievous, cunning, and charismatic. | | Bugs Bunny | Witty, cheeky, and playful. | | Pee-wee Herman | Eccentric and unpredictable. | | Dr. Evil | Satirical villain, comically ambitious. | | Borat Sagdiyev | Naive, awkward, hilariously inappropriate. | | Albert Einstein | Brilliant, theoretical, with quirky logic. | | Dorothy Gale | Innocent, curious, with wonder in her tone. | *** ## Timezone Define the timezone of the agent. This influences time-related actions, such as booking meetings. Timezone selection in Pearl Settings # Agents Source: https://developers.nlpearl.ai/pages/agents Agents are your capacity to handle voice calls and text conversations in NLPearl. Learn how they work and how to manage them.
Agents cover
Agents cover
In NLPearl, **agents** are your capacity to handle activity. They power both your **voice calls** and your **text conversations** - the number of agents you have determines how much you can run at the same time. ## How agent capacity works An agent is a **virtual unit of capacity — not a person and not a specific Pearl.** Think of it as one "lane" of throughput that your whole workspace shares. The more agents you own, the more activity you can run in parallel. What a single agent unlocks depends on the channel: Each agent handles **one call at a time**. With 5 agents, you can run **5 calls simultaneously** — a 6th call waits until one frees up. Each agent adds **3 messages per minute** of throughput. With 10 agents, that's up to **30 messages per minute**, spread across all your open chats. **The key difference:** on **voice**, an agent limits how many calls run *at the same time* (concurrency). On **text**, an agent doesn't cap the number of open conversations — it sets how fast Pearl can reply *across all of them* (a message rate). Capacity scales linearly: 1 agent → 3 messages/minute, 10 agents → 30 messages/minute. Agents are shared at the **workspace** level. You buy them once, then allocate them to each inbound or outbound activity from the Pearl overview — so a busy campaign can use more lanes while a quieter one uses fewer. ## Set up agents for your activities Agents are managed at the **workspace** level from your Settings, then allocated to each Pearl from its overview page once published. Click your **profile card** at the bottom-left of the sidebar, open **Settings**, then select the **Agent(s)** tab. This is where you purchase, review, and remove the agents in your workspace. Agent(s) tab in workspace Settings Use the **Purchase New Agent(s)** bar at the top: set the quantity, review the monthly price, and click **Purchase Agent(s)**. You're billed immediately (see [Subscription and billing](#subscription-and-billing)). Adding concurrent agents requires an **active paid subscription**. Extra agents can only be purchased on a paid plan. Purchase New Agent(s) bar in the Agent(s) settings The list shows every agent in your workspace, with its creation date. List of agents in the workspace Agents that come with your subscription are flagged with an **Included in your plan** badge — these are free and can't be removed. Included in your plan badge on a plan agent To remove an extra agent, click the red **trash** icon next to it. Remove an agent with the trash icon There are no pro-rata refunds — the agent stays active until the end of the period you've already paid for. **Example:** you remove an agent on the 5th, but your last renewal was on the 1st. The agent stays available until the end of that paid period (the 30th), and won't be billed again in the next cycle. After publishing your Pearl, open its overview page, open the **Settings** popover, and set the number of **Agent(s)** for that activity. Allocate 2 agents to a campaign and it handles 2 leads at a time. You can scale this up or down anytime. Allocate agents to a Pearl from its overview Settings ## Example The same number of agents translates differently on voice and text. Here's how a given allocation plays out: | Agents | Voice (simultaneous calls) | Text (messages / minute) | | :----: | :------------------------: | :----------------------: | | **2** | 2 calls at the same time | 6 messages / minute | | **5** | 5 calls at the same time | 15 messages / minute | | **10** | 10 calls at the same time | 30 messages / minute | For example, allocate **2 agents** to an outbound voice campaign and it dials **2 leads at the same time**; the same 2 agents on a text Pearl let it reply at up to **6 messages per minute** across all open chats. ## Subscription and billing Every plan includes a set number of agents at no extra cost - higher tiers include more. On an **active paid subscription**, you can add extra concurrent agents at any time to grow your capacity. Standard agents are billed at a flat monthly rate. Enterprise use and fine-tuned models cost more, depending on model complexity. See [Billing](/pages/billing) for current pricing. ### When you're billed When you purchase an agent, you're billed for it immediately, whatever point you're at in your billing cycle. On your renewal date, every additional agent renews automatically for the next period. Buying an agent shortly before your renewal date means two charges close together: one when you purchase, and one when everything renews. **Example** - your subscription renews on the 1st and you add an agent on the 29th. You're billed for it right away. On the 1st, the whole subscription (including that agent) renews, so it's billed again for the new period. You've effectively paid for two periods, and you keep the agent for the full duration of each. # Call Analytics Source: https://developers.nlpearl.ai/pages/analytics Track every campaign in real time: call outcomes, success and pickup rates, events, tags, sentiment, an activity heatmap, and costs — all from Pearl's automated conversations. Call Analytics dashboard overview
NLPearl gives you a detailed analytics dashboard for every campaign, so you can track performance, understand what Pearl is doing on your calls, and optimize your strategy as results come in. Outbound campaigns (initiated by Pearl) surface more data, while inbound campaigns show a lighter set of insights. Every metric reflects Pearl's automated voice interactions, never human agents. Most cards follow the same layout: a **headline metric** at the top, a **Selected period** tag confirming the number matches the range you picked, and an **info** button (ⓘ) with a short explanation. Cards that include a chart plot that metric across the selected period. Running a **Pearl Text** agent? The same dashboard adapts its wording to chats — *Chat Status Breakdown*, *Average Chat Duration*, *Chats Heatmap*, and so on. ## The analytics toolbar A toolbar sits at the top of the dashboard. Use it to set the time range for every card and to export a report. Analytics toolbar showing the leads count, date range picker, and Print button ### Choose your time range By default the dashboard shows the **last 30 days**. Open the date picker to jump to a preset — `Today`, `Yesterday`, `Last 7 days`, `This week`, `This month` — or set a custom **Start** and **End** date. Every card updates to match. Date range picker with quick presets and custom start and end fields ### Export a report Click **Print** to turn the current view into a shareable report. Pick the period you want the report to cover. The button sits in the top-right of the toolbar. In your browser's print dialog, choose **Save as PDF** (or send it to a printer). The report is formatted for print — a light theme with one card per page. It adds a header with your project name and the selected period, and a footer with the generation date. Browser print dialog previewing the analytics report with the NLPearl header, per-card layout, and footer ## Call Status Breakdown This card shows how your calls are distributed across their **final statuses**. The headline is your total number of calls for the period. Call Status Breakdown card with total calls, a distribution bar, status pills, and a trend chart **Each status is a segment of the distribution bar, sized by its share of the total.** The pills below the bar list every status with its call count. Horizontal distribution bar split into colored status segments with labeled pills Statuses you'll see: | Status | Meaning | Availability | | ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | | **Successful** | The call met the success condition you defined for the Pearl (a booking, a confirmation, and so on). | All | | **Unsuccessful** | The conversation happened, but the goal wasn't reached. | All | | **Completed** | An answered call with no success/failure verdict — shown when no success criteria is set for the Pearl. [Define one](/pages/pearl_analytics) to split these into Successful and Unsuccessful. | All | | **Need Retry** | Nobody picked up, so the lead will be retried per your retry settings. | Outbound | | **Voice Mail Left** | Pearl reached voicemail and left a message. | Outbound | | **Unreachable** | The lead couldn't be reached after every retry was exhausted. | Outbound | | **Error** | The call failed for a technical reason. | All | | **Other** | Any remaining calls that don't fit the above (for example, calls still in progress). Shown on the bar but not selectable. | All | Select any status — on the bar or in its pill — to overlay that status's trend on the chart below. Hover a segment to see its exact count and percentage. Line chart showing selected call statuses trending over the selected period On outbound campaigns, a toggle lets you switch the whole card between **All calls** and **Answered calls** (the calls a person actually picked up: Completed, Successful, and Unsuccessful). Toggle switching the Call Status Breakdown between All calls and Answered calls ## Average Call Duration The **average length of your calls**, measured from the moment the person picks up or starts interacting with Pearl. Useful to: * Detect drop-offs * Monitor engagement quality * Measure attention span Average Call Duration card with a headline duration and a trend chart ## Success Rate The **percentage of calls that met the success definition** you set for your Pearl — booking a meeting, confirming information, or anything else you defined as a success. The headline is your average success rate over the selected period, weighted by call volume. Read Success Rate alongside Average Call Duration to gauge how efficient your conversations are. Success Rate card with an average percentage and a trend chart The chart stays empty until you [define what success means](/pages/pearl_analytics) for your Pearl. ## Events **Events are the actions Pearl took during conversations.** The headline shows the total number of events and the average per answered call. Events card listing each action with its per-call rate and share of events Each row breaks down one action three ways: * **Count** — how many times it occurred. * **Per call** — the average number of times per answered call. * **Share of events** — its portion of all events triggered. Tracked actions include: * **Message Taken** * **SMS Sent** * **Call Transferred** * **Calendar Booked** * **Email Sent** ## Tags **Tags are the Indicator Tags you defined when creating your Pearl** — labels like `Interested`, `Callback Requested`, or `Wrong Number` that Pearl applies automatically based on how each conversation goes. The headline highlights your most-used tag and its share of calls. Tags card showing each tag's color, count, and share of calls Each tag shows its color, its count, and its **share of calls** — the percentage of calls it was applied to. Tags aren't just for display. You can filter campaigns by tag, trigger notifications, and use them to segment leads. Learn how to set them up in [Call Analytics — Indicator Tags](/pages/pearl_analytics). ## Calls Heatmap The heatmap shows **when calls happen** across the week — every cell is a day-and-hour slot, and brighter cells mean more activity. The headline calls out your busiest slot. Use it to find the best times to call (outbound) or to staff for demand (inbound). Weekly calls heatmap with a peak-time headline and a Less-to-More activity legend Two controls let you adjust the view: * **Color** — toggle a color scale on or off. * **Timezone** — read the grid in the timezone that matters to you. Heatmap controls: a Color toggle and a timezone dropdown ## Pickup Rate Outbound only. The **percentage of outbound calls answered** by your contacts. The headline is your average pickup rate for the period. It tells you how reachable your audience is, so you can fine-tune your calling hours. Pickup Rate card with an average percentage and a trend chart ## Sentiment Analysis The **emotional tone of your conversations**, detected from customer responses across five levels. The headline names the dominant sentiment and its share of calls. * Negative * Slightly Negative * Neutral * Slightly Positive * Positive Sentiment Analysis card with a dominant sentiment and each level's share of calls Each level lists its call count and share of calls, so you can watch satisfaction trends and adjust Pearl's tone. ## Costs Your **total and per-period call costs**, with a headline total and a trend over time — so you can see how usage affects your credit. Costs card with a total cost headline and a spend trend chart This card only reflects costs deducted from your available credit. Calls covered by your included minutes aren't shown. ## Inbound vs Outbound | Feature | Inbound | Outbound | | ---------------------------------------------------------- | ------------- | --------------------------------------------------- | | Call initiation | By the caller | By Pearl | | Call Status Breakdown | ✅ | ✅ *(adds Need Retry, Voice Mail Left, Unreachable)* | | All calls / Answered calls toggle | — | ✅ | | Pickup Rate | — | ✅ | | Duration, Success, Events, Tags, Sentiment, Heatmap, Costs | ✅ | ✅ | ## Summary With NLPearl Analytics you get full visibility into your campaigns' performance. Use these insights to fine-tune your strategy, lift your success and pickup rates, and optimize every conversation. # API Node Source: https://developers.nlpearl.ai/pages/api_action
API node interface on light mode
API node interface on dark mode
The **API node** runs an HTTP request automatically when the flow reaches it, letting your Pearl pull or push data from an external system. Depending on where you place it, it behaves in one of three ways: * **Pre-Call API**: runs once, before the conversation starts. * **In-Call API**: runs during the conversation, when the flow reaches the node. * **Post-Call API**: runs after the conversation ends, as a post-call action. The configuration form is the same in all three cases. Only the available variables, the response handling, and the transitions differ (see [Context Differences](#context-differences)). *** ## Adding an API Node | Context | Where to add it | | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------- | | **Pre-Call API** | On the **Start** node, choose **Pre Call API**. It is inserted between Start and the Opening Sentence, and runs before the call. | | **In-Call API** | Add an **API** node from the side toolbar (or the node picker under *Live Action Nodes*) and connect it where the request should run. | | **Post-Call API** | On the **Post-Call Actions** container (reached from an End Call transition), click **Add Action** and choose **API**. | *** ## Configuring the Request Explain what this API does and what data it returns (e.g. *"Fetches customer order history"*). Maximum **150 characters**. This helps Pearl understand when and how to use the action. API node description field Type the API endpoint URL and choose the **HTTP Method** (**GET**, **POST**, **PUT**, **DELETE**, or **PATCH**) depending on the API's requirements. Click **+** to insert a variable into the URL, limited to the variables available in the node's context (see [Context Differences](#context-differences)). API URL and method configuration The available fields depend on the method: * The **Body** section is shown only for **POST**, **PUT**, and **PATCH** (hidden for GET and DELETE). * The **Response Output Schema** is available for every method **except DELETE**. Add any header required by the API, such as `Content-Type` or `Authorization`. Header values are **static**. API headers configuration For a **dynamic authorization token**, use a [**Credential**](#credentials-authentication) instead of a static header. Provide **Key / Value** pairs, sent as JSON. API body configuration Each **Value** is either a **Variable** or a **Static & Custom** value. Static values support these types: | Type | Format | | ------------------ | ---------------------- | | **Text** | String | | **Whole Number** | Integer | | **Decimal Number** | Float / double | | **Boolean** | `true` / `false` | | **Date** | Calendar date | | **Time** | Time of day | | **Date & Time** | Combined date and time | For each row you can toggle a **Required** checkbox: * **Checked**: Pearl prompts the customer for the value before sending the request if it hasn't been collected yet. * **Unchecked**: the request is sent even if the value is missing; the key is simply omitted. When using a variable in the body, be aware that: * The platform **casts each variable to its configured data type** (e.g. Whole Number becomes an integer, Text is quoted as a string). A type mismatch may cause the API to reject the request. * You can mix static values and variables in the same body. * For nested JSON, use **dot notation** in the Key (`customer.address.street`) and **square brackets** for array indices (`order.items[0].productId`). See [Using Nested Objects](#using-nested-objects) below. A body value can also carry its own braces - a GraphQL query or a nested JSON fragment, for example. In an API node, only braces wrapping a valid variable ID are substituted; every other brace is sent as-is: * `{ {agentName} }` - the variable is replaced, the outer braces are kept. * `query { boards(ids: {agentName}) { id } }` - the variable is replaced, the rest of the query is left untouched. * `{ agentName }` - braces containing spaces around the ID are **not** recognized as a variable; the text is sent literally. ### Using Nested Objects Many APIs expect a **nested JSON structure** in their request body. Use dot notation and array indices in the **Key** column to build nested payloads while keeping them organised and readable. * Use **dot notation** for properties (`customer.address.street`) * Use **square brackets** for array indices (`order.items[0].productId`) You can pair nested paths with any variable type: Text, Number, Boolean, etc. Mapping table: | API key | Variable | | -------------------------- | --------------- | | `customer.name` | `customerName` | | `customer.email` | `customerEmail` | | `customer.address.street` | `street` | | `customer.address.city` | `city` | | `order.items[0].productId` | `productId` | | `order.items[0].quantity` | `quantity` | Resulting body: ```json body.json theme={null} { "customer": { "name": "{customerName}", "email": "{customerEmail}", "address": { "street": "{street}", "city": "{city}" } }, "order": { "items": [ { "productId": "{productId}", "quantity": "{quantity}" } ] } } ``` *** ## Response Output Schema & Variable Assignment API responses are capped at **10,000 characters**. Anything longer is automatically truncated. Available for every method **except DELETE**. The **Response Output Schema** lets you filter the API response so only the relevant data flows back into the conversation. Without filtering, the entire JSON is returned, which can reduce precision because the AI receives too much unrelated information. Even for small responses, setting a schema is strongly recommended to keep Pearl focused. Each row of the schema has three parts: | Column | Description | | ----------------------- | --------------------------------------------------------------------------------------- | | **Required** (checkbox) | Mark the path as mandatory for the action. | | **JSON Path** | The path to extract from the response. | | **Variable to Assign** | Store the extracted value in a variable. **Required for Pre-Call**, optional otherwise. | API response output schema configuration ### How it works * Provide a list of **JSON Path** strings, one per row. * The system extracts only those paths from the API response; everything else is discarded. ### Path syntax A path walks down the API response to the value you want. The simplest form is a chain of keys, and it covers most responses: | Path | What it returns | | ---------------- | --------------------------------------- | | `customer.email` | The `email` property inside `customer`. | | `items[0].id` | The `id` of the first entry in `items`. | A path can also **choose**, which is what you need as soon as an API answers with a list and you only want one entry out of it: | Path | What it returns | | ------------------------------------------------------ | --------------------------------------------------------------------------------------------------- | | `collection[?(@.status == 'available')][0].start_time` | The `start_time` of the first entry whose `status` is `available` — a filter, then the first match. | | `items[-1].id` | The `id` of the last entry. Negative indices count from the end. | | `items[0:3]` | The first three entries — a slice. | | `..email` | Every `email` found anywhere in the response, at any depth. | A slice or a recursive `..` search can match several values at once. Assign one of those to a variable and the variable has to allow multiple values — see **Assigning to a variable** below. These are not the same as the paths in the **Key** column of the request body. There, `order.items[0].productId` **builds** a nested payload. Here, the same shape **reads** a value out of the response. ### Using a variable inside a path A path can carry a `{variableId}` placeholder — the same syntax used everywhere else (see [Flow Variables](/api-reference/flow_variables)). It is replaced with the variable's current value before the response is read, so the path can depend on what the conversation has collected: ```text theme={null} collection[?(@.start_time startswith '{preferredDateIso}')][0].start_time ``` If the caller asked for a particular day and it was collected into `preferredDateIso`, that path returns the first slot on that day. Use a filtered path whenever the API returns a list and you only want one entry from it. A calendar call is the usual case: without a filter, you map slot 1, slot 2 and slot 3 into separate variables and let the agent pick between them. With one filtered path, the platform hands it exactly the first free slot on the day the caller asked for. Benefits: * Keeps the response size small * Improves the quality and relevance of AI outputs * Prevents hitting the 10,000-character truncation limit * Ensures only the necessary fields are carried into the next steps of the conversation ### Assigning to a variable Key things to know: * **The variable's type must match the data type returned by the API at that path.** * If the value returned is a list, make sure the variable is configured to **allow multiple values**. * A variable can store up to **600 characters**. Any data beyond this limit is **truncated**. Outside of Pre-Call APIs, assigning a variable is optional. If you don't assign one, the filtered JSON is still available for the conversation's internal logic, but it won't be stored for later reuse. *** ## Credentials (Authentication) If your API requires authentication, create a **Credential** on the platform, then enable the **Credentials** toggle in the API node and select it from the **Token** dropdown (use **Add New** to create one, **Edit** to update it). Leave the toggle off if no authentication is needed. API credentials toggle and token selection **Supported credential types** (chosen from the **Type** dropdown when creating a credential): | Type | Description | | ------------------ | -------------------------------------------------------- | | **Api Key** | Injected in a **Header** or **Query** parameter | | **Basic Auth** | Username + password | | **Bearer** | A static bearer token | | **Custom Api Key** | Custom headers / query params / body | | **Refresh Token** | The platform fetches and refreshes a token automatically | **OAuth2** providers are connected through [**Integrations**](/pages/pearl_vibe), not created manually in this form. Why use a Credential? * Avoid hardcoding tokens manually in every API node * Automatically refresh tokens based on their TTL (time-to-live) * Centralized management when multiple API nodes reuse the same token * No need to parse token responses manually, the platform extracts the token for you ### Configuring a Refresh Token credential Open the **Credential Manager** from the icon at the top of the Flow Editor header. Credential Manager access in the Flow Editor header In the **Credentials Manager**, click **+ Add** to create a new credential. Add a new credential in the Credentials Manager You can either pick a ready-made **integration** from the list (Google, Microsoft, Slack, HubSpot, Salesforce, Zoho, and more) to connect through its guided flow, or click **Add Manually** to configure a custom credential such as a **Refresh Token**. Choose an integration or add a credential manually If you chose **Add Manually**, enter a **Name** (a label to identify it later) and select a **Type**. The form updates to show the fields specific to the selected type. Manual credential form with name, type, and type-specific fields | Field | Description | | --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Access Token URL** | The method and endpoint used to request the token, with optional **Headers**, **Query Params**, and **Body** (e.g. `grant_type`, `client_id`, `client_secret`). | | **Token Path** | JSON path to locate the token in the response (e.g. `data.access_token`). | | **TTL (sec)** | Token time-to-live (minimum **100**). | | **Header Key** | Name of the header where the token is injected (e.g. `Authorization`). | | **Header Prefix** | Optional prefix for the token (e.g. `Bearer`). | | **Secured Variables** | Sensitive key/value pairs reused across requests. | Use **Test Credentials** to call the token endpoint and preview the JSON response, confirming your configuration retrieves the token successfully before saving. ### How the Credential is used Once saved, select this Credential from the **Token** dropdown in any API node. When selected: * The platform automatically adds the token to the request header, using the configured **Header Key** and optional **Header Prefix**. * The token is refreshed automatically when it expires, based on the configured **TTL**. Make sure the **Token Path** matches the exact location of the token in the JSON response. If the platform can't find the token at this path, the Credential will fail. *** ## Context Differences The same API node behaves differently depending on where you place it in the flow. | Aspect | Pre-Call API | In-Call API | Post-Call API | | ------------------------------- | -------------------------------- | ---------------------- | ------------------------------ | | **When it runs** | Before the call | During the call | After the call | | **Available variables** | Pre-Call only | Pre-Call + In-Call | Pre-Call + In-Call + Post-Call | | **Assign response to variable** | Required | Optional | Optional | | **Transitions** | Success (+ optional Not Success) | Continue / conditional | None | | **Can duplicate** | No | Yes | — | Runs **once before the conversation begins**. Typical uses: * **Inbound**: look up the caller using the auto-captured **phone number** and **call id**. * **Outbound**: preload data from Pre-Call variables already stored on the lead. Only **Pre-Call variables** are available (system variables like phone number, call id, first/last name, email, plus your own Pre-Call variables). * **Assigning response values to variables is required**, that's how pre-call data becomes usable in the conversation. All required variables must be returned for the node to take the **Success** path. * **Transitions**: a **Success** branch by default. Enable **On Error Transition** (in the Transitions tab) to add a **Not Success** branch for failed requests. * Pre-Call API nodes **cannot be duplicated**. Runs **when the flow reaches the node during the conversation**. * Both **Pre-Call** and **In-Call** variables are available. * After it runs, the flow follows the **Continue** transition (or your conditional transitions). * Assigning response values to variables is optional but recommended for reuse later in the flow. Runs **after the call**, as part of the **Post-Call Actions**. * All variable groups are available, including **Post-Call** variables (call time, summary, recording, duration, transcript). * Post-Call actions have **no transitions**. *** ## Testing Your API Use the **Test API** panel below the form: Test API panel Give sample values to every variable used in the request. Click **Send** to run the request. Review the raw response, the filtered response (if an Output Schema is set), and any variables populated from it. Use **Expand** to open a full-screen view with the request and response side by side. Test and perfect your setup before putting the Pearl in production. *** Learn how to create and use variables inside API nodes. # Billing Source: https://developers.nlpearl.ai/pages/billing Learn how to manage your billing settings, subscriptions, and invoices on the NLPearl.AI platform.
Billing cover
Billing cover
*** ## Billing Management The **Billing** page is your central place to manage everything related to payments on NLPearl.AI. From here you can choose or change your subscription plan, manage your payment methods, view and download invoices, and configure auto-recharge to keep your activities running without interruption. Billing changes are managed directly on the platform. Make sure you have the right permissions on your workspace to update subscriptions or payment methods. *** ## Subscription Management From the Billing page, you can select the subscription plan that best fits your needs, or change your current one at any time. Upgrades take effect **immediately**, giving you access to additional features and resources right away. Downgrades take effect at the **end of your current billing period**, on the anniversary date of your current plan. *** ## Payment Methods Enter and manage your credit card details directly from the Billing page. Keeping a valid payment method on file ensures your payments are processed smoothly and your subscription stays active. Payment method on the Billing page You can update or replace your card at any time. The new payment method is used for your next charge. *** ## Invoices Access your full billing history from the Billing page. Every invoice is available to **view and download** for your records and accounting needs. Invoices list on the Billing page *** ## Credits Credits fund your activities on NLPearl.AI. From the **Credits** tab of the **Subscription & Payment** page, you can top up your balance in two ways: buy credits instantly, or set up auto-recharge so your balance is replenished automatically. ### Buy credits instantly Purchase a credit amount that is added to your balance **immediately**. Use this for a one-time top-up or to get started right away. Buy credits instantly on the Subscription & Payment page ### Auto-recharge Auto-recharge keeps your balance topped up automatically so your activities never stop because of an insufficient balance. Turn on auto-recharge from the Credits tab. Define the balance level that triggers a recharge. Choose the amount your balance is recharged to whenever it falls below the threshold. Auto-recharge settings on the Subscription & Payment page We strongly recommend enabling auto-recharge. Without it, your calls and conversations stop as soon as your balance runs out. *** ## Next steps Compare the different subscription plans and choose the best one for your needs. Learn how payouts work and how to manage your earnings on the platform. # Phone Number Blacklist Source: https://developers.nlpearl.ai/pages/blacklist
Phone Number Blacklist cover
Phone Number Blacklist cover
*** The **Blacklist** feature enables you to restrict specific phone numbers or entire prefixes from engaging in inbound or outbound calls with your AI agent campaigns. Utilizing this feature helps enhance campaign efficiency and ensures communication efforts remain focused and relevant. ### Benefits * Prevent unwanted calls from specific numbers or number prefixes. * Enhance operational efficiency by avoiding irrelevant interactions. * Monitor and track blacklisted number activities clearly within your campaigns. *** ### Accessing the Blacklist The Blacklist lives in your **Settings**. Click your **profile card** at the bottom-left corner of the sidebar, then select **Settings**. Open Settings from the profile card From the left menu, select **Blacklist** under the *Workspace* section. Blacklist tab in the Workspace settings *** ### Adding a Number to the Blacklist In the **Add Blacklisted Phone Number** bar at the top, click **Add Phone Number**. Add Blacklisted Phone Number bar In the **Phone Number Blacklist** dialog, type the phone number you want to block (e.g., `+1 408 XXX XXXX`), then click **Add Phone Number**. Phone Number Blacklist dialog to enter a number You can also block an entire **prefix** (e.g., `+33`). Every number beginning with that prefix (`+33123456789`, `+33456789012`, etc.) is then blocked from both receiving and making calls. Need to block many numbers at once? You can **add them in bulk** instead of entering them one by one — paste or import a whole list in a single action. *** ### Managing Blacklisted Numbers All blocked numbers appear under **Blacklisted Phone Numbers**, with a counter showing how many are stored. List of blacklisted phone numbers **Search** — use the search field at the top right to quickly find a specific number in a long list. Search field in the blacklist **Remove** — click the red trash icon on a row to remove that number from the blacklist. Remove a number from the blacklist with the trash icon *** ### Monitoring Blacklisted Numbers in Campaigns * Blacklisted numbers will appear with a `Blacklisted` label in your campaign interface. * Track attempted interactions involving blacklisted numbers, whether inbound calls to your campaigns or outbound calls initiated by your AI agent. Blacklisted label on a call in a Pearl's Calls list Leveraging the blacklist feature ensures your campaigns remain targeted, effective, and free from unwanted communication. # Custom VoIP Integration Source: https://developers.nlpearl.ai/pages/custom_voip Learn how to integrate your own VoIP service with NLPearl.AI.
Custom VoIP Integration cover
Custom VoIP Integration cover
Integrate your own VoIP service with NLPearl to use your existing phone numbers for inbound and outbound calls. This flexibility allows you to leverage your current VoIP infrastructure while benefiting from NLPearl.AI’s advanced features. *** ### How to Integrate Your Custom VoIP Service To integrate your custom VoIP service, follow these steps: Start by clicking your **profile card** at the bottom-left corner of the sidebar, then open **Settings**. Open Settings from the profile card From there, open the **Phone Numbers** tab to manage the numbers linked to your account. Phone Numbers tab in Settings In the **Phone Numbers** tab, locate the **Custom VoIP** row and click **Add Custom VoIP** to start setting up your own provider. Add Custom VoIP from the Phone Numbers settings Enter the phone number you want to associate with this custom VoIP configuration. Enter it in **E.164 format** (digits only, with an optional leading `+`). This label is mainly for display (DID number, extension, etc.) and doesn't have to be a routable number, but it must be numeric. Enter the phone number for your custom VoIP configuration After adding the number, you land on a setup screen with two cards — **Inbound Configuration** and **Outbound Configuration** — each showing a **Configured** / **Not Configured** badge. Configure the direction(s) you need (one or both), then click **Finish Setup**. Choose to configure inbound and/or outbound ### Inbound Configuration Settings Secures your VoIP traffic by encrypting both the signaling (via TLS) and media (via SRTP). Activate this toggle **only** if your VoIP provider requires it. **When to Enable It:** * Your SIP provider specifically mentions TLS or SRTP support. * You want to ensure secure, encrypted voice communication (e.g., for compliance or privacy reasons). **When to Leave It Off:** * Your provider doesn’t support TLS/SRTP, enabling it may block calls or cause failed connections. * You’re using basic test environments or local SIP servers without encryption. Inbound TLS (SRTP) encryption toggle Inbound calls require **at least one** authentication method. Enable **IP Address** and/or **Credentials** authentication (you can use both). **IP Address Authentication:** Allow traffic from specific IP addresses, ideal if your VoIP infrastructure has a static IP. IP Address: Enter the public IP address(es) of your SIP servers so we can accept and process requests from them. Inbound IP-based authentication *** **Credentials Authentication:** Use a username and password to authenticate each incoming SIP request. Username: 2–32 characters, using letters, digits, hyphens (`-`) and underscores (`_`) only.
Password: At least 12 characters, with at least one uppercase letter, one lowercase letter, and one digit. Letters and digits only — **special characters are not allowed**. This method is useful if your infrastructure is cloud-based and IPs can change, or you want multi-tenant control. Inbound credential-based authentication
After you save the inbound configuration, NLPearl generates a **SIP Domain** for this number. This is what tells your provider where to send incoming calls so they reach the platform. The SIP Domain isn't something you type. It's created automatically and shown **read-only** at the top of the **Inbound Configuration** card, with a **Copy** button. It only appears **once the inbound configuration has been saved**, so reopen the card afterward to retrieve it. SIP Domain shown read-only with a Copy button in the Inbound Configuration **To finish connecting inbound calls:** 1. Save the inbound configuration, then reopen the **Inbound Configuration** card. 2. Copy the generated **SIP Domain**. 3. Add it to your VoIP provider / PBX as the **destination for inbound calls**, so your operator routes incoming calls to NLPearl. 4. If you enabled **Credentials Authentication**, also add the **username and password** you defined here to your VoIP settings so authentication succeeds.
*** ### Outbound Configuration Settings Secures your VoIP traffic by encrypting both the signaling (via TLS) and media (via SRTP). Activate this toggle **only** if your VoIP provider requires it. **When to Enable It:** * Your SIP provider specifically mentions TLS or SRTP support. * You want to ensure secure, encrypted voice communication (e.g., for compliance or privacy reasons). **When to Leave It Off:** * Your provider doesn’t support TLS/SRTP, enabling it may block calls or cause failed connections. * You’re using basic test environments or local SIP servers without encryption. Outbound TLS (SRTP) encryption toggle This is the address your outbound calls will be sent to, typically provided by your VoIP provider. Enter it as a **domain or IP address** (this is where your calls will be routed). Outbound SIP Trunk URL field This is the SIP user identity used in the “From” header of your outbound SIP requests. It's how your VoIP system identifies the origin of the call. What to enter: You can use one of the following formats depending on your provider: * A SIP username (e.g. `caller01`) * A DID or phone number in `E.164` format (e.g. `+1234567890`) * An extension (e.g. `201`) * A SIP URI (e.g. `caller01@example.com`), less common Outbound User Part field Select the network edge closest to your VoIP infrastructure to optimize call routing and reduce latency. Eight regions are available: | Region | Location | | ------------- | --------- | | North America | Virginia | | North America | Oregon | | Europe | Ireland | | Europe | Frankfurt | | Asia Pacific | Singapore | | Asia Pacific | Tokyo | | Asia Pacific | Sydney | | South America | São Paulo | Outbound Data Center selection This toggle enables or disables call transfers using the SIP REFER method. It is **enabled by default**. When enabled, it allows: * Transferring a live call from one destination to another without media proxying * Offloading media streams directly between endpoints * Reducing latency and server load If you **disable** SIP REFER, NLPearl's servers stay in the media path during transfers, which results in **additional costs**. Leave it on unless your provider doesn't support SIP REFER. Outbound Transfer Call Using SIP REFER toggle **Credentials Authentication:** Use this method if your VoIP provider requires username/password credentials to authenticate outbound calls. Username: This is the identifier associated with your SIP account. Password: A secure password used to authenticate the SIP user. Make sure it meets your provider’s security requirements (e.g. minimum 12 characters, including upper/lowercase letters, a number, and a special character). Outbound credential-based authentication **Header-Based Authentication:** Use this method if your VoIP provider requires custom headers for SIP request authentication. Header Key: This is the name of the custom SIP header field expected by your provider (e.g., X-Custom-Auth, X-Access-Token, etc.). Header Value: The corresponding value used to validate the request (e.g., a token, API key, or static secret). Example: AuthZ-87!t!link Header-based auth is typically used for advanced integrations or when SIP gateways are behind proxies/firewalls that don’t support IP or credential-based auth. Ensure this matches exactly what your provider expects, as even small typos (like case or symbols) can lead to rejections. You can add several key-value pairs if needed, for example, to meet multi-token security policies. Outbound header-based authentication * **IP Address Allow List:**\ **IP Address:** See [Twilio's SIP Trunking IP Addresses](https://www.twilio.com/docs/sip-trunking/ip-addresses).
Once integrated: * **Assign to Inbound/Outbound:**\ You can assign your custom VoIP phone numbers to inbound or outbound campaigns within NLPearl.AI. Assign a custom VoIP number to a campaign * **Update Configuration:**\ If any changes are needed, you can edit the VoIP settings by accessing the phone number in the Phone Numbers tab.
*** ### Troubleshooting Tips **Connection Issues**: Double-check all configuration settings, especially SIP URLs, usernames, passwords, and IP addresses. **Authentication Failures**: Make sure the authentication method you've selected matches the one supported by your VoIP provider. **Provider Support**: If you're unsure about specific requirements, contact your VoIP provider for assistance with configuration. ### Advantages of Custom VoIP Integration **Flexibility**: Leverage your existing VoIP infrastructure without switching providers or modifying your current setup. **Global Reach**: Access phone numbers and make calls in any region your VoIP provider supports, ideal for international teams. ***
Purchase and manage your **NLPearl-hosted phone numbers** directly, with instant activation and native support. Explore our **Twilio Integration** to access a broader range of international phone numbers. **Need Assistance?**\ If you require help with the integration process, please refer to our support resources or contact our support team for guidance.
# Dialogue Node Source: https://developers.nlpearl.ai/pages/dialogue
Dialogue node cover
Dialogue node cover
The **Dialogue** node is the main conversational node. Pearl speaks, asks questions, collects information, and keeps the conversation moving. It is the workhorse of most Pearl Voice flows. ## What it does Unlike a traditional IVR, Dialogue is not a rigid prerecorded prompt. Pearl Voice understands the intent of the step, adapts its wording in real time to what the caller says, and can follow the most relevant configured transition based on the conversation. ## When to use it Use Dialogue whenever Pearl needs to: | Pearl needs to | What it means | | ----------------------- | ------------------------------------------------------------------ | | **Speak to the caller** | Deliver a message, greeting, or confirmation | | **Ask a question** | Prompt the caller for an answer or a choice | | **Collect information** | Capture details such as a name, email, or intent | | **Explain something** | Give context, options, or next steps | | **React to the caller** | Respond before continuing or branching to another path in the flow | ## How to configure In **Script / Free Text**, enter what Pearl should say or ask. Maximum 500 characters. Supports all available variables. Use **Instructions** to guide tone, context, exceptions, pronunciation, required details, or how closely Pearl should follow the script.
Dialogue node configuration on the platform
Dialogue node configuration on the platform
When specific wording must be followed closely, add clear instructions such as "Say this exactly", "Do not rephrase", or "Always include the following sentence". ## Transitions Each Dialogue node includes a default **Continue** path. You can also add conditional transitions to direct the caller to another Dialogue node, an action node, or an End Call node. Each conditional transition includes: | Field | Description | | --------------- | ------------------------------------------------ | | **Condition** | Written in plain language, with variable support | | **Destination** | The node the caller is routed to | Pearl asks whether the caller wants to book an appointment. Based on the answer, she can move to a Booking node, send an SMS, transfer the call, or continue to another part of the conversation. # Send Email Node Source: https://developers.nlpearl.ai/pages/email_action
Send Email action interface on light mode
Send Email action interface on dark mode
The **Send Email** node lets your AI agent send an email automatically when a condition is met during (or after) a conversation, for example a confirmation, a quote, or follow-up information. ## Fields to configure Open the node and fill in the fields below to define who receives the email and what it contains. Send Email node configuration on the platform | Field | Description | | ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **From** | The sender account the email is sent from. Pick a connected account, click **Connect Email** to add one, or use **Edit** to update an existing connection. If none is selected, the default sender is used. | | **To** | The recipient address(es). Type addresses directly or insert variables (for example an email collected earlier in the conversation). At least one recipient is required. | | **CC** (optional) | Additional recipients in copy. Supports the same direct input and variables as **To**. | | **Subject** | The subject line of the email. Insert variables to personalize it (for example the prospect's first name). | | **Content (Body)** | The body of the email, using a rich text (HTML) editor. Insert variables to include details gathered during the conversation, such as a price quote or a meeting time. | ***
Email provider configuration panel
Pearl sends emails **from your own business address** using one of three providers. Pick the one that matches your setup.
Gmail Send from your Gmail address
Choose **Gmail** from the provider list. Enter your Gmail address in **Sender Email**. Enter a **Gmail app-password**, not your normal password. [Learn how to generate one](https://support.google.com/accounts/answer/185833). *(Optional)* Add an address under **Test Email to**, click **Test Config**, then **Save**. Enable **2-factor authentication** on your Google account and use an **app-password**, not your main password.
Office 365 Send from your Microsoft 365 address
Choose **Office 365** from the provider list. Enter your Microsoft address in **Sender Email**. Enter an **Office 365 app-password** (see your Microsoft security settings). *(Optional)* Add a **Test Email** address, click **Test Config**, then **Save**. Office 365 may block basic SMTP by default. Make sure your tenant allows it and use an app-password where required.
Custom SMTP Send through any SMTP server
Choose **Custom** from the provider dropdown. For example `smtp.gmail.com`, `smtp.office365.com`, or `mail.yourdomain.com`. Enter the **Port**, usually **587** for TLS or **465** for SSL, then toggle **Enable SSL** (usually **On**). Enter your **Sender Email** and its **SMTP account password**. *(Optional)* Add a **Test Email** address under **Test Email to**, click **Test Config**, then **Save**. If you're unsure about your SMTP details, check with your email hosting provider (Google Workspace, Outlook, Zoho, etc.).
## Variables Personalize the **Subject** and **Content**, and set dynamic **To** and **CC** recipients using variables collected during the conversation. Learn how to create and insert variables to tailor each email to the recipient. # Getting Started Source: https://developers.nlpearl.ai/pages/getting_started Go from sign-up to your first live AI agent in minutes.