# Background Agent Source: https://docs.subverseai.com/agents/background-agent Build an AI agent that runs tasks asynchronously as part of automated workflows ## Overview A Background Agent runs tasks asynchronously without a live user on the other end. Unlike Chat, Voice, or Email agents, background agents aren't triggered by a user message — they're invoked programmatically as part of an automated workflow, triggered by an event, or called as a **tool** by another agent. Background agents are the building block for autonomous, multi-step automation inside Subverse's **Agentverse** workflow system. They process data, make decisions, call APIs, and produce results — all without human interaction. **When to use a Background Agent:** * You want to run an AI task automatically as part of a larger workflow * You need an agent that processes uploaded files, form submissions, or data events * You want to give another agent (Voice, Chat, or Email) the ability to delegate a complex sub-task * You need fire-and-forget processing (e.g. "analyze this document and update the CRM") *** ## How to Create 1. Navigate to **Agents** in the left sidebar. 2. Click **Add Agent** and select **Background Agent** as the agent type. 3. Fill in the **Identity** fields — name and description. 4. Write the agent's system prompt — describe the task it should perform when triggered. 5. Configure the **LLM Service** (provider and model). 6. Optionally configure **Functions**, **Pipeline Settings**, and **Analytics**. 7. Click **Save**. To use the agent in a workflow, add it as a node inside an **Agentverse** flow. To call it as a tool from another agent, deploy it as an **LLM Tool** (see [LLM Tool Deployment](#llm-tool-deployment) below). *** ## LLM Tool Deployment Background agents can be **deployed as LLM Tools**, making them callable by other agents (Voice, Chat, Email) during their conversations. This lets you build composable AI systems where a front-facing agent delegates complex tasks to a specialized background agent. **How it works:** 1. Create the Background Agent and save it. 2. Navigate to **LLM Tools** and create a new tool. 3. Set **Deployment Method** to `Background Agent`. 4. Set the **Agent Name** to the exact name of your Background Agent. 5. Save the LLM Tool. 6. Attach the LLM Tool to a Chat, Voice, or Email agent's **During-Session Functions**. When the front-facing agent decides to use the tool, it invokes the background agent, waits for the result, and incorporates the output into its response. | Field | Type | Description | | - | - | - | | Deployment Method | Dropdown | Set to `Background Agent` to link to a Background Agent. | | Agent Name | Text | The exact name of the Background Agent to invoke. | Background agents used as tools are synchronous from the calling agent's perspective — the calling agent waits for the background agent to finish before continuing. Keep execution time short if using this pattern in a real-time chat or voice context. *** ## How to Test ### Option 1: Manual Trigger via API Send a POST request to the manual trigger endpoint: ``` POST /api/agentverse/manual-upload-trigger ``` This accepts a `multipart/form-data` payload. Include optional files to process and any dynamic variable values. The endpoint is fire-and-forget — it returns immediately and the agent runs in the background. Check the **Execution History** in the dashboard to see the result. ### Option 2: Trigger via an Agentverse Workflow 1. Open **Agentverse** and create or open a workflow. 2. Add a **Background Agent** node and link it to your agent. 3. Connect it to a trigger node (e.g. webhook, file upload, or scheduled trigger). 4. Click **Run** or send a test event. 5. Check the execution log for the agent's output. ### Option 3: Via LLM Tool 1. Open a Chat or Voice agent that has your LLM Tool attached. 2. Test the agent using the Chat Sidebar or Call Sidebar. 3. Send a message that should invoke the tool. 4. Verify the background agent was called and returned the expected result. *** ## Tips & Notes * **Output Schema is powerful:** If downstream systems need to parse the agent's output, always define a JSON Output Schema. This prevents the LLM from returning prose instead of structured data. * **Max Duration:** Background agents processing large files or making many API calls may need a longer max duration. The default is 10 minutes — increase it if tasks regularly time out. * **Thinking Level for complex tasks:** For tasks like multi-document analysis or data reasoning, set Thinking Level to **High** or **Very High** for better accuracy. * **Fire-and-forget:** Background agents don't block the caller. Use the execution history to check whether the task succeeded. * **Dynamic Variables:** Pass context at invocation time using dynamic variables. This lets you build a single general-purpose agent and customize its behavior per task (e.g. pass document type, user ID, or priority level). * **Chaining agents:** You can chain background agents together in Agentverse workflows — the output of one becomes the input to the next. This is the foundation of complex multi-step AI automations. *** See the full configuration reference — every field, type, and default value # Background Agent Configuration Source: https://docs.subverseai.com/agents/background-agent-configuration Full configuration reference for Background Agents ## Identity | Field | Type | Default | Description | | - | - | - | - | | Name | Text | — (required) | Unique identifier. Lowercase letters, numbers, and underscores only (e.g. `data_processor`). Must start with a letter. | | Description | Text | `""` | Internal description of what task this agent performs. | | Architecture | Dropdown | `Prompt Based` | **Prompt Based** uses a system prompt. **Conversational Flow** uses a visual node-based builder. | | Debug Mode | Toggle | Off | Outputs extra internal logs. Useful when building and testing workflows. | *** ## Agent Settings | Field | Type | Default | Description | | - | - | - | - | | Greeting Message | Text | `""` | The initial prompt or task description sent to the agent when it is invoked. | | Greeting Type | Dropdown | `Prompt` | **Prompt** — agent generates a response based on the context. **Say** — outputs exact text (rarely used for background agents). | | Who Speaks First | Dropdown | `SubVerseAI Agent` | Keep as **SubVerseAI Agent** so the agent begins processing immediately when triggered. | | System Prompt | Text area | Empty | The main system prompt. Describe clearly what input the agent receives, what to do with it, and what output to produce. Use the **Refine using AI** button for assistance. | *** ## Large Language Model Preferences | Field | Type | Default | Description | | - | - | - | - | | LLM Model | Dropdown | — (required) | The AI model powering this agent. Choose a capable model for complex tasks. Each model shows its speed and reasoning ratings. | | Thinking Level | Dropdown | `Default` | Extended reasoning depth. Options: **Default**, **Low**, **Medium**, **High**, **Very High**. For complex tasks like document analysis or data reasoning, use **High** or **Very High**. | | Max Tokens | Number | None | Maximum tokens the LLM can generate per response. Leave blank to use the model's default. | | Temperature | Slider | `0.5` | Response creativity. For structured tasks (classification, extraction) use `0.0`–`0.3`. For generative tasks (drafting, summarizing) use `0.5`–`0.8`. | *** ## Session Settings | Field | Type | Default | Description | | - | - | - | - | | Communication Method | Dropdown | `Two Way` | **Two Way** — agent exchanges messages internally as part of its task. **One Way** — agent only produces output. | | Session Timeout (mins) | Number | None | Minutes after which an idle background task is ended automatically. | | Remember Customer Interactions | Toggle | Off | Save a summary of this execution to memory when the task completes. | | Use Customer Interaction Memory | Toggle | Off | Pull past execution summaries into context when this agent is triggered again for the same user or entity. | *** ## Knowledgebase Settings | Field | Type | Default | Description | | - | - | - | - | | Knowledge Base | Dropdown | None | Attach a Knowledge Base. The agent will search it as part of completing its task. Useful for question-answering or document-grounded tasks. | *** ## Function Settings | Field | Type | Default | Description | | - | - | - | - | | Pre Call Tools | Multi-select | Empty | LLM tools that run before the agent starts its task (e.g. fetch data from an external system). | | During Call Tools | Multi-select | Empty | Tools the agent can call while executing (e.g. write to a database, call an external API, send an email). | | Post Call Tools | Multi-select | Empty | LLM tools that run after the task completes (e.g. store results, notify another system). | *** ## Agent Security Settings | Field | Type | Default | Description | | - | - | - | - | | Allow List (Allowed Callers) | Text area | Empty | Regex patterns for sources allowed to trigger this agent, separated by commas. Leave empty to allow all. | | Block List (Blocked Callers) | Text area | Empty | Regex patterns for sources that are blocked, separated by commas. Takes priority over Allow List. | *** ## Post Call Data Analysis After each execution, the agent can automatically analyze the output and extract structured data. | Field | Type | Description | | - | - | - | | LLM Model | Dropdown | The AI model used to run the post-execution analysis. Can differ from the main agent model. | | Parameters | Form / JSON | Define the data points to extract from each execution. Switch between **Form** (add parameters one by one) and **JSON** (paste a raw JSON schema). | **Parameter fields:** | Field | Description | | - | - | | Parameter Name | The key name for this data point (e.g. `task_completion`, `summary`). | | Details | Description of what this parameter represents and how to extract it. | | Type | Data type: `string`, `boolean`, `number`, etc. | | Required | Whether this parameter must be present in every analysis output. | # Chat Agent Source: https://docs.subverseai.com/agents/chat-agent Build an AI agent that communicates with users through text messages ## Overview A Chat Agent is a text-based AI that communicates with users through typed messages. It's ideal for customer support bots, FAQ assistants, lead qualification flows, or any use case where users interact by typing rather than speaking. Chat agents can be embedded in your website via a web chat channel, integrated into your product, or tested directly from the Subverse dashboard. **When to use a Chat Agent:** * You want a bot that responds to typed messages * You need to connect a live chat widget to your website * Your use case doesn't require voice or phone capabilities *** ## How to Create 1. Navigate to **Agents** in the left sidebar. 2. Click **Add Agent** and select **Chat** as the agent type. 3. Fill in the **Identity** fields — name and description. 4. Write the agent's system prompt under **Instructions**. 5. Configure the **LLM Service** (provider and model). 6. Optionally configure **Memory**, **Functions**, **Pipeline Settings**, and **Analytics**. 7. Click **Save**. ## Deploy: Connect to a Channel A saved Chat Agent can be tested from the dashboard immediately. To deploy it for real conversations, connect it to a communication channel. Chat agents support two channel types: Connect your WhatsApp Business number — customers message your number and the agent replies automatically Enable chat on your website or app via webhooks and APIs Each channel requires credentials (WhatsApp API key or WebChat credential) stored securely in encrypted form. See **[Credentials](/credentials/overview)** to set these up before creating a channel. *** ## How to Test 1. Open the agent from the **Agents** list. 2. Click the **Chat** icon or open the **Chat Sidebar** on the right side of the agent page. 3. Type a message and press Enter. 4. The agent responds in real time. 5. Adjust the system prompt or settings and re-test as needed. You don't need a live channel to test — the Chat Sidebar lets you interact with the agent directly from the dashboard. *** ## Tips & Notes * **Name format:** Agent names must be lowercase with only letters, numbers, and underscores. Example: `customer_support_v2`. * **Memory requires both toggles:** "Remember" saves data after a session; "Use Memory" reads it back at the start of the next session. You need both enabled for persistent memory to work. * **Knowledge Base:** Attach a KB to let the agent answer questions from your documents without embedding all content in the system prompt. * **Max Duration:** Conversations that exceed `maxDuration` are cut off. Increase this for complex support flows. *** See the full configuration reference — every field, type, and default value # Chat Agent Configuration Source: https://docs.subverseai.com/agents/chat-agent-configuration Full configuration reference for Chat Agents ## Identity | Field | Type | Default | Description | | - | - | - | - | | Name | Text | — (required) | Unique identifier. Lowercase letters, numbers, and underscores only (e.g. `support_bot`). Must start with a letter. | | Description | Text | `""` | Internal description of what this agent does. | | Architecture | Dropdown | `Prompt Based` | **Prompt Based** uses a system prompt. **Conversational Flow** uses a visual node-based builder. | | Debug Mode | Toggle | Off | Outputs extra internal reasoning logs. Use during development; disable in production. | *** ## Agent Settings | Field | Type | Default | Description | | - | - | - | - | | Greeting Message | Text | `""` | The first message the agent sends when a conversation starts. Leave blank if you want the user to write first. | | Greeting Type | Dropdown | `Prompt` | **Prompt** — agent generates the opening message dynamically. **Say** — agent sends exactly what you typed. | | Who Speaks First | Dropdown | `SubVerseAI Agent` | **SubVerseAI Agent** — agent opens the conversation. **User** — agent waits for the user to write first. | | System Prompt | Text area | Empty | The main system prompt. Write the agent's role, tone, rules, and behavior here. Use the **Refine using AI** button to get AI assistance. | *** ## Large Language Model Preferences | Field | Type | Default | Description | | - | - | - | - | | LLM Model | Dropdown | — (required) | The AI model powering this agent. Each model shows its speed and reasoning ratings. | | Thinking Level | Dropdown | `Default` | Extended reasoning depth. Options: **Default**, **Low**, **Medium**, **High**, **Very High**. Higher = better reasoning but slower. | | Max Tokens | Number | None | Maximum tokens the LLM can generate per response. Leave blank to use the model's default. | | Temperature | Slider | `0.5` | Response creativity. `0.0` = consistent and precise. `1.0+` = more varied and creative. | *** ## Session Settings | Field | Type | Default | Description | | - | - | - | - | | Communication Method | Dropdown | `Two Way` | **Two Way** — agent sends and receives messages. **One Way** — agent only sends (e.g. broadcast mode). | | Session Timeout (mins) | Number | None | Minutes of inactivity after which the session ends automatically. Leave blank for no timeout. | | Remember Customer Interactions | Toggle | Off | Save a summary of each conversation to memory after the session ends. | | Use Customer Interaction Memory | Toggle | Off | Pull relevant past conversation summaries into context at the start of a new session. Enable both for persistent memory across conversations. | *** ## Knowledgebase Settings | Field | Type | Default | Description | | - | - | - | - | | Knowledge Base | Dropdown | None | Attach a Knowledge Base so the agent can retrieve answers from your documents during a conversation. | *** ## Function Settings | Field | Type | Default | Description | | - | - | - | - | | Pre Call Tools | Multi-select | Empty | LLM tools that run automatically before the session starts (e.g. fetch customer data). | | During Call Tools | Multi-select | Empty | Tools the agent can call mid-conversation (e.g. check order status, send an email). | | Post Call Tools | Multi-select | Empty | LLM tools that run automatically after the session ends (e.g. update CRM, send a follow-up). | *** ## Agent Security Settings | Field | Type | Default | Description | | - | - | - | - | | Allow List (Allowed Callers) | Text area | Empty | Regex patterns for contacts allowed to interact with this agent, separated by commas. Leave empty to allow everyone. | | Block List (Blocked Callers) | Text area | Empty | Regex patterns for contacts that are blocked, separated by commas. Takes priority over Allow List. | *** ## Post Call Data Analysis After each conversation, the agent can automatically analyze the transcript and extract structured data. | Field | Type | Description | | - | - | - | | LLM Model | Dropdown | The AI model used to run the post-session analysis. Can differ from the main agent model. | | Parameters | Form / JSON | Define the data points to extract from each conversation. Switch between **Form** (add parameters one by one) and **JSON** (paste a raw JSON schema). | **Parameter fields:** | Field | Description | | - | - | | Parameter Name | The key name for this data point (e.g. `summary`, `user_sentiment`). | | Details | Description of what this parameter represents and how to extract it. | | Type | Data type: `string`, `boolean`, `number`, etc. | | Required | Whether this parameter must be present in every analysis output. | # Create Your First Agent Source: https://docs.subverseai.com/agents/create-first-agent A quick-start guide to building your first AI agent in Subverse ## Overview Subverse supports four agent types, each designed for a different channel and use case: | Agent Type | Channel | Best For | | - | - | - | | [Voice Agent](/agents/voice-agent) | Phone calls | Inbound/outbound calling, voice-based support | | [Chat Agent](/agents/chat-agent) | WhatsApp / Web chat / Telegram / SMS | Text-based support, FAQ bots, lead qualification | | [Email Agent](/agents/email-agent) | Email inbox | Auto-responding to incoming emails | | [Background Agent](/agents/background-agent) | LLM Functions / Workflows / API | Async task automation, sub-agents in Agentverse | To create any agent, navigate to **Agents** in the left sidebar and click **Add Agent**. You'll be prompted to select the agent type first. Not sure which type to pick? If you're just getting started, **Voice Agent** is the most fully-featured option and a great way to learn the platform. For a text-first use case, start with **Chat Agent**. *** ## Quick Start: Your First Voice Agent This guide walks you through creating and testing a Voice Agent — the fastest way to see Subverse in action. ### Step 1: Create the Agent 1. Go to **Agents** in the left sidebar. 2. Click **Add Agent** and select **Voice** as the agent type. 3. Give your agent a **Name** (lowercase letters, numbers, and underscores — e.g. `support_bot`). 4. Optionally add a **Description** for internal reference. ### Step 2: Write the System Prompt The system prompt is the most important setting. It defines your agent's identity, role, and behavior. Navigate to the **Instructions** section and fill in: * **Initial Message** — what the agent says when a call connects (e.g. `"Hello! You've reached Acme support. How can I help you today?"`) * **System Context** — the full behavior prompt for your agent. Click on "Generate using AI" and describe the agent behavior and it will generate a great prompt for you. A good system prompt covers: 1. **Identity** — who is the agent? 2. **Role** — what is its purpose? 3. **Tone** — how should it communicate? 4. **Capabilities** — what can it do? 5. **Limits** — what should it avoid or escalate? ### Step 3: Configure the LLM Under **LLM Service**, select a provider (e.g. OpenAI) and a model (e.g. `gpt-4o`). The default temperature of `0.5` works well for most support use cases. ### Step 4: Configure Speech (STT & TTS) Voice agents require: * **STT Service** — how the agent hears the caller (e.g. Deepgram, `en-US`) * **TTS Service** — how the agent speaks (e.g. ElevenLabs, choose a Voice ID) For a quick start, pick any provider, select a language, and choose a voice. You can fine-tune these later. ### Step 5: Save and Test 1. Click **Save** in the top-right corner. 2. To test, open the **Call Sidebar** on the agent's page. 3. Enter the bot's phone number and your personal number, then click **Call**. 4. The agent will call your phone — speak naturally and verify the behavior. *** ## Next Steps Once your first agent is running, explore the full configuration options or set up another agent type: Full guide: STT, TTS, turn management, call transfers Text-based agents for web chat and messaging Auto-reply agents for incoming email Async task agents for workflows and automation # Email Agent Source: https://docs.subverseai.com/agents/email-agent Build an AI agent that reads and replies to incoming emails automatically ## Overview An Email Agent reads incoming emails and replies to them automatically. When a new email arrives at a configured address, the agent processes the message and sends a response — just like a human would. Email agents are powered by an **Email Channel**, which connects a real inbox (via SMTP credentials) to your agent. The agent handles what to reply; the channel handles sending and receiving the actual emails. **When to use an Email Agent:** * You want to automatically handle incoming support requests or inquiries by email * You need a first-line response bot that can triage, answer FAQs, or escalate to a human * You want to send structured or personalized email replies using AI *** ## How to Create ### Step 1: Create the Email Agent 1. Navigate to **Agents** in the left sidebar. 2. Click **Add Agent** and select **Email** as the agent type. 3. Fill in the **Identity** fields — name and description. 4. Write the agent's system prompt under **Instructions** — describe how it should respond to emails, what tone to use, and what topics it handles. 5. Configure the **LLM Service** (provider and model). 6. Optionally configure **Memory**, **Functions**, **Pipeline Settings**, and **Analytics**. 7. Click **Save**. ### Step 2: Create an Email Channel An Email Channel connects the agent to a real email address. You'll need an email credential (SMTP details) set up in **[Credentials](/credentials/overview)** before creating the channel. 1. Navigate to **Channels** in the left sidebar. 2. Click **Add Channel** and select **Email**. 3. Enter the channel name, email address, and select an email credential. 4. Under **Agent Configuration**, select the Email Agent you just created. 5. Click **Save**. Once the channel is active, any email sent to the configured address will be processed by the linked agent. Full setup guide and configuration reference for Email Channels *** ## How to Test 1. Create and save your Email Agent. 2. Create an Email Channel linked to the agent. 3. Send a test email to the address configured in the channel. 4. Wait a few seconds for the agent to process the email. 5. Check your inbox for the agent's reply. 6. Navigate to **Sessions** in the dashboard to see the full conversation log and analytics output. Make sure the SMTP credential is valid and the email address is configured to receive inbound mail. If no reply arrives, check the session logs for errors. *** ## Tips & Notes * **First Speaker should be User:** Email conversations are always initiated by an incoming email. Set Who Speaks First to **User** so the agent waits rather than sending an unsolicited message first. * **Allow List pattern:** To restrict the agent to only your team's emails, use a pattern like `.*@yourcompany\.com`. Leave Allow List empty to allow all senders. * **Knowledge Base:** If emails often ask FAQs, attach a Knowledge Base with your documentation. The agent will search it before responding. * **Memory across threads:** By default, each email is a fresh context. Enable both memory fields to give the agent awareness of prior conversations with the same sender. *** See the full configuration reference — every field, type, and default value # Email Agent Configuration Source: https://docs.subverseai.com/agents/email-agent-configuration Full configuration reference for Email Agents ## Identity | Field | Type | Default | Description | | - | - | - | - | | Name | Text | — (required) | Unique identifier. Lowercase letters, numbers, and underscores only (e.g. `support_email_bot`). Must start with a letter. | | Description | Text | `""` | Internal description of what this agent handles. | | Architecture | Dropdown | `Prompt Based` | **Prompt Based** uses a system prompt. **Conversational Flow** uses a visual node-based builder. | | Debug Mode | Toggle | Off | Outputs extra internal logs. Use during development; disable in production. | *** ## Agent Settings | Field | Type | Default | Description | | - | - | - | - | | Greeting Message | Text | `""` | Rarely used for email agents — the agent typically responds to incoming email rather than initiating. | | Greeting Type | Dropdown | `Prompt` | **Prompt** — dynamically generated opening. **Say** — sends exact text verbatim. | | Who Speaks First | Dropdown | `SubVerseAI Agent` | Set to **User** for email agents so the agent waits for an incoming email before responding. | | System Prompt | Text area | Empty | The main system prompt. Describe the agent's purpose, tone, rules, and how it should handle different types of emails. Use the **Refine using AI** button for assistance. | *** ## Large Language Model Preferences | Field | Type | Default | Description | | - | - | - | - | | LLM Model | Dropdown | — (required) | The AI model powering this agent. Each model shows its speed and reasoning ratings. | | Thinking Level | Dropdown | `Default` | Extended reasoning depth. Options: **Default**, **Low**, **Medium**, **High**, **Very High**. Higher = better reasoning but slower. | | Max Tokens | Number | None | Maximum tokens the LLM can generate per response. Leave blank to use the model's default. | | Temperature | Slider | `0.5` | Response creativity. For support emails, a lower value (0.2–0.5) is usually better. | *** ## Session Settings | Field | Type | Default | Description | | - | - | - | - | | Communication Method | Dropdown | `Two Way` | **Two Way** — agent reads and replies to emails. **One Way** — agent only sends. | | Session Timeout (mins) | Number | None | Minutes after which an idle email processing session ends automatically. | | Remember Customer Interactions | Toggle | Off | Save a summary of each email thread to memory after the session closes. | | Use Customer Interaction Memory | Toggle | Off | Pull relevant past email summaries into context when the same sender emails again. Enable both for continuity across separate email conversations. | *** ## Knowledgebase Settings | Field | Type | Default | Description | | - | - | - | - | | Knowledge Base | Dropdown | None | Attach a Knowledge Base so the agent can look up answers from your documents when composing replies. | *** ## Function Settings | Field | Type | Default | Description | | - | - | - | - | | Pre Call Tools | Multi-select | Empty | LLM tools that run before the agent processes the email (e.g. fetch customer account info). | | During Call Tools | Multi-select | Empty | Tools the agent can call while composing its reply (e.g. check order status, look up ticket history). | | Post Call Tools | Multi-select | Empty | LLM tools that run after the reply is sent (e.g. create a support ticket, log to CRM). | *** ## Agent Security Settings | Field | Type | Default | Description | | - | - | - | - | | Allow List (Allowed Callers) | Text area | Empty | Regex patterns for email addresses allowed to trigger this agent, separated by commas. Example: `.*@yourdomain\.com` to allow only your domain. Leave empty to allow all senders. | | Block List (Blocked Callers) | Text area | Empty | Regex patterns for email addresses that are blocked, separated by commas. Takes priority over Allow List. | *** ## Post Call Data Analysis After each email session, the agent can automatically analyze the conversation and extract structured data. | Field | Type | Description | | - | - | - | | LLM Model | Dropdown | The AI model used to run the post-session analysis. Can differ from the main agent model. | | Parameters | Form / JSON | Define the data points to extract from each email conversation. Switch between **Form** (add parameters one by one) and **JSON** (paste a raw JSON schema). | **Parameter fields:** | Field | Description | | - | - | | Parameter Name | The key name for this data point (e.g. `summary`, `user_sentiment`). | | Details | Description of what this parameter represents and how to extract it. | | Type | Data type: `string`, `boolean`, `number`, etc. | | Required | Whether this parameter must be present in every analysis output. | # Voice Agent Source: https://docs.subverseai.com/agents/voice-agent Build an AI agent that makes and receives phone calls ## Overview A Voice Agent is a phone-based AI that speaks and listens in real time. It handles inbound or outbound phone calls — converting speech to text (STT), processing the caller's intent with an LLM, and responding with synthesized speech (TTS). Voice agents include fine-grained controls for speech detection, interruption handling, turn-taking, call transfers, and ambient audio. **When to use a Voice Agent:** * You want an AI that can make or receive phone calls * You need voice-based customer support, appointment booking, or outbound calling * Your use case requires real-time speech interaction *** ## How to Create 1. Navigate to **Agents** in the left sidebar. 2. Click **Add Agent** and select **Voice** as the agent type. 3. Fill in the **Identity** fields — name and description. 4. Write the agent's system prompt under **Instructions**. 5. Configure the **LLM Service** (provider and model). 6. Configure the **STT Service** (speech-to-text provider and language). 7. Configure the **TTS Service** (voice provider and voice ID). 8. Configure **Turn Management** — how the agent detects when the caller has finished speaking. 9. Optionally configure **Call Settings**, **Pipeline Settings**, **Functions**, and **Analytics**. 10. Click **Save**. *** ## Deploy: Connect to a Phone Number A saved Voice Agent can be tested from the dashboard immediately, but to handle real inbound or outbound calls you need to connect it to a **Voice Channel**. A Voice Channel uses a SIP trunk to link your agent to a real phone number. Subverse supports both inbound (receive calls) and outbound (make calls) trunks. Configure an inbound or outbound SIP trunk and link it to this agent Create the SIP credential required to authenticate your trunk *** ## How to Test 1. Open the agent from the **Agents** list. 2. Click the **Call** icon to open the **Call Sidebar**. 3. Enter the bot's phone number and your personal phone number. 4. Click **Call** — the agent places an outbound call to your number. 5. Speak naturally and test the conversation flow. 6. Check the call log and transcript after the call ends. *** ## Tips & Notes * **Endpointing vs Responsiveness:** Endpointing controls the silence gap before responding; Responsiveness controls the overall speed of the pipeline. Lower both for a faster-feeling agent. * **Preemptive Generation:** Leave this on for most use cases — it significantly reduces perceived latency. Only disable it if you need strict full-turn capture (e.g. customers dictating long account numbers). * **Turn Detection:** Start with `STT` for most cases. Switch to `VAD` if users frequently complain of being cut off. * **Warm Transfer:** Always pair a warm transfer with a clear `Warm Transfer Prompt` so the receiving person understands the context. * **Backchannel:** Recommended for longer-response scenarios where the user speaks several sentences. It makes the agent feel more attentive. * **Allow List / Block List:** Use E.164 regex patterns (e.g. `^\+1\d{10}$` to match all US numbers). *** See the full configuration reference — every field, type, and default value # Voice Agent Configuration Source: https://docs.subverseai.com/agents/voice-agent-configuration Full configuration reference for Voice Agents ## Identity | Field | Type | Default | Description | | - | - | - | - | | Name | Text | — (required) | Unique identifier. Lowercase letters, numbers, and underscores only (e.g. `sales_caller`). Must start with a letter. | | Description | Text | `""` | Internal description of what this agent does. | | Architecture | Dropdown | `Prompt Based` | **Prompt Based** uses a system prompt. **Conversational Flow** uses a visual node-based builder. | | Debug Mode | Toggle | Off | Outputs extra internal reasoning logs. Use during development; disable in production. | *** ## Agent Settings | Field | Type | Default | Description | | - | - | - | - | | Greeting Message | Text | `""` | What the agent says when the call connects. Leave blank if the caller speaks first. | | Greeting Type | Dropdown | `Prompt` | **Prompt** — agent generates the greeting dynamically based on context. **Say** — agent reads exactly what you typed, word for word. | | Who Speaks First | Dropdown | `SubVerseAI Agent` | **SubVerseAI Agent** — agent speaks first (outbound style). **User** — agent waits for the caller to speak (inbound style). | | System Prompt | Text area | Empty | The main system prompt. Define the agent's identity, role, tone, capabilities, and rules. Use the **Refine using AI** button to get AI assistance writing or improving the prompt. | *** ## Large Language Model Preferences | Field | Type | Default | Description | | - | - | - | - | | LLM Model | Dropdown | — (required) | The AI model powering this agent. Each model shows its speed and reasoning ratings. | | Thinking Level | Dropdown | `Default` | Extended reasoning depth before responding. Options: **Default**, **Low**, **Medium**, **High**, **Very High**. Higher = better reasoning but slower and more expensive. | | Max Tokens | Number | None | Maximum tokens the LLM can generate per response. Leave blank to use the model's default. | | Temperature | Slider | `0.5` | Response creativity. `0.0` = consistent and precise. `1.0+` = more varied and creative. | *** ## Speech Detection Settings | Field | Type | Default | Description | | - | - | - | - | | Transcript Model | Dropdown | — (required) | The speech-to-text model used to transcribe the caller's speech (e.g. Deepgram Nova 3). | | Transcript Language | Dropdown | — (required) | Language for transcription (e.g. English (US), English (India)). | | Custom Keywords | Text | None | Words or phrases the STT model should pay extra attention to (e.g. product names, brand terms). Separate multiple entries with commas. | | Smart Format | Toggle | Off | Automatically format numbers, currencies, dates, and addresses in transcripts (e.g. "twenty dollars" → "\$20"). | | Numerals | Toggle | Off | Convert spoken numbers into digits (e.g. "five" → "5"). | | Allow Interruptions Overall | Toggle | On | Whether the caller can interrupt the agent mid-sentence. Turn off for strict scripted playback. | | Allow Interruptions Initially | Toggle | Off | Whether the caller can interrupt the very first message the agent speaks. Useful for letting eager callers skip the intro. | | Interruption Sensitivity | Slider | `2` | How easily the agent is interrupted. Higher = more sensitive. Range: 0–4. | *** ## Voice Settings | Field | Type | Default | Description | | - | - | - | - | | TTS Model | Dropdown | — (required) | The text-to-speech model for generating speech (e.g. ElevenLabs Flash V2.5). | | TTS Language | Dropdown | — (required) | Language for speech synthesis (e.g. English (US)). | | Gender | Radio | None | Filter voices by **Male** or **Female**. Optional. | | Voice | Dropdown | — (required) | The specific voice to use. Click **Browse** to preview available voices from the selected provider. | | Speed | Slider | `2` | Speaking speed. Higher = faster. Range: 0–3. | | Voice Stability (Expressiveness) | Slider | `0.5` | How consistent the voice sounds. Lower = more expressive and varied. Higher = very consistent. | | Similarity Boost | Slider | `0.8` | How closely the voice matches its original model. Higher = more faithful but may sound less natural. | | Voice Pitch | Slider | `2` | Voice pitch adjustment. Range: 0–4. | | Voice Volume | Slider | `2` | Output volume level. Range: 0–4. | *** ## Call Settings | Field | Type | Default | Description | | - | - | - | - | | Communication Method | Dropdown | `Two Way` | **Two Way** — agent speaks and listens. **One Way** — agent only speaks (e.g. announcements). | | DTMF Enabled | Toggle | Off | Enable touch-tone input. The agent can detect digit presses (e.g. "Press 1 for sales"). | | Background Ambient | Toggle | Off | Play subtle background audio (e.g. office sounds) to make calls feel less robotic. | | Background Thinking | Toggle | Off | Play a brief sound while the agent is generating a response, signaling to the caller that something is happening. | | Transfer To | Text | None | SIP URI or phone number to transfer the call to when a transfer is triggered. | | Display Phone Number | Radio | `Show Agent Number` | **Show Caller Number** — displays the caller's number to the recipient. **Show Agent Number** — displays the agent's number. | | Transfer Type | Radio | `Cold Transfer` | **Warm Transfer** — agent introduces the caller before transferring. **Cold Transfer** — call is transferred immediately without introduction. | | Warm Transfer Prompt | Text | `""` | The message the agent reads during a warm transfer (e.g. "I have a customer calling about a billing issue"). Only applies when Transfer Type is **Warm Transfer**. | | Whisper | Toggle | Off | The agent can hear the caller but the caller cannot hear the agent. Useful for live coaching scenarios. | | Silence Time | Number | `8` | Seconds of caller silence before a silence action is triggered. | | Silence Turns | Number | `2` | Consecutive silence events before the agent takes action. | | Max Duration | Number | `600` | Maximum call length in seconds. The call ends automatically at this limit. | | Silence Prompt | Text | `""` | What the agent says when a silence timeout occurs (e.g. "Are you still there?"). | | Agent Responsiveness | Slider | `4` | Overall responsiveness after end-of-turn is detected. Higher = responds more quickly. Range: 0–4. | | Preemptive Response | Toggle | On | Agent starts generating a response before the caller fully finishes speaking. Significantly reduces perceived latency. Turn off only if you need strict full-turn capture. | | Session Timeout (mins) | Number | None | Minutes of inactivity after which the call session ends automatically. Leave blank for no timeout. | *** ## Agent Transfers | Field | Type | Default | Description | | - | - | - | - | | Select Agents | Dropdown | None | Other Subverse agents this agent can transfer the conversation to during a call. | *** ## Knowledgebase Settings | Field | Type | Default | Description | | - | - | - | - | | Knowledge Base | Dropdown | None | Attach a Knowledge Base so the agent can look up answers from your documents during a call. | *** ## Function Settings | Field | Type | Default | Description | | - | - | - | - | | Pre Call Tools | Multi-select | Empty | LLM tools that run automatically before the call starts (e.g. fetch customer account info). | | During Call Tools | Multi-select | Empty | Tools the agent can call mid-call based on the conversation (e.g. look up order status, book an appointment, transfer the call). | | Post Call Tools | Multi-select | Empty | LLM tools that run automatically after the call ends (e.g. update CRM, send an SMS follow-up). | *** ## Agent Security Settings | Field | Type | Default | Description | | - | - | - | - | | Allow List (Allowed Callers) | Text area | Empty | Regex patterns for phone numbers allowed to interact with this agent, separated by commas. Leave empty to allow all callers. | | Block List (Blocked Callers) | Text area | Empty | Regex patterns for phone numbers that are blocked, separated by commas. Takes priority over Allow List. | *** ## Post Call Data Analysis After each call, the agent can automatically analyze the transcript and extract structured data. | Field | Type | Description | | - | - | - | | LLM Model | Dropdown | The AI model used to run the post-call analysis. Can differ from the main agent model. | | Parameters | Form / JSON | Define the data points to extract from each call. Switch between **Form** (add parameters one by one) and **JSON** (paste a raw JSON schema). | **Parameter fields:** | Field | Description | | - | - | | Parameter Name | The key name for this data point (e.g. `summary`, `user_sentiment`). | | Details | Description of what this parameter represents and how to extract it. | | Type | Data type: `string`, `boolean`, `number`, etc. | | Required | Whether this parameter must be present in every analysis output. | # Dynamic Inputs Source: https://docs.subverseai.com/agentverse/dynamic-inputs Link upstream node outputs to downstream node parameters using the {{ }} expression syntax # Dynamic Inputs Every node in AgentVerse produces a structured JSON output when it runs. **Dynamic inputs** let you reference that output in any downstream node's parameters — turning static configuration into data-driven workflows. *** ## How It Works When you test a node using the **Test** button, AgentVerse captures the node's real output. A **link icon** ( ⚡ ) then appears next to every parameter in downstream nodes. Clicking it opens a field picker showing all available outputs from upstream nodes — click any field to insert it as an expression. Select the node whose output you want to reference. Click **Test** in the node panel. The node executes and its output is captured and displayed. Click the node where you want to use the upstream data. Any parameter that supports expressions will show a **link icon** (⚡) when hovered. Click the ⚡ icon next to the parameter. A picker opens showing all available fields from upstream nodes, organised by node name. Browse the tree and click the field you want. AgentVerse inserts the corresponding `{{ }}` expression automatically. The field picker is only populated after an upstream node has been tested. If you don't see any fields, test the upstream node first. *** ## The `{{ }}` Expression Syntax Expressions are written inside double curly braces: `{{ }}`. You can reference any field from any upstream node that has run. ### Basic Field Reference ``` {{ nodeName.fieldName }} ``` For example, if a **Webhook** trigger receives a POST body with a `message` field: ``` {{ webhook.body.message }} ``` ### Nested Fields Use dot notation to traverse nested objects: ``` {{ aiAgent.output.text }} {{ shopify.order.customer.email }} {{ airtable.fields.Status }} ``` ### Array Items Reference a specific index in an array: ``` {{ forLoop.item.name }} {{ webhook.body.contacts[0].phone }} ``` ### Multiple Expressions in One Field Expressions can be embedded inside a string with other text: ``` Hello {{ subverseAgents.extractedData.customerName }}, your order {{ shopify.order.id }} is confirmed. ``` *** ## Available Node Outputs Each node exposes its output under its **node name** — the label shown in the canvas. If you rename a node, the expression path updates accordingly. | Node | Example Expression | | - | - | | Webhook Trigger | `{{ webhook.body.message }}` | | AI Agent | `{{ aiAgent.text }}` | | Airtable | `{{ airtable.fields.Name }}` | | HTTP Request | `{{ httpRequest.data.id }}` | | SubVerse Agents | `{{ subverseAgents.extractedData.intent }}` | | For Loop | `{{ forLoop.item }}` | | Conditions | `{{ conditions.outputIndex }}` | Rename your nodes to descriptive names (e.g. `fetchCustomer` instead of `HTTP Request`) to make expressions easier to read and maintain. *** ## Testing Expressions Before activating your orchestration, verify expressions are resolving correctly: 1. **Test each node in sequence** — start from the trigger and test nodes one by one. 2. **Check the output panel** — each tested node shows its full JSON output. Confirm the field you're referencing is present. 3. **Use the expression editor** — hover the parameter field and click ⚡ to browse and validate available fields. If an upstream node fails or is skipped, its output will not be available. Add [Conditions](./nodes/conditions.md) nodes to handle missing or null values before referencing them downstream. *** ## Common Patterns ### Pass webhook data to an AI prompt ``` Summarise the following customer message: {{ webhook.body.message }} ``` ### Build a dynamic Slack message from AI output ``` {{ aiAgent.text }} ``` ### Reference extracted data from a SubVerse AI conversation ``` Customer intent: {{ subverseAgents.extractedData.intent }} Preferred date: {{ subverseAgents.extractedData.preferredDate }} ``` ### Use loop item data inside a loop When iterating with a [For Loop](./nodes/for-loop.md), each iteration exposes the current item: ``` {{ forLoop.item.email }} {{ forLoop.item.orderId }} ``` *** ## Related Pages * [Node Types](./node-types.md) — Understand all node categories and their outputs * [Quickstart](./quickstart.md) — See dynamic inputs in action in a real orchestration * [For Loop](./nodes/for-loop.md) — Iterating over arrays with dynamic item references # Introduction to AgentVerse Source: https://docs.subverseai.com/agentverse/introduction SubVerse AI's Agent Orchestration Engine — build and run automated workflows that combine AI agents with business integrations # Introduction to AgentVerse AgentVerse is SubVerse AI's Agent Orchestration Engine — a visual, low-code platform for building and running automated workflows that combine AI agents with business integrations. *** ## What is AgentVerse? AgentVerse lets you design **orchestrations** — directed graphs of nodes that execute in sequence or in parallel. Each node represents a discrete unit of work: calling an API, running an AI model, applying conditional logic, or waiting for a human decision. Orchestrations are triggered by events (webhooks, schedules, incoming messages) and can route data through AI agents, third-party services, and control-flow logic before delivering a result. *** ## Core Concepts | Concept | Description | | - | - | | **Orchestration** | The workflow graph you build — a collection of connected nodes | | **Node** | A single step in an orchestration (trigger, action, logic, or AI) | | **Orchestration Run** | A single execution instance of an orchestration | | **Connection** | A directed edge between two nodes that carries data | | **Credentials** | Stored authentication details used by integration nodes | *** ## Node Categories AgentVerse nodes are organised into four categories: Start an orchestration in response to an event — webhook, schedule, Slack, WhatsApp, Shopify, and more Interact with external services — send messages, write records, make HTTP calls, upload files Control execution — branch with conditions, loop over arrays, pause and wait, require human approval Run AI — call any LLM provider or execute full SubVerse AI agent conversations *** ## Key Features * **Visual canvas** — drag-and-drop orchestration builder with real-time previews * **Any LLM** — connect AI Agent nodes to OpenAI, Anthropic, Google, or any OpenAI-compatible endpoint * **Dynamic inputs** — reference upstream node outputs anywhere using `{{ nodeName.field }}` expressions * **Human-in-the-loop** — pause orchestrations for human approval via Slack or email * **Robust execution engine** — built for reliability with fault tolerance and retry support * **Multi-channel AI agents** — run SubVerse AI agents over voice, WhatsApp, email, and chat * **Fine-grained monitoring** — inspect every orchestration run, node output, and error in detail *** ## How Orchestrations Work ``` Trigger Node │ ▼ Action / AI / Logic Node(s) │ ▼ Output (API call, message, database write, etc.) ``` Data flows between nodes as a structured JSON object. Each node receives the output of its upstream node, transforms or acts on it, and passes the result downstream. Reference any upstream value in a node parameter using double curly braces: ``` {{ webhook.body.message }} {{ aiAgent.text }} {{ airtable.fields.Status }} ``` See [Dynamic Inputs](./dynamic-inputs.md) for a full guide on the `{{ }}` expression syntax and how to link fields using the visual picker. For AI Agent nodes, **AI Tool** connections (sub-edges) allow the agent to call other nodes as tools during reasoning. *** ## Next Steps Build your first orchestration in 10 minutes Understand all node categories in detail Track and debug orchestration runs # Monitoring Source: https://docs.subverseai.com/agentverse/monitoring Track orchestration runs, inspect node-level execution traces, and set up failure alerts # Monitoring AgentVerse logs every orchestration execution in full detail — inputs, outputs, errors, and timing at both the run level and the individual node level. Use the monitoring panel to debug issues, verify behaviour, and track performance over time. *** ## Orchestration Runs Open any orchestration and click the **Runs** tab to see all past and in-progress executions. ### Run Statuses | Status | Description | | - | - | | `Running` | The orchestration is currently executing | | `Success` | All nodes completed without errors | | `Failed` | One or more nodes encountered an error | | `Waiting` | The run is paused (Wait node or Human in the Loop) | | `Cancelled` | The run was manually stopped | ### Filtering Runs Narrow the list using: | Filter | Description | | - | - | | **Status** | Show only `Success`, `Failed`, `Running`, or `Waiting` runs | | **Date Range** | Filter by start time window | | **Trigger Type** | Filter by how the run was initiated | | **Run ID** | Search for a specific run by its unique ID | *** ## Run Detail View Click any run row to open the **Run Detail** panel. This shows everything that happened during that execution. ### Run Summary | Field | Description | | - | - | | **Run ID** | Unique identifier for this execution — use this when contacting support | | **Trigger** | Which trigger started the run: `webhook`, `schedule`, or `manual` | | **Started At / Ended At** | Timestamps for run start and completion | | **Duration** | Total wall-clock execution time | | **Status** | Final run outcome | ### Node Execution Trace The trace shows every node that ran, in order: | Column | Description | | - | - | | **Node** | Node name and type | | **Status** | `Success`, `Error`, or `Skipped` | | **Started At** | When the node began executing | | **Duration** | How long the node took | | **Input** | The data received by the node | | **Output** | The data produced by the node | | **Error** | Error message and stack trace if the node failed | Click any node row to expand and inspect its **full input and output payloads as JSON**. This is the primary tool for debugging unexpected node behaviour. When debugging, expand both the input and output of the failing node side by side. The input tells you what data the node received; the output (or error) tells you what went wrong. *** ## Re-running Failed Runs To retry a failed orchestration: 1. Find the failed run in the **Runs** panel. 2. Click the **Re-run** button (replay icon) on the right. 3. The orchestration restarts from the beginning using the same original trigger data. Re-runs create a new Run ID and are logged as a separate entry — the original failed run is preserved. This means you can compare the re-run trace against the original to confirm the fix. *** ## Alerts and Notifications Configure alerts to be notified automatically when an orchestration fails or exceeds a duration threshold. ### Setting Up Alerts 1. Open the orchestration and navigate to **Settings → Alerts**. 2. Click **Add Alert**. 3. Configure the alert rule: | Field | Options | | - | - | | **Trigger On** | `Orchestration Failed`, `Orchestration Timed Out`, `Node Error` | | **Notify Via** | `Slack`, `Email` | | **Destination** | Slack channel name or email address | | **Cooldown** | Minimum time between repeated alerts for the same orchestration (prevents alert spam) | ### Alert Payload Every alert includes: * Orchestration name and ID * Run ID * Failed node name and error message * Direct link to the run detail page Set a cooldown period for high-frequency orchestrations to avoid alert fatigue. A cooldown of 5–15 minutes is typical for production orchestrations. *** ## Related Pages * [Troubleshooting](./troubleshooting.md) — Diagnose and resolve common issues * [Quickstart](./quickstart.md) — Build and test your first orchestration # Node Types Source: https://docs.subverseai.com/agentverse/node-types Overview of all AgentVerse node categories — triggers, actions, logic, and AI nodes # Node Types AgentVerse nodes are the building blocks of every orchestration. Each node performs a specific function and connects to other nodes to form a workflow. *** ## Categories ### Trigger Nodes Trigger nodes start an orchestration. Every orchestration must have exactly one trigger node as its entry point. Trigger nodes have no inputs — they only produce outputs. | Node | Description | | - | - | | [Webhook](./nodes/webhook.md) | Start an orchestration via an incoming HTTP request | | [Starter — Schedule At](./nodes/schedule-trigger.md) | Run an orchestration on a time-based schedule | | [Starter — Manual Trigger](./nodes/manual-trigger.md) | Start an orchestration manually from the UI | | [Airtable Trigger](./nodes/airtable-trigger.md) | Trigger on Airtable record events | | [Slack Trigger](./nodes/slack-trigger.md) | Trigger on Slack events (messages, reactions, etc.) | | [WhatsApp Trigger](./nodes/whatsapp-trigger.md) | Trigger on incoming WhatsApp messages | | [Shopify Trigger](./nodes/shopify-trigger.md) | Trigger on Shopify store events (orders, carts, products, etc.) | | [SubVerse AI Trigger](./nodes/subverse-ai-trigger.md) | Trigger when a SubVerse AI voice call completes | *** ### Action Nodes Action nodes interact with external services. They receive data from upstream nodes, perform an operation (API call, database write, file upload), and return a result. | Node | Description | | - | - | | [Slack](./nodes/slack.mdx) | Send messages, manage channels, and interact with Slack | | [Airtable](./nodes/airtable.mdx) | Read, create, update, and delete Airtable records | | [Shopify](./nodes/shopify.mdx) | Manage Shopify orders, products, customers, and inventory | | [WhatsApp](./nodes/whatsapp.mdx) | Send WhatsApp messages and manage contacts | | [Freshdesk](./nodes/freshdesk.mdx) | Manage Freshdesk support tickets, notes, and replies | | [HTTP Request](./nodes/http-request.mdx) | Make HTTP calls to any external API | | [Send Email](./nodes/email.mdx) | Send emails through any SMTP server | | [File Upload](./nodes/file-upload.mdx) | Upload files to cloud storage (S3) | | [Respond to Webhook](./nodes/respond-to-webhook.mdx) | Send a custom HTTP response back to a webhook caller | *** ### Logic Nodes Logic nodes control the flow of an orchestration. They branch, loop, pause, or wait for external input before continuing execution. | Node | Description | | - | - | | [Conditions](./nodes/conditions.md) | Branch execution based on one or more conditions | | [For Loop](./nodes/for-loop.md) | Iterate over a list of items or repeat N times | | [Wait](./nodes/wait.md) | Pause execution for a duration or until an event | | [Human in the Loop](./nodes/human-in-the-loop.md) | Pause and require a human approval to continue | *** ### AI Nodes AI nodes integrate language models and AI agents into your orchestration. They support multi-modal operations and can connect to other nodes as tools. | Node | Description | | - | - | | [AI Agent](./nodes/ai-agent.md) | Call any LLM provider to generate text or images | | [SubVerse Agents](./nodes/subverse-agents.md) | Execute SubVerse AI agents over voice, WhatsApp, email, or chat | *** ## Connection Types Nodes communicate over two types of connections: | Type | Description | | - | - | | **Main** | The primary data flow between nodes — carries JSON data from one node to the next | | **AI Tool** | Connects tool nodes to an AI Agent node, making them callable by the agent during reasoning | AI Tool connections are only available on the **AI Agent** node. Connect any action or logic node as a tool to give the agent the ability to call it autonomously. *** ## Data Flow and `{{ }}` Expressions Data moves between nodes as structured JSON. Reference any upstream node's output in a parameter field using the `{{ }}` expression syntax: ``` {{ nodeName.fieldName }} {{ nodeName.nested.field }} {{ forLoop.item.email }} ``` Every node parameter that accepts expressions shows a **⚡ link icon** when hovered. Click it to open the field picker, which shows all available outputs from upstream tested nodes — click any field to insert the expression automatically. See [Dynamic Inputs](./dynamic-inputs.md) for the full guide on expressions, the field picker, and common patterns. *** ## Node Parameters All nodes share a common parameter structure: | Property | Description | | - | - | | **Display Name** | Label shown on the canvas | | **Node Name** | Internal identifier used in `{{ }}` expression references | | **Credentials** | Stored authentication details for external services | | **Parameters** | Node-specific configuration fields | Parameters support static values, `{{ }}` expressions, and dynamic option loading from connected external services. # Ai agent Source: https://docs.subverseai.com/agentverse/nodes/ai-agent # AI Agent The **AI Agent** node calls a large language model to generate text or images. It supports any LLM provider, configurable system instructions, tool connections, and multi-modal operations. AI Agent Node *** ## Use Cases * Generate summaries, classifications, or structured data from upstream inputs * Answer questions based on dynamic context from other nodes * Generate images from text prompts * Use reasoning models for complex decision-making within an orchestration * Build autonomous agents that use other nodes as tools *** ## Node Reference ### Parameters | Parameter | Type | Required | Description | | - | - | - | - | | **Provider** | Select | Yes | The LLM provider to use: `OpenAI`, `Anthropic`, `Google`, or `Custom` | | **Model** | String | Yes | The model ID (e.g. `gpt-4o`, `claude-3-5-sonnet-20241022`, `gemini-1.5-pro`) | | **Operation** | Select | Yes | `Generate a text response` or `Generate an image` | | **Credential** | Credential | Yes | API key credential for the selected provider | | **Instructions** | String | No | System instructions that guide the AI behavior | | **Prompt** | String | Yes | The user message or input to the model | | **Reasoning Effort** | Select | No | `Low`, `Medium`, or `High` — applicable to GPT-5, o-series, and other reasoning models | | **Service Tier** | Select | No | The API service tier to use for the request | | **Max Tokens** | Number | No | Maximum tokens in the response | | **Temperature** | Number | No | Sampling temperature (0–2). Higher = more creative. | | **Timeout** | Number | No | Maximum time to wait for a response (in seconds) | *** ## Providers | Provider | Credential Type | Notes | | - | - | - | | `OpenAI` | OpenAI API Key | Supports GPT-4, GPT-4o, o1, DALL-E image generation | | `Anthropic` | Anthropic API Key | Supports Claude 3, Claude 4 models | | `Google` | Google AI API Key | Supports Gemini 1.5, Gemini 2 models | | `Custom` | Bearer Token / API Key | Use any OpenAI-compatible API endpoint | *** ## Operations ### Generate a text response Calls the model with system instructions and a user prompt. Returns the generated text response. | Field | Description | | - | - | | **Instructions** | System instructions that set the model's persona or task context | | **Prompt** | The user message. Supports template expressions (e.g. `{{ webhook.body.message }}`). | | **Reasoning Effort** | Controls the depth of reasoning for supported models (GPT-5, o-series). | ### Generate Image Generates an image from a text description (requires an image-capable model, e.g. DALL-E 3). | Field | Description | | - | - | | **Prompt** | Text description of the image to generate | | **Image Size** | Output image dimensions (e.g. `1024x1024`, `1792x1024`) | | **Quality** | `Standard` or `HD` | | **Style** | `Vivid` or `Natural` | *** ## Tool Connections (AI Tool Edges) Connect other nodes to the AI Agent via an **AI Tool** edge to give the agent the ability to call those nodes during reasoning. The agent autonomously decides when and how to use each tool. AI Agent with Tools Example: Connect an **Airtable** node and an **HTTP Request** node as tools. The agent will query Airtable or call the API as needed to answer the user's request. *** ## Output Data For `Generate Text`: ```json theme={null} { "text": "The primary benefits of AI automation include...", "model": "gpt-4o", "usage": { "promptTokens": 245, "completionTokens": 87, "totalTokens": 332 }, "finishReason": "stop" } ``` Reference in downstream nodes: ``` {{ aiAgent.text }} {{ aiAgent.usage.totalTokens }} ``` For `Generate Image`: ```json theme={null} { "imageUrl": "https://oaidalleapiprodscus.blob.core.windows.net/...", "revisedPrompt": "..." } ``` *** ## Related Nodes * [SubVerse Agents](./subverse-agents.md) — Run a full multi-turn SubVerse AI agent with channel support * [Conditions](./conditions.md) — Branch based on AI output * [Slack](./slack.md) — Send the generated text to a Slack channel # Airtable Source: https://docs.subverseai.com/agentverse/nodes/airtable # Airtable The **Airtable** node lets you read and write data in Airtable bases — create, retrieve, update, and delete records, or list bases and tables. Airtable Node *** ## Credentials Two credential types are supported: | Type | Description | | - | - | | **Airtable Personal Access Token** | Token-based authentication using an Airtable API key | | **Airtable OAuth2** | Platform-managed OAuth2 — sign in with your Airtable account | To create a credential: 1. Go to **Settings → Credentials → New Credential** 2. Select the desired Airtable credential type 3. Complete the authentication flow *** ## Operations ### Record | Operation | Description | | - | - | | `Create` | Add a new record to a table | | `Get` | Retrieve a single record by ID | | `Get Many` | Retrieve multiple records with optional filters and sorting | | `Update` | Update fields on an existing record | | `Upsert` | Create a record if it doesn't exist, update it if it does | | `Delete` | Delete a record by ID | ### Base | Operation | Description | | - | - | | `Get Many` | List all bases accessible to the credential, with optional permission-level filtering | | `Get Schema` | Retrieve the schema (tables and fields) of a base | *** ## Parameters: Create Record | Parameter | Type | Required | Description | | - | - | - | - | | **Base** | Resource Locator | Yes | The Airtable base to write to | | **Table** | Resource Locator | Yes | The table to create a record in | | **Fields** | Key-Value | Yes | The field names and values for the new record | | **Type Cast** | Boolean | No | Automatically cast field values to the correct type | ## Parameters: Get Many Bases | Parameter | Type | Required | Description | | - | - | - | - | | **Return All** | Boolean | No | When enabled, returns all bases instead of up to a limit | | **Options — Permission Level** | Select | No | Filter returned bases by permission level | ## Parameters: Get Many Records | Parameter | Type | Required | Description | | - | - | - | - | | **Base** | Resource Locator | Yes | The Airtable base to read from | | **Table** | Resource Locator | Yes | The table to read records from | | **Filter by Formula** | String | No | Airtable formula to filter records (e.g. `{Status} = 'Active'`) | | **Sort** | Collection | No | Sort by one or more fields | | **Max Records** | Number | No | Maximum number of records to return | | **Fields** | Multi-Select | No | Return only these specific fields | | **View** | String | No | Limit results to a specific view | *** ## Output Data A single record returned from `Get` or `Create`: ```json theme={null} { "id": "recXXXXXXXXXXXXXX", "createdTime": "2025-03-10T09:00:00.000Z", "fields": { "Name": "Acme Corp", "Status": "Active", "Revenue": 150000, "Tags": ["Enterprise", "US"] } } ``` Reference fields in downstream nodes: ``` {{ airtable.fields.Name }} {{ airtable.fields.Status }} {{ airtable.id }} ``` *** ## Filter Formula Examples | Formula | Description | | - | - | | `{Status} = 'Active'` | Records where Status equals "Active" | | `{Revenue} > 100000` | Records where Revenue is greater than 100,000 | | `AND({Status} = 'Active', {Region} = 'US')` | Active records in the US | | `NOT({Email} = '')` | Records with a non-empty email | *** ## Related Nodes * [Airtable Trigger](./airtable-trigger.md) — Trigger an orchestration on Airtable record events * [For Loop](./for-loop.md) — Iterate over a list of retrieved records # Airtable trigger Source: https://docs.subverseai.com/agentverse/nodes/airtable-trigger # Airtable Trigger The **Airtable Trigger** starts an orchestration when a record is created, updated, or deleted in an Airtable base. Airtable Trigger Node *** ## Use Cases * Sync Airtable records to another service when new rows are added * Notify a Slack channel when a CRM record is updated * Trigger an AI agent when new data arrives in Airtable *** ## Credentials This node requires an **Airtable** credential. Two credential types are supported: | Type | Description | | - | - | | **Airtable Personal Access Token** | Token-based authentication using an Airtable API token | | **Airtable OAuth2** | Platform-managed OAuth2 — sign in with your Airtable account | To create a credential, go to **Settings → Credentials → New Credential** and select the Airtable credential type. *** ## Node Reference ### Parameters | Parameter | Type | Required | Description | | - | - | - | - | | **Credential** | Credential | Yes | Select or create an Airtable credential | | **Base** | Resource Locator | Yes | The Airtable base to monitor — select from list, by URL, or by ID | | **Table** | Resource Locator | Yes | The table within the base to monitor — select from list, by URL, or by ID | | **Trigger Field** | String | Yes | A **Created Time** or **Last Modified Time** field used to detect new/updated records. Your table schema must include one of these field types for the trigger to work correctly. | | **Download Attachments** | Boolean | No | When enabled, downloads any attachment fields defined in **Additional Fields** | | **Additional Fields — Fields** | String | No | Comma-separated list of field names to return in the output (returns all fields by default) | *** ## Output Data The trigger outputs the full record that triggered the event: ```json theme={null} { "id": "recXXXXXXXXXXXXXX", "createdTime": "2025-03-10T09:00:00.000Z", "fields": { "Name": "Acme Corp", "Status": "Active", "Revenue": 150000 } } ``` Reference fields in downstream nodes: ``` {{ airtableTrigger.fields.Name }} {{ airtableTrigger.fields.Status }} {{ airtableTrigger.id }} ``` *** ## Related Nodes * [Airtable](./airtable.md) — Read and write Airtable records within an orchestration * [Conditions](./conditions.md) — Branch based on record field values # Conditions Source: https://docs.subverseai.com/agentverse/nodes/conditions # Conditions The **Conditions** node routes execution to different branches based on evaluated conditions. Each branch has an output connection, and data is routed to the first branch whose condition is true. Conditions Node *** ## Use Cases * Route an order to different fulfillment workflows based on order value * Send different Slack messages depending on AI agent output * Escalate to a human if an AI response confidence is low * Branch on HTTP response status codes from an upstream node *** ## Node Reference ### Parameters Each Conditions node has one or more **Condition Branches**. Each branch has a **Branch Name** and one or more rules. | Parameter | Type | Description | | - | - | - | | **Branch Name** | String | A label for this branch (e.g. `Condition 1`, `High Value`) | | **Rule Type** | Toggle | `Rule-based` — define a field comparison; `AI` — describe the condition in plain language | | **+ Add Rule** | Button | Add an additional rule to this branch | | **+ Add Condition Branch** | Button | Add a new output branch to the node | *** ## Rule Types ### Rule-based Define conditions manually using field comparisons: | Field | Description | | - | - | | **Value 1** | Left-hand side — reference upstream data using dot notation (e.g. `input.output_parsed.status`) | | **Operation** | Comparison operator (see below) | | **Value 2** | Right-hand side — static value or expression | ### Available Operators | Operator | Description | | - | - | | `Equal` | Value 1 equals Value 2 | | `Not Equal` | Value 1 does not equal Value 2 | | `Greater Than` | Value 1 > Value 2 (numeric) | | `Less Than` | Value 1 \< Value 2 (numeric) | | `Greater Than or Equal` | Value 1 ≥ Value 2 (numeric) | | `Less Than or Equal` | Value 1 ≤ Value 2 (numeric) | | `Contains` | String contains substring | | `Does Not Contain` | String does not contain substring | | `Starts With` | String starts with prefix | | `Ends With` | String ends with suffix | | `Is Empty` | Value is empty, null, or undefined | | `Is Not Empty` | Value has a non-empty value | | `Regex Match` | String matches a regular expression | ### AI Mode In AI mode, describe the condition in plain language. AgentVerse evaluates the upstream data against your description using an LLM. | Field | Description | | - | - | | **Condition Description** | Natural language description of the condition (e.g. "The customer is asking to speak to a manager") | *** ## Multiple Branches Each condition creates a separate output branch. The node routes data to the **first** branch whose condition evaluates to `true`. If no condition matches and a fallback branch is enabled, data is routed to the fallback. | Branch | Condition | | - | - | | Branch 1 | `{{ order.total }} >= 1000` | | Branch 2 | `{{ order.total }} >= 500` | | Branch 3 (Fallback) | Everything else | *** ## Output Data Each branch receives the same input data that entered the Conditions node. No transformation is applied — conditions only control routing. *** ## Related Nodes * [For Loop](./for-loop.md) — Iterate over an array conditionally * [Human in the Loop](./human-in-the-loop.md) — Route edge cases for human review * [AI Agent](./ai-agent.md) — Use AI mode with an upstream LLM node for complex evaluations # Send Email Source: https://docs.subverseai.com/agentverse/nodes/email Send automated emails through any SMTP server from an AgentVerse orchestration # Send Email The **Send Email** node sends emails through an SMTP server. Use it for transactional messages, alerts, reports, and follow-ups inside an orchestration. Send Email Node *** ## Credentials This node requires an **[Email (SMTP / IMAP)](/credentials/types/email-smtp)** credential. To create a credential: 1. Go to **Settings → Credentials → New Credential** 2. Select **Email (SMTP / IMAP)** 3. Enter your SMTP username, password, host, port, and encryption *** ## Use Cases * **Order Confirmations**: Email receipts and invoices after a purchase * **Appointment Reminders**: Send appointment details to customers * **Status Alerts**: Notify internal teams or customers when events occur * **Reports**: Email generated summaries or documents * **Follow-ups**: Send post-call or post-chat summaries *** ## Parameters | Parameter | Type | Required | Description | | - | - | - | - | | **Credential** | Credential | Yes | Select an [Email (SMTP / IMAP)](/credentials/types/email-smtp) credential | | **From Email** | String | No | Sender address in `sender@example.com` or `Name ` format. Defaults to the credential username when omitted | | **To Email** | String | Yes | Recipient email address | | **CC Email** | String | No | CC recipient address | | **BCC Email** | String | No | BCC recipient address | | **Reply To** | String | No | Reply-To address | | **Subject** | String | Yes | Email subject line | | **Email Format** | Select | Yes | `HTML`, `Text`, or `Both` (default: `HTML`) | | **Text** | String | No | Plain text body. Shown when Email Format is `Text` or `Both` | | **HTML** | String | No | HTML body. Shown when Email Format is `HTML` or `Both`. Supports the built-in HTML editor | | **Attachments** | Collection | No | Files to attach by public link or direct upload. Each attachment requires a file URL; the file name is optional | | **Ignore SSL Issues (Insecure)** | Boolean | No | Bypass SSL certificate validation (default: disabled) | | **Append Attribution** | Boolean | No | Add a "Sent via SubverseAI" footer (default: disabled) | ### Email Format | Format | Behavior | | - | - | | `HTML` | Sends only the HTML body | | `Text` | Sends only the plain text body | | `Both` | Sends both HTML and plain text; the recipient's client decides which to display | ### Attachments Each attachment supports: | Field | Required | Description | | - | - | - | | **Attachment Type** | Yes | Choose `Link` for an existing URL or `Upload File` to upload a file directly | | **File URL** | Yes | Public URL for link mode. In upload mode, this value is set automatically after the file is uploaded | | **File Name** | No | Name shown in the email, e.g. `invoice.pdf`. When omitted, the node derives it from the URL | Uploaded files stored by SubverseAI are resolved to a temporary signed URL when the email is sent. *** ## Output Data A successful send returns: ```json theme={null} { "messageId": "", "response": "250 OK", "accepted": ["recipient@example.com"], "rejected": [] } ``` Reference in downstream nodes: ``` {{ sendEmail.messageId }} {{ sendEmail.accepted }} {{ sendEmail.rejected }} ``` *** ## Common Patterns ### Attach a File by URL ``` HTTP Request or upstream node (returns a file URL) ↓ Send Email (Attachment Type: Link) ``` Map the attachment **File URL** to the upstream URL. You can leave **File Name** blank to derive it automatically from the URL. ### Upload and Attach a File Choose **Upload File** in the attachment, then drag and drop or select the file. The uploaded file URL is populated automatically. ### Send AI-Generated Follow-up ``` AI Agent Node (generate email subject and body) ↓ Send Email (subject and body linked from AI Agent output) ``` *** ## Related Nodes * [HTTP Request](./http-request.md) — Fetch files or data to include in an email * [SubVerse Agents](./subverse-agents.md) — Hand off email conversations to an AI agent * [Conditions](./conditions.md) — Branch based on send success or failure Link the **Subject**, **HTML**, and **Text** fields from an upstream **AI Agent** node to generate personalized, context-aware emails. For Gmail and other providers with app-specific passwords, use the app password in the credential, not your regular account password. # File upload Source: https://docs.subverseai.com/agentverse/nodes/file-upload # File Upload The **File Upload** node uploads files to cloud storage (S3) from within an orchestration. It supports multiple input methods — direct file, base64 string, public URL, or WhatsApp media — and returns a public download URL. File Upload Node *** ## Use Cases * Store files received from a webhook or WhatsApp message in S3 * Convert base64-encoded file data to a publicly accessible URL * Mirror files from an external URL into your own storage * Attach uploaded file URLs to records in Airtable or Slack *** ## Node Reference ### Parameters | Parameter | Type | Required | Description | | - | - | - | - | | **Operation** | Select | Yes | The upload operation to perform (see below) | | **Media ID** | String | Conditional | WhatsApp media ID from the incoming message (required for `Upload WhatsApp Media`) | | **Custom File Name** | String | No | Name for the uploaded file (auto-generated if not provided) | | **Content Type** | String | No | MIME type of the file (auto-detected if not provided, e.g. `application/pdf`) | | **URL Expiry (TTL)** | Number | No | How long the presigned download URL remains valid, in minutes (default: `10`) | | **Bucket Path** | String | No | Sub-folder path within the storage bucket (default: `uploads/workflow/`) | ### Operations | Operation | Description | | - | - | | `Upload WhatsApp Media` | Download a media item from WhatsApp using its media ID and upload it to storage | | `Upload from URL` | Download a file from a public URL and upload it to storage | | `Upload Binary` | Upload a binary file received from an upstream node | *** ## Output Data A successful upload returns the storage URL: ```json theme={null} { "url": "https://subverse-storage.s3.ap-south-1.amazonaws.com/uploads/report-2025.pdf", "fileName": "report-2025.pdf", "mimeType": "application/pdf", "size": 204800, "uploadedAt": "2025-03-10T09:00:00.000Z" } ``` Reference in downstream nodes: ``` {{ fileUpload.url }} {{ fileUpload.fileName }} ``` *** ## Related Nodes * [WhatsApp Trigger](./whatsapp-trigger.md) — Receive a WhatsApp media message and upload the file * [Airtable](./airtable.md) — Attach the uploaded URL to an Airtable record * [Slack](./slack.md) — Share the file URL in a Slack message # For loop Source: https://docs.subverseai.com/agentverse/nodes/for-loop # For Loop The **For Loop** node iterates over a collection of items or repeats a sub-graph N times. Nodes placed inside the loop body execute once per item or iteration. For Loop Node *** ## Use Cases * Process each record from an Airtable query individually * Send a personalized Slack message to each user in a list * Call an AI Agent once for each item in an array * Retry an operation a fixed number of times *** ## Node Reference ### Parameters | Parameter | Type | Required | Description | | - | - | - | - | | **Loop Mode** | Select | Yes | How to iterate: `Count` or `Array` (see below) | | **Iteration Count** | Number | Conditional | Number of iterations (required when Mode is `Count`) | | **Input Array** | Expression | Conditional | The array to iterate over (required when Mode is `Array`) | | **Execution Mode** | Select | No | `Sequential` or `Parallel` — how iterations are executed | | **Max Concurrency** | Number | No | Max parallel iterations when using `Parallel` mode (max: 10) | | **Error Handling** | Toggle | No | `Fail Fast` — stop on first error; `Continue on Error` — log and continue | ### Loop Modes | Mode | Description | | - | - | | `Count` | Run the loop body a fixed number of times. Current iteration index (`{{ $index }}`) is available. | | `Array` | Run the loop body once for each element in an array. Current item (`{{ $item }}`) is available. | ### Execution Modes | Mode | Description | | - | - | | `Sequential` | Iterations execute one at a time, in order. Each iteration waits for the previous to complete. | | `Parallel` | Iterations execute concurrently up to `Max Concurrency`. Faster, but order of completion is not guaranteed. | ### Error Handling | Option | Description | | - | - | | `Fail Fast` | Halt the loop immediately on the first error and fail the orchestration run | | `Continue on Error` | Log the error and continue processing remaining iterations | *** ## Loop Variables Within the loop body, use these built-in expressions: | Variable | Description | | - | - | | `{{ $index }}` | Current iteration index (0-based) | | `{{ $item }}` | Current item value (in Array mode) | | `{{ $iteration }}` | Current iteration number (1-based) | | `{{ $total }}` | Total number of iterations | *** ## Example: Process an Array of Records Configuration: ``` Loop Mode: Array Input Array: {{ airtable.records }} Execution Mode: Sequential ``` Inside the loop body, `{{ $item.fields.Name }}` refers to the current record's `Name` field. *** ## Output Data After the loop completes, the node outputs an array containing the results from each iteration: ```json theme={null} [ { "result": "Processed record recAAA" }, { "result": "Processed record recBBB" }, { "result": "Processed record recCCC" } ] ``` *** ## Related Nodes * [Airtable](./airtable.md) — Retrieve a list of records to iterate over * [Conditions](./conditions.md) — Branch within a loop based on per-item values * [Wait](./wait.md) — Add a delay between iterations # Freshdesk Source: https://docs.subverseai.com/agentverse/nodes/freshdesk # Freshdesk The **Freshdesk** node lets you manage support tickets in Freshdesk from within an orchestration — create, retrieve, update, delete, and add notes to tickets. Freshdesk Node *** ## Credentials This node requires a **Freshdesk API** credential with your Freshdesk domain and API key. To create a credential: 1. Go to **Settings → Credentials → New Credential** 2. Select **Freshdesk API** 3. Enter your **API Key** and **Domain** See [Freshdesk API Credentials](/credentials/types/freshdesk-api) for detailed setup instructions. *** ## Operations ### Ticket | Operation | Description | | - | - | | `Create` | Create a new support ticket | | `Get` | Retrieve a single ticket by ID | | `Get Many` | List tickets with optional filters and pagination | | `Update` | Update an existing ticket | | `Delete` | Delete a ticket by ID | | `Add Note` | Add a public reply or private note to a ticket | *** ## Parameters: Create Ticket | Parameter | Type | Required | Description | | - | - | - | - | | **Credential** | Credential | Yes | Select or create a Freshdesk API credential | | **Requester Identification** | Select | Yes | How to identify the requester: `email`, `facebookId`, `phone`, `requesterId`, `twitterId`, or `uniqueExternalId` | | **Value** | String | Yes | Value for the selected requester identifier | | **Status** | Select | Yes | `open`, `pending`, `resolved`, or `closed` | | **Priority** | Select | Yes | `low`, `medium`, `high`, or `urgent` | | **Source** | Select | Yes | `chat`, `email`, `feedbackWidget`, `mobileHelp`, `OutboundEmail`, `phone`, or `portal` | | **Agent Name or ID** | Options | No | Agent to assign the ticket to | | **CC Emails** | String | No | Comma-separated email addresses to CC | | **Company Name or ID** | Options | No | Company ID of the requester | | **Description** | String | No | HTML content of the ticket | | **Due By** | DateTime | No | ISO timestamp when the ticket is due to be resolved | | **Email Config ID** | Number | No | Email config ID used for this ticket | | **FR Due By** | DateTime | No | ISO timestamp when the first response is due | | **Group Name or ID** | Options | No | Group to assign the ticket to | | **Name** | String | No | Name of the requester | | **Product Name or ID** | Options | No | Product associated with the ticket | | **Subject** | String | No | Subject of the ticket | | **Tags** | String | No | Comma-separated tags | | **Type** | Select | No | `Question`, `Incident`, `Problem`, `Feature Request`, or `Refund` | ## Parameters: Get Ticket | Parameter | Type | Required | Description | | - | - | - | - | | **Credential** | Credential | Yes | Select or create a Freshdesk API credential | | **Ticket ID** | String | Yes | ID of the ticket to retrieve | ## Parameters: Get Many Tickets | Parameter | Type | Required | Description | | - | - | - | - | | **Credential** | Credential | Yes | Select or create a Freshdesk API credential | | **Return All** | Boolean | No | Fetch all pages of results | | **Limit** | Number | No | Maximum number of tickets to return (default `5`, max `100`) | | **Company ID** | String | No | Filter by company ID | | **Include** | Multi-Select | No | Include related data: `company`, `description`, `requester`, or `stats` | | **Order** | Select | No | Sort order: `asc` or `desc` | | **Order By** | Select | No | Sort by `createdAt`, `dueBy`, or `updatedAt` | | **Requester Email** | String | No | Filter by requester email address | | **Requester ID** | String | No | Filter by requester ID | | **Updated Since** | DateTime | No | Filter tickets updated after this timestamp | ## Parameters: Update Ticket | Parameter | Type | Required | Description | | - | - | - | - | | **Credential** | Credential | Yes | Select or create a Freshdesk API credential | | **Ticket ID** | String | Yes | ID of the ticket to update | | **Update Fields** | Collection | No | Fields to update. Supports the same options as **Create Ticket** | ## Parameters: Delete Ticket | Parameter | Type | Required | Description | | - | - | - | - | | **Credential** | Credential | Yes | Select or create a Freshdesk API credential | | **Ticket ID** | String | Yes | ID of the ticket to delete | ## Parameters: Add Note | Parameter | Type | Required | Description | | - | - | - | - | | **Credential** | Credential | Yes | Select or create a Freshdesk API credential | | **Ticket ID** | String | Yes | ID of the ticket to add the note to | | **Body** | String | Yes | Content of the note or reply | | **Private** | Boolean | Yes | If `true`, the note is private (internal). If `false`, it is sent as a public reply | | **Notify Emails** | String | No | Comma-separated email addresses to notify | | **Incoming** | Boolean | No | Whether the note appears as being created from outside the web portal | *** ## Output Data A single ticket returned from `Get` or `Create`: ```json theme={null} { "id": 1, "subject": "Login issue", "description": "User cannot log in.", "status": 2, "priority": 1, "source": 2, "requester_id": 42, "responder_id": 5, "created_at": "2024-06-01T12:00:00Z", "updated_at": "2024-06-01T12:00:00Z" } ``` A note returned from `Add Note`: ```json theme={null} { "id": 1, "body": "We are looking into this issue and will update you shortly.", "private": false, "user_id": 5, "ticket_id": 1, "created_at": "2024-06-01T12:00:00Z", "updated_at": "2024-06-01T12:00:00Z" } ``` Reference fields in downstream nodes: ``` {{ freshdesk.id }} {{ freshdesk.subject }} {{ freshdesk.status }} {{ freshdesk.requester_id }} {{ freshdesk.responder_id }} ``` *** ## Related Nodes * [HTTP Request](./http-request.md) — Call custom Freshdesk API endpoints not covered by this node * [Send Email](./email.md) — Notify customers or agents about ticket updates # Google sheets Source: https://docs.subverseai.com/agentverse/nodes/google-sheets # Google Sheets The **Google Sheets** node lets you read and write data in Google Spreadsheets — read ranges, append rows, update cells, upsert rows, clear values, delete rows or columns, create and delete sheets, and create and delete entire spreadsheets. Google Sheets Node *** ## Credentials Three credential types are supported: | Type | Description | | - | - | | **Google Sheets Service Account** | Server-to-server authentication using a service account JSON key — works with private sheets after sharing them with the service account email | | **Google Sheets OAuth2 API** | Sign in with your own Google account — accesses any sheet your account can open, no manual sharing required | | **Google Sheets API Key** | Read-only access to publicly shared sheets — no write operations | To create a credential: 1. Go to **Settings → Credentials → New Credential** 2. Select the desired Google Sheets credential type 3. Complete the authentication flow The **API Key** credential only works for sheets shared as **Anyone with the link** and supports read operations only. For private sheets or any write operation, use **Service Account** or **OAuth2 API**. *** ## Operations ### Values | Operation | Description | | - | - | | `Read Rows` | Read values from a range — returns a 2D array of rows | | `Append Rows` | Add rows after the last row with data in a sheet | | `Update Rows` | Overwrite cells at a specific range | | `Append or Update Rows` | Upsert rows by a lookup column — update matching rows or append new ones | | `Clear Range` | Remove values from a range while preserving formatting | | `Delete Rows or Columns` | Remove rows or columns by index — remaining rows/columns shift to fill the gap | ### Spreadsheet | Operation | Description | | - | - | | `Create Sheet` | Add a new tab to an existing spreadsheet | | `Delete Sheet` | Remove a tab from a spreadsheet by its numeric sheet ID | | `Create Spreadsheet` | Create a brand new spreadsheet owned by the credential account | | `Delete Spreadsheet` | Move a spreadsheet to trash via the Google Drive API | *** ## Parameters: Read Rows | Parameter | Type | Required | Description | | - | - | - | - | | **Spreadsheet ID** | String | Yes | Spreadsheet ID from the URL: `/spreadsheets/d/{id}/` | | **Range** | String | Yes | A1 notation range — e.g. `Sheet1!A1:D10` or just `Sheet1` | | **Value Render Option** | Select | No | `FORMATTED_VALUE` (default), `FORMULA`, or `UNFORMATTED_VALUE` | ## Parameters: Append Rows | Parameter | Type | Required | Description | | - | - | - | - | | **Spreadsheet ID** | String | Yes | Spreadsheet ID | | **Range** | String | Yes | Sheet name or range — only the sheet name matters for append (e.g. `Sheet1`) | | **Rows** | Array | Yes | Array of rows to append. Each row is an array of cell values | | **Value Input Option** | Select | No | `RAW` (as-is) or `USER_ENTERED` (parsed). Default `USER_ENTERED` | ## Parameters: Update Rows | Parameter | Type | Required | Description | | - | - | - | - | | **Spreadsheet ID** | String | Yes | Spreadsheet ID | | **Range** | String | Yes | A1 notation range to overwrite — e.g. `Sheet1!A2:C2` | | **Rows** | Array | Yes | Array of rows. Dimensions must match the range | | **Value Input Option** | Select | No | `RAW` or `USER_ENTERED`. Default `USER_ENTERED` | ## Parameters: Append or Update Rows | Parameter | Type | Required | Description | | - | - | - | - | | **Spreadsheet ID** | String | Yes | Spreadsheet ID | | **Range** | String | Yes | A1 notation range to search and write within (e.g. `Sheet1!A1:D`) | | **Rows** | Array | Yes | Array of rows to upsert. Each row is an array of cell values | | **Lookup Column Index** | Number | Yes | 0-based column index used to match rows (0 = column A) | | **Value Input Option** | Select | No | `RAW` or `USER_ENTERED`. Default `USER_ENTERED` | ## Parameters: Clear Range | Parameter | Type | Required | Description | | - | - | - | - | | **Spreadsheet ID** | String | Yes | Spreadsheet ID | | **Range** | String | Yes | A1 notation range to clear — e.g. `Sheet1!A1:D10` | ## Parameters: Delete Rows or Columns | Parameter | Type | Required | Description | | - | - | - | - | | **Spreadsheet ID** | String | Yes | Spreadsheet ID | | **Dimension** | Select | Yes | `ROWS` or `COLUMNS` | | **Ranges** | Collection | Yes | Array of ranges to delete — at least one required | | **Ranges → Sheet ID** | Number | Yes | Numeric sheet (tab) ID | | **Ranges → Start Index** | Number | Yes | 0-based index of first row/column to delete (row 1 = index 0) | | **Ranges → End Index** | Number | Yes | 0-based index after the last row/column to delete (must be > start) | ## Parameters: Create Sheet | Parameter | Type | Required | Description | | - | - | - | - | | **Spreadsheet ID** | String | Yes | Spreadsheet to add the sheet to | | **Title** | String | Yes | Title for the new tab — must be non-empty and unique | | **Row Count** | Number | No | Number of rows. Default `1000` | | **Column Count** | Number | No | Number of columns. Default `26` | ## Parameters: Delete Sheet | Parameter | Type | Required | Description | | - | - | - | - | | **Spreadsheet ID** | String | Yes | Spreadsheet ID | | **Sheet ID** | Number | Yes | Numeric ID of the sheet (tab) to delete | ## Parameters: Create Spreadsheet | Parameter | Type | Required | Description | | - | - | - | - | | **Title** | String | Yes | Spreadsheet title — must be non-empty | | **Locale** | String | No | Spreadsheet locale (e.g. `en_US`). Default `en_US` | ## Parameters: Delete Spreadsheet | Parameter | Type | Required | Description | | - | - | - | - | | **Spreadsheet ID** | String | Yes | Spreadsheet ID to delete (moved to Google Drive trash) | *** ## Output Data A read result from `Read Rows`: ```json theme={null} { "range": "Sheet1!A1:D3", "majorDimension": "ROWS", "values": [ ["Name", "Email", "Phone", "Status"], ["John Doe", "john@example.com", "1234567890", "Active"], ["Jane Smith", "jane@example.com", "0987654321", "Inactive"] ] } ``` Reference cells in downstream nodes: ``` {{ googleSheets.values[0][0] }} {{ googleSheets.values[1][1] }} ``` An append or update result: ```json theme={null} { "spreadsheetId": "spreadsheet-id-123", "updates": { "updatedRange": "Sheet1!A4:C4", "updatedRows": 1, "updatedCells": 3 } } ``` An append-or-update result: ```json theme={null} { "spreadsheetId": "spreadsheet-id-123", "appendResult": { "updatedRange": "Sheet1!A4:C4", "updatedRows": 1, "updatedCells": 3 }, "updateResults": [ { "updatedRange": "Sheet1!A2:C2", "updatedRows": 1, "updatedCells": 3 } ] } ``` A create sheet result: ```json theme={null} { "spreadsheetId": "spreadsheet-id-123", "sheetId": 1234567890, "title": "February 2025" } ``` A create spreadsheet result: ```json theme={null} { "spreadsheetId": "1aB2cD3eF4gH5iJ6kL7mN8oP9qR0sT1uV2wX3yZ4", "spreadsheetUrl": "https://docs.google.com/spreadsheets/d/1aB2cD3eF4gH5iJ6kL7mN8oP9qR0sT1uV2wX3yZ4/edit" } ``` A clear, delete sheet, delete rows/columns, or delete spreadsheet result: ```json theme={null} { "spreadsheetId": "spreadsheet-id-123", "deleted": true } ``` *** ## A1 Notation Examples | Range | Description | | - | - | | `Sheet1` | Entire sheet named "Sheet1" | | `Sheet1!A1:D10` | Cells A1 through D10 on "Sheet1" | | `Sheet1!A:D` | All rows in columns A through D | | `Sheet1!A2:A` | All rows in column A starting from row 2 | *** ## Related Nodes * [For Loop](./for-loop.md) — Iterate over rows returned by Read Rows * [Conditions](./conditions.md) — Branch based on cell values * [HTTP Request](./http-request.md) — Send row data to an external API # HTTP Request Source: https://docs.subverseai.com/agentverse/nodes/http-request Make HTTP calls to any external API or web endpoint from an AgentVerse orchestration # HTTP Request The **HTTP Request** node makes HTTP calls to any external API or web endpoint. It supports all standard HTTP methods, custom headers, query parameters, multiple body formats, and a wide range of authentication types. HTTP Request Node *** ## Use Cases * Call a REST API that does not have a dedicated AgentVerse integration * Interact with internal services or microservices * Fetch data from a third-party API and pass it to downstream nodes * Trigger webhooks on external platforms *** ## Node Reference ### Parameters | Parameter | Type | Required | Description | | - | - | - | - | | **Method** | Select | Yes | HTTP method: `GET`, `POST`, `PUT`, `PATCH`, `DELETE`, `HEAD`, `OPTIONS` | | **URL** | String | Yes | The full URL of the endpoint | | **Send Headers** | Boolean | No | Enable to add custom request headers | | **Send Query Parameters** | Boolean | No | Enable to add query string parameters to the URL | | **Body Type** | Select | No | Format of the request body (for POST/PUT/PATCH) | | **Body** | String / JSON / Form | No | The request body payload | | **Options — Timeout** | Number | No | Request timeout in milliseconds (default: `30000`, max: `300000`) | | **Options — Follow Redirects** | Boolean | No | Whether to follow HTTP redirects (default: enabled) | | **Options — Ignore SSL Issues** | Boolean | No | Skip SSL certificate verification (use with caution) | | **Options — Response Format** | Select | No | How to parse the response: `autodetect`, `json`, `text`, or `base64` (default: `autodetect`) | | **Options — Full Response** | Boolean | No | Return status code, headers, and body instead of just the body (default: disabled) | | **Options — Ignore Response Code** | Boolean | No | Don't throw on 4xx/5xx — handle the error response yourself (default: disabled) | ### Body Types | Type | Description | | - | - | | `JSON` | Send body as `application/json` | | `Form Data (URL Encoded)` | Send body as `application/x-www-form-urlencoded` | | `Form Data (Multipart)` | Send body as `multipart/form-data` (for file uploads) | | `Raw / Binary` | Send raw string or binary body | *** ## Response Format Use **Response Format** to control how the node parses the API response: | Format | When to use | | - | - | | `Autodetect` | Let the node choose based on the `Content-Type` header | | `JSON` | Force parsing as JSON | | `Text` | Return the response as a plain string | | `Base64` | Return binary data (images, PDFs, audio) as a Base64 string | **Tip:** Choose `Base64` when you need to pass binary files to downstream nodes such as **Send Email** attachments or file upload actions. ## Output Data By default, the node returns the parsed response body: ```json theme={null} { "users": [ { "id": 1, "name": "Alice" }, { "id": 2, "name": "Bob" } ] } ``` When **Full Response** is enabled: ```json theme={null} { "statusCode": 200, "statusMessage": "OK", "headers": { "content-type": "application/json" }, "body": { ... } } ``` When **Response Format** is set to `Base64`: ```json theme={null} { "data": "iVBORw0KGgoAAAANSUhEUgAAAA..." } ``` Reference fields in downstream nodes: ``` {{ httpRequest.users[0].name }} {{ httpRequest.statusCode }} ``` *** ## Pagination For APIs that return paginated results, enable **Pagination** under Options: | Setting | Description | | - | - | | **Pagination Type** | `Page Number`, `Offset`, or `Cursor-Based` | | **Max Items** | Stop paginating after this many total items | *** ## Related Nodes * [Respond to Webhook](./respond-to-webhook) — Return an HTTP response from an orchestration * [Conditions](./conditions) — Branch based on HTTP response status or body * [Send Email](./email) — Attach binary data fetched via HTTP Request Combine **HTTP Request** (Base64 response format) with **Send Email** to fetch a document from an API and email it as an attachment. # Human in the loop Source: https://docs.subverseai.com/agentverse/nodes/human-in-the-loop # Human in the Loop The **Human in the Loop** node pauses an orchestration run and sends an approval request to a human via Slack or email. Execution resumes only after the reviewer approves or rejects the request — or after a configured timeout. Human In The Loop Node *** ## Use Cases * Require manager approval before processing a large transaction * Route AI-generated content for human review before publishing * Create an approval step in a multi-stage data pipeline * Escalate flagged support tickets to a human agent *** ## Node Reference ### Parameters | Parameter | Type | Required | Description | | - | - | - | - | | **Approval Channel** | Select | Yes | How to send the approval request: `Slack` or `Email` | ### Email Channel Parameters | Parameter | Type | Required | Description | | - | - | - | - | | **Email Addresses** | String | Yes | One or more approver email addresses, separated by commas | | **Subject** | String | No | Email subject line (default: `Workflow Approval Required`) | | **Message** | String | No | Body message for the approval email (default: `Please review and approve this workflow action.`) | ### Slack Channel Parameters | Parameter | Type | Required | Description | | - | - | - | - | | **Slack Credential** | Credential | Yes | Select or create a Slack OAuth2 credential | | **Send To** | Select | Yes | `Channel` or `User` | | **Slack Channel** | String | Conditional | Channel name or ID (required when `Send To` is `Channel`) | | **Slack User** | String | Conditional | User ID or email (required when `Send To` is `User`) | | **Message** | String | No | Custom message to include in the approval request | ### Timeout Settings | Parameter | Type | Required | Description | | - | - | - | - | | **Value** | Number | Yes | How long to wait for a response before timing out (default: `24`) | | **Unit** | Select | Yes | Unit for the timeout: `Minutes`, `Hours`, `Days` (default: `Hours`) | | **On Timeout** | Select | Yes | What to do if no response is received: `Approve` or `Reject` | *** ## How It Works 1. The node sends an approval request to the configured channel (Slack or email). 2. The request includes **Approve** and **Reject** action buttons. 3. The orchestration run is paused and waits for a response. 4. When the approver clicks **Approve** or **Reject**, execution resumes on the corresponding branch. 5. If no response arrives within the timeout window, the **Default Action** is applied. *** ## Output Branches The node has two output branches: | Branch | Condition | | - | - | | **Approved** | The approver clicked Approve, or timed out with Default Action = Approve | | **Rejected** | The approver clicked Reject, or timed out with Default Action = Reject | Connect different downstream nodes to each branch to handle both outcomes. *** ## Output Data The output includes the original upstream data plus the reviewer's decision: ```json theme={null} { "decision": "approved", "reviewer": "alice@example.com", "reviewedAt": "2025-03-10T09:15:00.000Z", "comment": "Looks good, proceed." } ``` Reference in downstream nodes: ``` {{ humanInTheLoop.decision }} {{ humanInTheLoop.reviewer }} {{ humanInTheLoop.comment }} ``` *** ## Related Nodes * [Wait](./wait.md) — A lower-level pause node for custom webhook-based resume flows * [Conditions](./conditions.md) — Branch based on the approval outcome * [Slack](./slack.md) — Send a follow-up Slack message after the decision # Manual trigger Source: https://docs.subverseai.com/agentverse/nodes/manual-trigger # Manual Trigger (Starter) The **Starter** node is AgentVerse's combined manual and scheduled trigger. In **Manual Trigger** mode it starts an orchestration immediately when you click **Trigger Now** from the canvas — used for testing, on-demand tasks, and orchestrations that do not need to respond to an event. > The same Starter node also supports **Schedule At** mode. See [Schedule Trigger](./schedule-trigger.md). Starter Node — Manual Trigger mode *** ## Use Cases * Test an orchestration during development * Run one-off data processing tasks on demand * Trigger workflows that take user-uploaded files as input *** ## Node Reference ### Parameters | Parameter | Type | Description | | - | - | - | | **Trigger Mode** | Select | Set to `Manual Trigger` to enable on-demand execution | | **Upload Data Files** | Files | Optional XLSX, CSV, or JSON files to inject as input data | There are no required parameters. Click **Trigger Now** on the node canvas to execute immediately, or use **Test (N Records)** to run with a preview of your uploaded data. *** ## How It Works When you click **Trigger Now** on the Starter node: 1. AgentVerse creates a new Orchestration Run immediately. 2. Any uploaded files (XLSX, CSV, JSON) are parsed and injected as the trigger output. 3. Execution proceeds through all downstream nodes. 4. The run result appears in the **Orchestration Runs** panel in real time. *** ## Output Data When no files are uploaded, the output is a minimal execution context: ```json theme={null} { "executionMode": "manual", "triggeredAt": "2025-03-10T09:00:00.000Z" } ``` When files are uploaded, each file is available as a binary item: ```json theme={null} { "binary": { "file": { "data": "", "mimeType": "application/pdf", "fileName": "report.pdf" } } } ``` *** ## Testing vs. Production | Mode | Description | | - | - | | **Test Mode** | Run the orchestration from the canvas editor. Uses test data and does not count toward production run limits. | | **Production Run** | Triggered by activating the orchestration and clicking Run from the runs list. Uses live credentials and counts as a production execution. | *** ## Related Nodes * [Schedule Trigger](./schedule-trigger.md) — Run automatically on a time-based schedule * [Webhook Trigger](./webhook.md) — Trigger from an external HTTP event # Respond to webhook Source: https://docs.subverseai.com/agentverse/nodes/respond-to-webhook # Respond to Webhook The **Respond to Webhook** node sends a custom HTTP response back to the caller of a [Webhook Trigger](./webhook.md). It is used when you need full control over the HTTP response — custom status codes, headers, or body content. Respond to Webhook Node *** ## Use Cases * Return a custom JSON response to an API caller after processing * Respond with a specific HTTP status code (e.g. `201 Created`, `400 Bad Request`) * Set custom response headers (e.g. `Content-Type`, `X-Request-ID`) * Build synchronous webhook endpoints that return processed data *** ## Prerequisites The orchestration's Webhook Trigger must have **Response Mode** set to `Using Respond to Webhook Node`. If the response mode is set to `Immediately` or `When Last Node Finishes`, this node has no effect. *** ## Node Reference ### Parameters | Parameter | Type | Required | Description | | - | - | - | - | | **Respond With** | Select | Yes | The format of the response body (see below) | | **Response Body** | String / JSON | Conditional | The body to return (required for `JSON`, `Text`, `Binary`) | | **Response Code** | Number | No | HTTP status code (default: `200`) | | **Response Headers** | Key-Value | No | Additional headers to include in the response | ### Respond With Options | Option | Description | | - | - | | `All Incoming Items` | Return the full output of all upstream nodes as JSON | | `First Incoming Item` | Return only the first item from the upstream output | | `JSON` | Return a custom JSON body | | `Text` | Return a plain text body | | `Binary` | Return a binary file (e.g. an image or PDF) | | `No Data` | Return an empty response with just a status code | *** ## Example: Return a Custom JSON Response Configuration: | Field | Value | | - | - | | **Respond With** | `JSON` | | **Response Code** | `200` | | **Response Body** | `{ "status": "success", "orderId": "{{ airtable.id }}" }` | Resulting HTTP response: ```http theme={null} HTTP/1.1 200 OK Content-Type: application/json { "status": "success", "orderId": "recXXXXXXXXXXXXXX" } ``` *** ## Example: Return a 400 Error | Field | Value | | - | - | | **Respond With** | `JSON` | | **Response Code** | `400` | | **Response Body** | `{ "error": "Invalid request", "message": "{{ conditions.reason }}" }` | *** ## Related Nodes * [Webhook Trigger](./webhook.md) — The trigger node this node responds to * [Conditions](./conditions.md) — Branch before responding based on orchestration logic # Schedule trigger Source: https://docs.subverseai.com/agentverse/nodes/schedule-trigger # Schedule Trigger (Starter) The **Starter** node is AgentVerse's combined manual and scheduled trigger. In **Schedule At** mode it starts an orchestration automatically at a specified date and time or on a recurring schedule. > The same Starter node also supports **Manual Trigger** mode. See [Manual Trigger](./manual-trigger.md). Starter Node — Schedule At mode *** ## Use Cases * Run daily reports or summaries * Sync data between services on a recurring basis * Send scheduled notifications or reminders * Trigger time-based AI agent tasks *** ## Node Reference ### Parameters | Parameter | Type | Description | | - | - | - | | **Trigger Mode** | Select | Set to `Schedule At` to enable time-based execution | | **Scheduled Date/Time** | DateTime | The date and time for the first (or only) run | | **Repeat Enabled** | Boolean | If enabled, the orchestration repeats on the defined interval | | **Repeat Interval** | Select | How often to repeat: `Hourly`, `Daily`, `Weekly`, `Monthly`, `Custom (Cron)` | | **Cron Expression** | String | Custom cron schedule (only shown when `Custom` is selected) | | **Timezone** | Select | The timezone used to evaluate the schedule | | **Upload Data Files** | Files | Optional XLSX, CSV, or JSON files to inject as input data on each run | ### Repeat Interval Options | Value | Description | | - | - | | `Hourly` | Run every hour | | `Daily` | Run every day at the specified time | | `Weekly` | Run on the specified day(s) of the week | | `Monthly` | Run on the specified day of the month | | `Custom (Cron)` | Run on a custom cron expression | ### Cron Expression Format ``` ┌───────────── minute (0–59) │ ┌───────────── hour (0–23) │ │ ┌───────────── day of month (1–31) │ │ │ ┌───────────── month (1–12) │ │ │ │ ┌───────────── day of week (0–6, 0=Sunday) │ │ │ │ │ * * * * * ``` Examples: | Expression | Meaning | | - | - | | `0 9 * * 1-5` | Every weekday at 9:00 AM | | `0 0 1 * *` | First day of every month at midnight | | `*/15 * * * *` | Every 15 minutes | | `0 8 * * 1` | Every Monday at 8:00 AM | *** ## Output Data The Schedule Trigger outputs the scheduled execution time: ```json theme={null} { "scheduledTime": "2025-03-10T09:00:00.000Z", "timezone": "America/New_York" } ``` *** ## Timezone Behavior All schedule times are evaluated in the configured timezone. If no timezone is set, UTC is used by default. Daylight saving time transitions are handled automatically. *** ## Related Nodes * [Manual Trigger](./manual-trigger.md) — Start an orchestration manually instead * [Wait](./wait.md) — Pause mid-orchestration until a specific time # Shopify Source: https://docs.subverseai.com/agentverse/nodes/shopify # Shopify The **Shopify** node lets you manage your Shopify store from within an orchestration — read and update orders, products, customers, and inventory. Shopify Node *** ## Credentials This node requires a **Shopify** credential with API access configured in your Shopify admin. To create a credential: 1. Go to **Settings → Credentials → New Credential** 2. Select **Shopify** 3. Enter your Shopify store URL and API access token *** ## Operations ### Order | Operation | Description | | - | - | | `Get` | Retrieve a single order by ID | | `Get Many` | List orders with optional filters | | `Create` | Create a new draft order | | `Update` | Update order fields or status | | `Delete` | Delete an order | | `Fulfill` | Fulfill an order or fulfillment | | `Cancel` | Cancel an order | ### Product | Operation | Description | | - | - | | `Get` | Retrieve a single product by ID | | `Get Many` | List products with optional filters | | `Create` | Create a new product | | `Update` | Update product details, variants, or images | | `Delete` | Delete a product | ### Customer | Operation | Description | | - | - | | `Get` | Retrieve a customer by ID or email | | `Get Many` | List customers | | `Create` | Create a new customer | | `Update` | Update customer details | | `Delete` | Delete a customer | ### Inventory | Operation | Description | | - | - | | `Adjust Level` | Increase or decrease inventory at a location | | `Set Level` | Set inventory to a specific quantity | | `Get Level` | Get current inventory level | *** ## Parameters: Get Many Orders | Parameter | Type | Required | Description | | - | - | - | - | | **Credential** | Credential | Yes | Select or create a Shopify credential | | **Status** | Select | No | Filter by order status: `open`, `closed`, `cancelled`, `any` | | **Financial Status** | Select | No | Filter by payment status: `paid`, `pending`, `refunded`, etc. | | **Fulfillment Status** | Select | No | Filter by fulfillment status | | **Created At Min** | DateTime | No | Return orders created after this time | | **Created At Max** | DateTime | No | Return orders created before this time | | **Limit** | Number | No | Maximum number of orders to return | *** ## Output Data A single order from `Get Order`: ```json theme={null} { "id": 5678901234, "name": "#1001", "email": "customer@example.com", "total_price": "99.00", "currency": "USD", "financial_status": "paid", "fulfillment_status": null, "line_items": [ { "id": 1234567890, "title": "Blue T-Shirt", "quantity": 2, "price": "49.50" } ], "created_at": "2025-03-10T09:00:00-05:00" } ``` Reference fields: ``` {{ shopify.name }} {{ shopify.email }} {{ shopify.financial_status }} {{ shopify.line_items[0].title }} ``` *** ## Related Nodes * [Shopify Trigger](./shopify-trigger.md) — Trigger on Shopify store events * [Slack](./slack.md) — Notify a team channel when an order is created or updated * [HTTP Request](./http-request.md) — Call custom Shopify API endpoints not covered by this node # Shopify trigger Source: https://docs.subverseai.com/agentverse/nodes/shopify-trigger # Shopify Trigger The **Shopify Trigger** starts an orchestration when a specified event occurs in your Shopify store — such as an order being created, a cart updated, or a product changed. Shopify Trigger Node *** ## Use Cases * Trigger an order fulfillment workflow when a new order is placed * Notify a Slack channel when a customer abandons their cart * Sync product changes to an external system when a product is updated * Run post-purchase AI workflows when checkout completes *** ## Credentials This node requires a **Shopify** credential. To create a credential: 1. Go to **Settings → Credentials → New Credential** 2. Select **Shopify** 3. Enter your Shopify store URL and API access token *** ## Node Reference ### Parameters | Parameter | Type | Description | | - | - | - | | **Credential** | Credential | Select or create a Shopify credential | | **Trigger On** | Select | The Shopify event that starts the orchestration (see below) | ### Webhook URL The Shopify Trigger displays a unique **Webhook URL** in the node panel. Register this URL in your Shopify app's **Webhooks** settings (Admin → Settings → Notifications → Webhooks). ### Event Types | Event | Description | | - | - | | `App Uninstalled` | The Shopify app is uninstalled from the store | | `Cart Created` | A new shopping cart is created | | `Cart Updated` | Items in a cart are added, removed, or changed | | `Checkout Created` | A checkout session is initiated | | `Checkout Delete` | A checkout session is deleted | | `Checkout Update` | A checkout session is updated | | `Collection Created` | A new product collection is created | | `Collection Deleted` | A product collection is deleted | | `Collection Updated` | A product collection is updated | | `Customer Created` | A new customer account is created | | `Customer Deleted` | A customer account is deleted | | `Customer Updated` | A customer account is updated | | `Draft Order Created` | A new draft order is created | | `Draft Order Deleted` | A draft order is deleted | | `Draft Order Updated` | A draft order is updated | | `Fulfillment Created` | An order fulfillment is created | | `Fulfillment Updated` | An order fulfillment status changes | | `Order Cancelled` | An order is cancelled | | `Order Created` | A new order is placed | | `Order Fulfilled` | An order is fully fulfilled | | `Order Paid` | An order payment is confirmed | | `Order Updated` | An order is updated | | `Product Created` | A new product is created | | `Product Deleted` | A product is deleted | | `Product Updated` | A product is updated | | `Refund Created` | A refund is issued on an order | *** ## Output Data The trigger outputs the full Shopify webhook payload for the event. For an `Order Created` event: ```json theme={null} { "id": 5678901234, "name": "#1001", "email": "customer@example.com", "total_price": "99.00", "currency": "USD", "financial_status": "paid", "line_items": [ { "title": "Blue T-Shirt", "quantity": 2, "price": "49.50" } ], "created_at": "2025-03-10T09:00:00-05:00" } ``` Reference fields in downstream nodes: ``` {{ shopifyTrigger.name }} {{ shopifyTrigger.email }} {{ shopifyTrigger.total_price }} {{ shopifyTrigger.line_items[0].title }} ``` *** ## Related Nodes * [Shopify](./shopify.md) — Read and update Shopify data within an orchestration * [Slack](./slack.md) — Send a notification when an order event occurs * [AI Agent](./ai-agent.md) — Process order data with an LLM # Slack Source: https://docs.subverseai.com/agentverse/nodes/slack # Slack The **Slack** node lets you interact with Slack from within an orchestration — send messages, manage channels, look up users, upload files, and more. Slack Node *** ## Credentials This node requires a **Slack OAuth2** credential. To create a credential: 1. Go to **Settings → Credentials → New Credential** 2. Select **Slack OAuth2** 3. Authenticate with your Slack workspace *** ## Operations ### Message | Operation | Description | | - | - | | `Send` | Post a message to a channel or user | | `Update` | Edit an existing message | | `Delete` | Delete a message | | `Get Permalink` | Get a permanent link to a message | | `Search` | Search messages in a workspace | | `Reply` | Reply to a message in a thread | ### Channel | Operation | Description | | - | - | | `Archive` | Archive a channel | | `Close` | Close a direct message channel | | `Create` | Create a new public or private channel | | `Get` | Retrieve details of a channel | | `Get Many` | List multiple channels | | `History` | Retrieve messages from a channel's history | | `Invite` | Invite a user to a channel | | `Join` | Join a channel | | `Kick` | Remove a user from a channel | | `Leave` | Leave a channel | | `Member` | List members of a channel | | `Open` | Open a direct message channel | | `Rename` | Rename a channel | | `Set Purpose` | Set the purpose (description) of a channel | | `Set Topic` | Set the topic of a channel | | `Unarchive` | Unarchive a channel | ### User | Operation | Description | | - | - | | `Get` | Get a user's profile by ID or email | | `Get Many` | List users in a workspace | | `Get Status` | Get a user's current status | | `Update Profile` | Update a user's profile fields | ### File | Operation | Description | | - | - | | `Get` | Get file metadata | | `Get Many` | List files in a workspace | | `Upload` | Upload a file to a channel | | `Delete` | Delete a file | ### Reaction | Operation | Description | | - | - | | `Add` | Add a reaction emoji to a message | | `Get` | Get reactions on a message | | `Remove` | Remove a reaction from a message | *** ## Parameters: Send a Message | Parameter | Type | Required | Description | | - | - | - | - | | **Send Message To** | Select | Yes | The destination: a channel or a user | | **Message Type** | Select | Yes | `Simple Text Message` — plain text with markdown support; or `Blocks` — use Slack's Block Kit UI builder for rich messages with form fields, sections, and more | | **Message Text** | String | Yes | The message text to post. Supports [Slack markdown](https://api.slack.com/reference/surfaces/formatting). | | **Options** | Collection | No | Additional options (thread reply, username override, icon emoji, etc.) | *** ## Output Data A successful `Send Message` operation returns: ```json theme={null} { "ok": true, "channel": "C012AB3CD", "ts": "1678901234.000100", "message": { "text": "Hello from AgentVerse!", "type": "message", "user": "U012AB3CD" } } ``` Reference fields in downstream nodes: ``` {{ slack.ts }} {{ slack.channel }} ``` *** ## Related Nodes * [Slack Trigger](./slack-trigger.md) — Trigger an orchestration from a Slack event * [AI Agent](./ai-agent.md) — Generate message content with an LLM before sending # Slack trigger Source: https://docs.subverseai.com/agentverse/nodes/slack-trigger # Slack Trigger The **Slack Trigger** starts an orchestration when a Slack event occurs — such as a new message in a channel, a direct message to a bot, a reaction added, or a file shared. Slack Trigger Node *** ## Use Cases * Respond to bot commands or mentions in Slack channels * Trigger AI processing when a user sends a message to a channel * Automate workflows based on Slack reactions or file uploads * Build Slack bots powered by AgentVerse orchestrations *** ## Credentials This node requires a **Slack OAuth2** credential. To create a credential: 1. Go to **Settings → Credentials → New Credential** 2. Select **Slack OAuth2** 3. Authenticate with your Slack workspace *** ## Node Reference ### Parameters | Parameter | Type | Description | | - | - | - | | **Credential** | Credential | Select or create a Slack OAuth2 credential | | **Trigger On** | Multi-select | The Slack event types to listen for (default: `Any Event`) | ### Trigger On Options | Option | Description | | - | - | | `Any Event` | Fires on all Slack events delivered to the webhook | | `Message` | A message is posted in a channel or DM | | `Bot Mention` | The bot is @mentioned in a channel | | `Reaction Added` | A user adds a reaction emoji to a message | | `File Shared` | A file is uploaded and shared in a channel | | `Channel Created` | A new channel is created in the workspace | | `Member Joined Channel` | A user joins a channel | ### Options | Option | Description | | - | - | | **Resolve IDs** | When enabled, resolves Slack user/channel IDs to their human-readable names and returns them alongside the IDs | | **Usernames or IDs to Ignore** | Events from these users will not trigger the orchestration | ### Webhook URL The Slack Trigger displays a unique **Webhook URL** in the node panel. Configure this URL in your Slack app's **Event Subscriptions** settings to route Slack events to AgentVerse. *** ## Output Data The trigger outputs the full Slack event payload: ```json theme={null} { "type": "message", "text": "Hey @bot, summarize this document", "user": "U012AB3CD", "channel": "C012AB3CD", "ts": "1678901234.000100", "team": "T012AB3CD" } ``` Reference fields in downstream nodes: ``` {{ slackTrigger.text }} {{ slackTrigger.user }} {{ slackTrigger.channel }} ``` *** ## Related Nodes * [Slack](./slack.md) — Send messages and interact with Slack within an orchestration * [AI Agent](./ai-agent.md) — Process the Slack message with an LLM # Subverse agents Source: https://docs.subverseai.com/agentverse/nodes/subverse-agents # SubVerse Agents The **SubVerse Agents** node executes a SubVerse AI agent on a specific communication channel — voice, WhatsApp, email, or chat. It initiates an agent conversation and can optionally wait for the conversation to complete before passing results downstream. SubVerse Agents Node *** ## Use Cases * Initiate an outbound voice call handled by a SubVerse AI agent * Send a WhatsApp message and have an AI agent conduct the conversation * Launch an AI agent over email to gather information from a contact * Embed an AI chat session in an orchestration and use the outcome downstream *** ## Node Reference ### Parameters | Parameter | Type | Required | Description | | - | - | - | - | | **Agent Channel** | Select | Yes | The communication channel: `Voice`, `WhatsApp`, `Email`, or `Chat` | | **Agent** | Select | Yes | The SubVerse AI agent to execute (select from list) | | **Agent Version** | String | No | The agent version to use: `default`, `draft`, or a specific version (e.g. `v1`) | | **Wait for Completion** | Boolean | No | If enabled, the orchestration pauses until the agent conversation finishes | | **Customer Metadata** | Key-Value | No | Custom key-value pairs passed to the agent. Reference them in agent prompts using `{{key}}` syntax. | *** ## Channel-Specific Parameters ### Voice | Parameter | Type | Required | Description | | - | - | - | - | | **Customer Phone Number** | String | Yes | The phone number to call (E.164 format, e.g. `+912298765432`) | | **Bot Phone Number** | Select | No | The SubVerse AI outbound caller number — leave empty to use the default | ### WhatsApp | Parameter | Type | Required | Description | | - | - | - | - | | **Customer Phone Number** | String | Yes | The WhatsApp number to message (E.164 format) | | **Bot Phone Number** | Select | No | The SubVerse AI WhatsApp sender number — leave empty to use the default | #### WhatsApp Options | Parameter | Type | Required | Description | | - | - | - | - | | **Message Type** | Select | No | `Prompt (AI-driven)` \| `Say (Fixed message)` \| `Template`. Default `Prompt` | | **Message** | String | No | Fixed message text — required when **Message Type** is `Say` | | **Template ID** | String | No | WhatsApp template name — required when **Message Type** is `Template` | | **Template Language** | String | No | BCP-47 language code for the template (e.g. `en`, `en_US`, `hi`). Default `en` | | **Template Variables** | Key-Value | No | Key/value pairs substituted into the WhatsApp template body placeholders. Only visible when **Message Type** is `Template` | | **Additional Context** | String | No | Extra instructions injected into the LLM prompt — only used when **Message Type** is `Prompt` | | **Attachment URLs** | String | No | Comma-separated list of publicly accessible URLs to attach | **Template Variables** fill the placeholders in a WhatsApp template body (e.g. `{{1}}`, `{{customer_name}}`). They are independent from **Customer Metadata** — metadata is passed into the agent session for prompt substitution, while template variables are sent directly to the WhatsApp template. Only template variables are used for template substitution; metadata is never sent as template variables. ### Email | Parameter | Type | Required | Description | | - | - | - | - | | **Customer Email** | String | Yes | The recipient email address | ### Chat | Parameter | Type | Required | Description | | - | - | - | - | | **Session ID** | String | No | Optional session identifier for continuing an existing chat | | **Initial Message** | String | No | The first message to send to the agent | *** ## Customer Metadata Provide custom key-value pairs that the agent can reference during the conversation using `{{key}}` in prompts: | Example Key | Example Value | Description | | - | - | - | | `customerName` | `John Doe` | Customer's full name | | `orderId` | `ORD-12345` | Relevant order reference | | `language` | `en` | Preferred language for the conversation | *** ## Wait for Completion When **Wait for Completion** is enabled: * The orchestration run pauses while the SubVerse AI agent handles the conversation. * Once the agent marks the conversation as complete, execution resumes. * The full conversation outcome (transcript, status, extracted data) is available downstream. When disabled: * The node starts the agent conversation and immediately moves to the next node. * The conversation happens asynchronously — the [SubVerse AI Trigger](./subverse-ai-trigger.md) can be used to react to the completion in a separate orchestration when it finishes. *** ## Output Data When the agent conversation completes: ```json theme={null} { "conversationId": "conv_XXXXXXXXX", "channel": "voice", "status": "completed", "outcome": "resolved", "agentName": "Support Agent", "customerNumber": "+919876543210", "duration": 120, "transcript": [ { "role": "agent", "text": "Hello! How can I assist you today?" }, { "role": "user", "text": "I need to reschedule my appointment." }, { "role": "agent", "text": "Sure, let me help with that." } ], "extractedData": { "intent": "reschedule_appointment", "preferredDate": "2025-03-15" }, "startedAt": "2025-03-10T09:00:00.000Z", "endedAt": "2025-03-10T09:02:00.000Z" } ``` Reference in downstream nodes: ``` {{ subverseAgents.outcome }} {{ subverseAgents.extractedData.intent }} {{ subverseAgents.transcript }} {{ subverseAgents.conversationId }} ``` *** ## Related Nodes * [SubVerse AI Trigger](./subverse-ai-trigger.md) — React to a completed SubVerse AI call in a separate orchestration * [Conditions](./conditions.md) — Branch based on the agent's outcome or extracted intent # Subverse ai trigger Source: https://docs.subverseai.com/agentverse/nodes/subverse-ai-trigger # SubVerse AI Trigger The **SubVerse AI Trigger** starts an orchestration when a SubVerse AI voice call completes. It enables post-call workflows triggered by AI-handled inbound calls. SubVerse AI Trigger Node *** ## Use Cases * Trigger a follow-up workflow after an AI voice agent completes a customer call * Log call outcomes to Airtable or a CRM after call completion * Send a post-call summary or follow-up message via Slack or WhatsApp * Escalate unresolved calls to a human agent *** ## Credentials This node uses your SubVerse AI workspace credentials, which are configured at the workspace level. No additional credential setup is required. *** ## Node Reference ### Parameters | Parameter | Type | Description | | - | - | - | | **Event** | Select | The call event that triggers the orchestration | ### Event Options | Event | Description | | - | - | | `Incoming Call Completed` | Fires when a SubVerse AI agent finishes handling an inbound call | *** ## Output Data The trigger outputs the call completion payload, including transcript, outcome, and caller details: ```json theme={null} { "callId": "call_XXXXXXXXX", "botNumber": "+19876543210", "callerNumber": "+11234567890", "status": "completed", "duration": 145, "transcript": [ { "role": "agent", "text": "Hello, how can I help you today?" }, { "role": "user", "text": "I'd like to check my account balance." } ], "outcome": "resolved", "startedAt": "2025-03-10T09:00:00.000Z", "endedAt": "2025-03-10T09:02:25.000Z" } ``` Reference fields in downstream nodes: ``` {{ subverseAITrigger.callerNumber }} {{ subverseAITrigger.outcome }} {{ subverseAITrigger.transcript }} {{ subverseAITrigger.duration }} ``` *** ## Related Nodes * [SubVerse Agents](./subverse-agents.md) — Execute SubVerse AI agents for outbound calls or other channels * [SubVerse AI](./subverse-ai.md) — Manage SubVerse AI voice interactions within an orchestration * [Slack](./slack.md) — Send post-call notifications to a Slack channel # Wait Source: https://docs.subverseai.com/agentverse/nodes/wait # Wait The **Wait** node pauses an orchestration run for a specified duration or until a specific date and time. Wait Node *** ## Use Cases * Add a delay between consecutive API calls to avoid rate limiting * Wait for a scheduled time before sending a reminder * Implement time-window logic (e.g. "wait until next business day") *** ## Node Reference ### Parameters | Parameter | Type | Required | Description | | - | - | - | - | | **Wait Mode** | Toggle | Yes | `for Duration` — pause for a fixed amount of time; `Until Time` — pause until a specific date/time | | **Amount** | Number | Conditional | Duration to wait (required for `for Duration`) | | **Unit** | Select | Conditional | Unit of the duration: `Seconds`, `Minutes`, `Hours`, `Days` (required for `for Duration`) | | **Date/Time** | DateTime | Conditional | Resume at this specific timestamp (required for `Until Time`) | *** ## Wait Modes ### for Duration Pauses for a fixed duration after the node is reached. | Field | Example | | - | - | | **Amount** | `5` | | **Unit** | `Seconds` | The orchestration resumes automatically after the specified time. ### Until Time Pauses until an absolute date and time is reached, regardless of when the node was entered. | Field | Example | | - | - | | **Date/Time** | `2025-03-15T09:00:00Z` | *** ## Output Data The upstream node output passes through the Wait node unchanged. No data transformation occurs. *** ## Related Nodes * [Human in the Loop](./human-in-the-loop.md) — A higher-level wait node that includes approval channel logic * [Schedule Trigger](./schedule-trigger.md) — Start an orchestration at a specific time instead of waiting mid-run * [For Loop](./for-loop.md) — Use Wait inside a loop to throttle iteration rate # Webhook Source: https://docs.subverseai.com/agentverse/nodes/webhook # Webhook Trigger The **Webhook** trigger starts an orchestration when an HTTP request is received at a unique URL generated for that orchestration. Webhook Trigger Node *** ## Use Cases * Receive data from third-party services (GitHub, Stripe, Typeform, etc.) * Build custom HTTP endpoints without infrastructure setup * Handle form submissions or API integrations *** ## Node Reference ### Parameters | Parameter | Type | Description | | - | - | - | | **Allow Multiple HTTP Methods** | Boolean | When enabled, the webhook accepts requests from more than one HTTP method | | **Respond** | Select | When and how to respond to the caller (see below) | ### Respond Options | Option | Description | | - | - | | `Immediately` | Responds as soon as the request is received, before the orchestration finishes | | `When Last Node Finishes` | Waits for the full orchestration to complete, then responds with the last node's output | | `Using Respond to Webhook Node` | Defers the response to an explicit [Respond to Webhook](./respond-to-webhook.md) node placed later in the orchestration | ### Options | Option | Description | | - | - | | **Response Code** | The HTTP status code to return (default: `200`) | | **Response Headers** | Custom headers to include in the response | | **IP(s) Whitelist** | Comma-separated list of allowed IP addresses or CIDR ranges. Leave empty to allow all. | *** ## Webhook URL Each orchestration gets a unique webhook URL shown inside the node. Copy it using the **Copy URL** link. > The production URL is only active when the orchestration is **Activated**. A separate test URL is available while editing. *** ## Output Data The Webhook trigger outputs an object with the full HTTP request details: ```json theme={null} { "headers": { "content-type": "application/json", "authorization": "Bearer ..." }, "params": {}, "query": { "source": "stripe" }, "body": { "event": "payment.completed", "amount": 4999 }, "webhookUrl": "https://...", "executionMode": "production" } ``` Reference fields in downstream nodes: ``` {{ webhook.body.event }} {{ webhook.query.source }} {{ webhook.headers.authorization }} ``` *** ## Related Nodes * [Respond to Webhook](./respond-to-webhook.md) — Send a custom HTTP response back to the caller * [Schedule Trigger](./schedule-trigger.md) — Trigger on a time-based schedule instead # WhatsApp Business Cloud Source: https://docs.subverseai.com/agentverse/nodes/whatsapp Send messages and manage media through the WhatsApp Business Cloud API # WhatsApp Business Cloud The **WhatsApp Business Cloud** node lets you send text, contacts, locations, templates, and media through the Meta WhatsApp Business Cloud API. WhatsApp Business Cloud Node *** ## Credentials This node requires a **[WhatsApp API](/credentials/types/whatsapp-api)** credential. To create a credential: 1. Go to **Settings → Credentials → New Credential** 2. Select **WhatsApp API** 3. Enter your Meta **Access Token** and **Business Account ID** *** ## Resources and Operations ### Message | Operation | Description | | - | - | | `Send` | Send a text, contact, location, audio, document, image, or video message | | `Send and Wait for Response` | Send a message and pause the orchestration until the recipient responds or the wait expires | | `Send Template` | Send a template approved in your Meta Business account | ### Media | Operation | Description | | - | - | | `Upload` | Upload a file to Meta and return its WhatsApp media ID | | `Download` | Retrieve media information by WhatsApp media ID | | `Delete` | Delete media by WhatsApp media ID | *** ## Common Message Parameters | Parameter | Type | Required | Description | | - | - | - | - | | **Credential** | Credential | Yes | Select or create a [WhatsApp API](/credentials/types/whatsapp-api) credential | | **Sender Phone Number (or ID)** | Select | Yes | Sender number loaded from the credential's Business Account ID | | **Recipient's Phone Number** | String | Yes | Recipient phone number including the country code, for example `+919876543210` | | **Message Type** | Select | For `Send` | `Audio`, `Contacts`, `Document`, `Image`, `Location`, `Text`, or `Video` | ## Send Media in a Message For `Audio`, `Document`, `Image`, and `Video` messages, choose where the media comes from: | Source | Description | | - | - | | **Link** | Provide a URL that WhatsApp can download | | **WhatsApp Media** | Provide the ID of media already uploaded to Meta | | **Upload File** | Drag and drop or select a local file. SubverseAI uploads the file and resolves its temporary signed URL when sending | Documents can include a filename. Images, videos, and documents can include a caption. ## Send Template Parameters | Parameter | Type | Required | Description | | - | - | - | - | | **Template** | Select | Yes | Approved template loaded from the connected WhatsApp Business account | | **Components** | Collection | No | Dynamic `header`, `body`, and `button` values. Button components support a subtype and zero-based index | ## Media Resource Parameters | Operation | Parameter | Required | Description | | - | - | - | - | | `Upload` | **Sender Phone Number (or ID)** | Yes | Phone number under which Meta stores the media | | `Upload` | **Upload File** | Yes | Drag and drop or select the file to upload | | `Upload` | **Filename** | No | Optional name to use for the uploaded file | | `Download` | **Media ID** | Yes | ID of the media to retrieve | | `Delete` | **Media ID** | Yes | ID of the media to delete | *** ## Output Data A successful send operation returns: ```json theme={null} { "messaging_product": "whatsapp", "contacts": [ { "input": "+919876543210", "wa_id": "919876543210" } ], "messages": [ { "id": "wamid.XXXXXXXXXXXX" } ] } ``` Reference in downstream nodes: ``` {{ whatsapp.messages[0].id }} {{ whatsapp.contacts[0].wa_id }} ``` *** ## Related Nodes * [WhatsApp Trigger](./whatsapp-trigger.md) — Trigger on incoming WhatsApp messages * [SubVerse Agents](./subverse-agents.md) — Delegate WhatsApp conversations to a SubVerse AI agent # Whatsapp trigger Source: https://docs.subverseai.com/agentverse/nodes/whatsapp-trigger # WhatsApp Trigger The **WhatsApp Trigger** starts an orchestration when an incoming WhatsApp message is received on a connected number. WhatsApp Trigger Node *** ## Use Cases * Build AI-powered WhatsApp bots using AgentVerse * Automate customer support workflows triggered by WhatsApp messages * Route incoming messages based on content or sender * Integrate WhatsApp as an input channel for AI agents *** ## Credentials This node requires a **WhatsApp** credential configured with your WhatsApp Business API access token and phone number ID. To create a credential: 1. Go to **Settings → Credentials → New Credential** 2. Select **WhatsApp** 3. Enter your WhatsApp Business API access token and phone number ID *** ## Node Reference ### Parameters | Parameter | Type | Description | | - | - | - | | **Credential** | Credential | Select or create a WhatsApp credential | | **Trigger On** | Multi-select | Event types to listen for (e.g. `Messages`, `Template Category Update`) | ### Trigger On Options | Option | Description | | - | - | | `Messages` | Fires when a text or media message is received | | `Template Category Update` | Fires when a message template's category changes | ### Options | Option | Description | | - | - | | **Receive Message Status Updates** | Filter which delivery status updates trigger the orchestration: `All`, `Sent`, `Delivered`, `Read`. WhatsApp sends a notification when a message status changes (e.g. from Sent → Delivered). Set this to avoid multiple executions per message. | ### Webhook URL The WhatsApp Trigger displays a unique **Webhook URL** in the node panel. Configure this URL in your WhatsApp Business API app settings under **Webhooks**. *** ## Output Data The trigger outputs the incoming message payload: ```json theme={null} { "from": "919876543210", "to": "911234567890", "messageId": "wamid.XXXXXXXXXXXX", "type": "text", "text": { "body": "Hello, I need help with my order." }, "timestamp": "1678901234" } ``` For media messages: ```json theme={null} { "from": "919876543210", "type": "image", "image": { "id": "media-id", "mimeType": "image/jpeg", "caption": "Here's my receipt" }, "timestamp": "1678901234" } ``` Reference fields in downstream nodes: ``` {{ whatsappTrigger.text.body }} {{ whatsappTrigger.from }} {{ whatsappTrigger.messageId }} ``` *** ## Related Nodes * [WhatsApp](./whatsapp.md) — Send WhatsApp messages within an orchestration * [SubVerse Agents](./subverse-agents.md) — Route the message to a SubVerse AI agent * [AI Agent](./ai-agent.md) — Process the incoming message with an LLM # Quickstart Source: https://docs.subverseai.com/agentverse/quickstart Build your first AgentVerse orchestration in 10 minutes — webhook trigger, AI processing, Slack notification # Quickstart Build your first orchestration: receive a webhook, process the payload with an AI Agent, and send the result to Slack. **Time to complete:** \~10 minutes *** ## Prerequisites * Access to an AgentVerse workspace * A Slack workspace with a connected credential (you'll create it in Step 4) * An LLM provider API key (OpenAI, Anthropic, Google, or any supported provider) *** ## What You'll Build ``` [Webhook Trigger] → [AI Agent] → [Slack] ``` 1. A webhook receives an incoming HTTP POST with a user message 2. An AI Agent processes the message and generates a response 3. The response is sent to a Slack channel *** ## Steps 1. Open **AgentVerse** from the SubVerse AI dashboard. 2. Click **New Orchestration**. 3. Give it a name, e.g. `Webhook AI Slack Notification`. 4. Click **Create**. The canvas opens with an empty orchestration ready to build. 1. On the canvas, click **+** to open the node picker. 2. Under **Trigger**, select **Webhook**. 3. Set **HTTP Method** to `POST`. 4. Set **Response Mode** to `When Last Node Finishes`. 5. Copy the **Webhook URL** shown in the node — you will need this to test. The webhook URL is unique per orchestration. It only becomes active after you activate the orchestration in Step 5. 1. Click **+** on the right edge of the Webhook node. 2. Under **AI**, select **AI Agent**. 3. Configure the node: | Field | Value | | - | - | | **Provider** | Your preferred LLM provider (e.g. OpenAI) | | **Model** | Your preferred model (e.g. `gpt-4o`) | | **Operation** | `Generate Text` | | **Instructions** | `You are a helpful assistant. Respond concisely to the user message.` | 4. In the **Prompt** field, reference the incoming message from the webhook using the `{{ }}` expression syntax: ``` {{ webhook.body.message }} ``` Test the Webhook node first by clicking **Test**, then use the ⚡ link icon next to the Prompt field to visually browse and insert available fields. See [Dynamic Inputs](./dynamic-inputs.md) for details. 1. Click **+** on the right edge of the AI Agent node. 2. Under **Action**, select **Slack**. 3. Select operation **Send a Message**. 4. Connect or create a **Slack credential**: * Click **Create New Credential** * Authenticate with your Slack workspace via OAuth 5. Configure the message: | Field | Value | | - | - | | **Channel** | `#general` (or your target channel) | | **Message Text** | `{{ aiAgent.text }}` | 1. Click **Activate** in the top toolbar to enable the webhook listener. 2. Send a test request: ```bash theme={null} curl -X POST https:// \ -H "Content-Type: application/json" \ -d '{"message": "Summarise the benefits of AI automation in one sentence."}' ``` 3. Open the **Runs** tab to see the live execution trace. 4. Verify the Slack channel received the AI-generated message. *** ## What Happened | Step | Node | Action | | - | - | - | | 1 | Webhook | Received POST, extracted `body.message` | | 2 | AI Agent | Sent prompt to LLM, received text response | | 3 | Slack | Posted the AI response to the Slack channel | *** ## Next Steps Learn how to link node outputs to parameters using `{{ }}` expressions Branch your orchestration based on AI output or data values Replace the AI Agent with a full multi-channel SubVerse AI agent Track runs, inspect traces, and set up failure alerts # Troubleshooting Source: https://docs.subverseai.com/agentverse/troubleshooting # Troubleshooting This page covers common issues encountered when building and running AgentVerse orchestrations, along with steps to diagnose and resolve them. *** ## General Debugging Workflow 1. Open the **Orchestration Runs** panel and find the failed run. 2. Click the run to open the **Run Detail** view. 3. Inspect the **Node Execution Trace** — identify the first node with an `Error` status. 4. Expand the node row to view the full error message and the input data it received. 5. Use the information below to resolve the specific error type. *** ## Common Errors ### Orchestration Does Not Trigger **Symptom:** No runs appear in the Orchestration Runs panel when the expected event occurs. | Cause | Resolution | | - | - | | Orchestration is not activated | Click **Activate** in the top toolbar. A deactivated orchestration will not listen for trigger events. | | Webhook URL is incorrect | Copy the exact webhook URL from the Webhook Trigger node — use the production URL, not the test URL. | | Cron schedule is in the wrong timezone | Check the timezone setting on the Schedule Trigger node. Verify that the configured time is correct for your target timezone. | | Slack / WhatsApp trigger app is not installed | Ensure the bot has been added to the target channel or workspace. Re-authenticate the credential if needed. | *** ### Node Failed: Credential Error **Symptom:** A node fails with `401 Unauthorized`, `403 Forbidden`, or `Invalid API key`. | Cause | Resolution | | - | - | | Credential has expired | Go to **Settings → Credentials**, find the credential, and re-authenticate or update the token. | | Credential lacks required permissions/scopes | Check the node's documentation for required scopes and update your OAuth app or API key. | | Wrong credential selected | Open the node configuration and confirm the correct credential is selected. | *** ### Node Failed: Template Resolution Error **Symptom:** A node fails with `Cannot read property of undefined` or produces empty/unexpected values. **Cause:** A `{{ }}` expression references a field that does not exist in the upstream node's output. **Resolution:** 1. Open the failed run and expand the upstream node to view its actual output. 2. Verify the field names match exactly (case-sensitive). 3. Use dot notation for nested fields: `{{ webhook.body.data.userId }}` 4. Use a fallback value for optional fields: `{{ webhook.body.userId || 'unknown' }}` *** ### Node Failed: HTTP Request Error **Symptom:** HTTP Request node fails with a 4xx or 5xx status code. | Status Code | Likely Cause | Resolution | | - | - | - | | `400 Bad Request` | Malformed request body or missing required fields | Check the API documentation and verify your request body format | | `401 Unauthorized` | Missing or invalid authentication | Verify the credential and authentication method configured on the node | | `403 Forbidden` | Insufficient API permissions | Check API key scopes or account permissions | | `404 Not Found` | Incorrect endpoint URL | Verify the URL — check for trailing slashes, typos, or incorrect path parameters | | `429 Too Many Requests` | Rate limit exceeded | Add a [Wait](./nodes/wait.md) node to throttle request rate | | `5xx Server Error` | External service is unavailable | Check the service's status page; implement retry logic using a For Loop | *** ### Orchestration Run Times Out **Symptom:** A run stays in `Running` state for a long time and then fails with a timeout error. | Cause | Resolution | | - | - | | An AI Agent node takes too long | Increase the **Timeout** setting on the AI Agent node, or switch to a faster model | | Wait node with webhook resume never received a callback | Check that the external system is posting to the correct resume URL | | Human in the Loop awaiting approval | Check that the approval request was delivered to the correct Slack channel or email address | | External API is slow to respond | Increase the timeout on the HTTP Request node; add retry logic | *** ### Infinite Loop **Symptom:** A For Loop runs indefinitely and the run never completes. | Cause | Resolution | | - | - | | Array input is empty (causes unexpected behavior) | Add a [Conditions](./nodes/conditions.md) node before the For Loop to check that the array is non-empty | | Loop has no termination condition | Verify that `Iteration Count` or the `Input Array` reference is correctly set | *** ### Human in the Loop — Approval Message Not Received **Symptom:** The Slack or email approval message is never delivered. | Cause | Resolution | | - | - | | Bot is not a member of the target channel | Invite the Slack bot to the channel | | Email is in spam | Ask the approver to check their spam folder; whitelist the sending domain | | Incorrect channel or email configured | Open the Human in the Loop node and verify the **Slack Channel** or **To Email** field | | Credential has expired | Re-authenticate the Slack credential in **Settings → Credentials** | *** ### SubVerse Agent Call Did Not Start **Symptom:** A SubVerse Agents or SubVerse AI node reports a failure to initiate a call. | Cause | Resolution | | - | - | | Invalid phone number format | Ensure the number is in E.164 format: `+` (e.g. `+919876543210`) | | Bot number is not configured | Verify the bot number in the SubVerse AI dashboard and ensure it is active | | Insufficient call credits | Check your SubVerse AI account balance | *** ## Getting Help If you cannot resolve an issue using this guide: 1. Collect the **Run ID** and **error message** from the Run Detail view. 2. Check the **Node Execution Trace** and note which node failed and what input it received. 3. Contact SubVerse AI support with this information. *** ## Related Pages * [Monitoring](./monitoring.md) — View run history, metrics, and alerts * [Node Types](./node-types.md) — Reference for all node parameters and behavior # Cancel Scheduled Messages Source: https://docs.subverseai.com/api-reference/chat/cancel DELETE /chat-agent/cancel/{sessionId} Cancel messages scheduled with Trigger Chat that have not been sent yet. Stop messages you scheduled with [Trigger Chat](/api-reference/chat/trigger) before they are sent. This works for WhatsApp, Web Chat and Email messages. ## Endpoint ``` DELETE https://api-v2.subverseai.com/api/chat-agent/cancel/{sessionId} ``` ## Authentication Every request needs your workspace API key in the `x-api-key` header. ``` x-api-key: your_workspace_api_key ``` You can create an API key from your dashboard. See [API Keys](/integrations/api-keys) for details. ## Path Parameters | Parameter | Required | Description | | - | - | - | | `sessionId` | Yes | The `sessionId` you got back from Trigger Chat when you scheduled the message. | *** ## Response This API always returns `200`. Check `isCancelled` in the response to see whether anything was cancelled. ### Cancelled The scheduled messages were stopped and won't be sent. ```json theme={null} { "responseCode": 200, "message": "Scheduled messages cancelled successfully", "data": { "sessionId": "a3f1c9e2-7b4d-4e8a-9c21-5d6e7f8a9b0c", "isCancelled": true } } ``` ### Nothing to cancel There are no pending messages for this conversation. The message may have already been sent, already been cancelled, or the `sessionId` may be incorrect. ```json theme={null} { "responseCode": 200, "message": "No scheduled jobs found", "data": { "sessionId": "a3f1c9e2-7b4d-4e8a-9c21-5d6e7f8a9b0c", "isCancelled": false, "reason": "No scheduled jobs found for this session" } } ``` ### Could not cancel The message couldn't be cancelled, usually because it is already being sent. `reason` gives more detail. ```json theme={null} { "responseCode": 200, "message": "Jobs not cancelled", "data": { "sessionId": "a3f1c9e2-7b4d-4e8a-9c21-5d6e7f8a9b0c", "isCancelled": false, "reason": "..." } } ``` ### Response Fields | Field | Type | Description | | - | - | - | | `sessionId` | string | The conversation you asked to cancel. | | `isCancelled` | boolean | `true` if scheduled messages were stopped, otherwise `false`. | | `reason` | string | Only when `isCancelled` is `false`. Explains why nothing was cancelled. | *** ## Errors | Status | `errorCode` | What it means | | - | - | - | | 401 | `apiKeyMissing` | The `x-api-key` header is missing. | | 401 | `apiKeyInvalid` | The API key is not valid. | *** ## Code Examples ### cURL ```bash theme={null} curl -X DELETE \ -H "x-api-key: YOUR_API_KEY" \ https://api-v2.subverseai.com/api/chat-agent/cancel/SESSION_ID ``` ### JavaScript ```javascript theme={null} const response = await fetch( "https://api-v2.subverseai.com/api/chat-agent/cancel/SESSION_ID", { method: "DELETE", headers: { "x-api-key": "YOUR_API_KEY" }, } ); const result = await response.json(); console.log(result.data.isCancelled); ``` ### Python ```python theme={null} import requests response = requests.delete( "https://api-v2.subverseai.com/api/chat-agent/cancel/SESSION_ID", headers={"x-api-key": "YOUR_API_KEY"}, ) print(response.json()["data"]["isCancelled"]) ``` ### Node.js (axios) ```javascript theme={null} const axios = require("axios"); const { data } = await axios.delete( "https://api-v2.subverseai.com/api/chat-agent/cancel/SESSION_ID", { headers: { "x-api-key": "YOUR_API_KEY" } } ); console.log(data.data.isCancelled); ``` # Trigger Chat Source: https://docs.subverseai.com/api-reference/chat/trigger POST /chat-agent/trigger Start a conversation with a customer over WhatsApp, Web Chat or Email using your chosen agent — or get the agent's reply straight back in the response. Start a conversation with a customer on **WhatsApp**, **Web Chat** or **Email** using one of your agents. You can let the agent write the message, send your own text, use an approved WhatsApp template, or schedule the message for later. You can also use this API to **get the agent's reply straight back** in the response, without messaging any customer. This is handy for testing an agent or building your own chat experience. ## Endpoint ``` POST https://api-v2.subverseai.com/api/chat-agent/trigger ``` ## Authentication Every request needs your workspace API key in the `x-api-key` header. ``` x-api-key: your_workspace_api_key ``` You can create an API key from your dashboard. See [API Keys](/integrations/api-keys) for details. *** ## Choose how you want to use it Send a message through one of your WhatsApp, Web Chat or Email channels. The customer receives it and can reply, and your agent carries on the conversation. Set `doReturnResponse` to `true`. The agent's reply comes back in the response and nothing is sent to a customer. *** ## Message a customer ### Before you start * Set up a WhatsApp, Web Chat or Email channel under **Integrations** in your dashboard, and make sure it is enabled. * Assign an agent to the channel, or pass `agentName` in your request. ### Basic fields | Field | Required | Description | | - | - | - | | `communicationChannel` | Yes | The name of your channel, exactly as it appears under **Integrations** in your dashboard. | | `customerNumber` | WhatsApp & Web Chat | **WhatsApp:** the customer's phone number with country code, e.g. `+919876543210`. **Web Chat:** the user's ID on your website or app. | | `customerEmail` | Email | The customer's email address. | | `agentName` | No | The agent that should handle the conversation. Defaults to the agent assigned to the channel. | | `agentVersion` | No | `default` (published version), `draft` (latest saved draft) or a version number such as `2`. | | `metadata` | No | Customer details used to personalise the conversation. See [Personalise with metadata](#personalise-with-metadata). | | `attachments` | No | A list of links to files (images, PDFs, documents) to send with the message. Links must be publicly accessible. | ### WhatsApp Use `whatsappOptions.messageType` to choose how the first message is created. The agent writes the opening message itself, using its instructions, the customer's `metadata` and any `additionalContext` you provide. This is the default. ```json theme={null} { "communicationChannel": "Support WhatsApp", "customerNumber": "+919876543210", "agentName": "payment_reminder", "metadata": { "name": "John Doe", "amountDue": "₹1,200" }, "whatsappOptions": { "messageType": "prompt", "additionalContext": "Remind the customer that their payment is due tomorrow." } } ``` Sends your text exactly as written. If the customer replies, your agent takes over the conversation. ```json theme={null} { "communicationChannel": "Support WhatsApp", "customerNumber": "+919876543210", "whatsappOptions": { "messageType": "say", "message": "Hi John, your order ORD-1042 has been shipped!" } } ``` Sends one of your approved WhatsApp templates. Use this when messaging a customer who hasn't chatted with you in the last 24 hours, since WhatsApp only allows templates in that case. ```json theme={null} { "communicationChannel": "Support WhatsApp", "customerNumber": "+919876543210", "whatsappOptions": { "messageType": "template", "templateId": "order_update", "templateLanguage": "en", "templateVariables": { "1": "John", "2": "ORD-1042" } } } ``` | `whatsappOptions` field | Used with | Description | | - | - | - | | `messageType` | All | `prompt` (default), `say` or `template`. | | `additionalContext` | `prompt` | Extra instructions or background for the agent when writing the message. | | `message` | `say` | **Required for `say`.** The exact text to send. | | `templateId` | `template` | **Required for `template`.** The name of your approved WhatsApp template. | | `templateLanguage` | `template` | The template's language code, e.g. `en` or `hi`. Defaults to `en`. | | `templateVariables` | `template` | Values for the template's placeholders. | **Sending from a specific number:** if your WhatsApp channel has more than one number, pass `agentNumber` to choose which one to send from. It must be one of the channel's numbers. If you leave it out, one of them is picked for you. ### Web Chat The agent writes the opening message and sends it to the user in your web chat. Pass the user's ID as `customerNumber`. To give the agent extra instructions, use `whatsappOptions.additionalContext`. ```json theme={null} { "communicationChannel": "Website Chat", "customerNumber": "user_8812", "metadata": { "name": "John Doe", "plan": "Pro" }, "whatsappOptions": { "additionalContext": "Welcome the user and ask if they need help upgrading their plan." } } ``` ### Email Use `emailOptions.messageType` to choose who writes the email. ```json theme={null} { "communicationChannel": "Support Email", "customerEmail": "john@example.com", "metadata": { "name": "John Doe" }, "emailOptions": { "messageType": "prompt", "subject": "Following up on your request", "additionalContext": "Follow up on the refund request the customer raised last week." } } ``` ```json theme={null} { "communicationChannel": "Support Email", "customerEmail": "john@example.com", "emailOptions": { "messageType": "say", "subject": "Your order has shipped", "body": "Hi John, your order ORD-1042 is on its way!", "cc": "orders@yourcompany.com" } } ``` | `emailOptions` field | Used with | Description | | - | - | - | | `messageType` | All | `prompt` (default) or `say`. | | `additionalContext` | `prompt` | Extra instructions or background for the agent when writing the email. | | `body` | `say` | **Required for `say`.** The exact email content to send. | | `subject` | All | Email subject line. | | `cc` | All | Email addresses to CC, separated by commas. | | `bcc` | All | Email addresses to BCC, separated by commas. | | `replyTo` | All | The `sessionId` of an earlier email conversation. The email is sent as a reply in that same thread, and anyone already in CC/BCC stays included. Leave it out to start a new thread. | *** ## Schedule a message Instead of sending right away, you can send at a set time, only during working hours, or both. Scheduling works with every channel and message type. | Field | Description | | - | - | | `scheduleTime` | Date and time to send, in ISO format, e.g. `2026-10-05T09:30:00Z`. If the time has already passed, the message is sent right away. | | `startWorkingHour` | Earliest time of day to send, in 24-hour `HH:MM` format. Messages due earlier wait until this time. | | `endWorkingHour` | Latest time of day to send, in 24-hour `HH:MM` format. Messages due later are sent the next day at `startWorkingHour` (or at midnight if `startWorkingHour` isn't set). | | `timezone` | Timezone for your working hours, e.g. `Asia/Kolkata`. Defaults to `UTC`. | ```json theme={null} { "communicationChannel": "Support WhatsApp", "customerNumber": "+919876543210", "whatsappOptions": { "messageType": "say", "message": "Hi John, just checking in on your recent order." }, "scheduleTime": "2026-10-05T04:00:00Z", "startWorkingHour": "09:00", "endWorkingHour": "20:00", "timezone": "Asia/Kolkata" } ``` Changed your mind? Use [Cancel Scheduled Messages](/api-reference/chat/cancel) with the `sessionId` you got back to stop a message that hasn't been sent yet. *** ## Get the agent's reply Set `doReturnResponse` to `true` to send a message to your agent and receive its reply in the response. No message is sent to a customer, so you don't need a channel. | Field | Required | Description | | - | - | - | | `doReturnResponse` | Yes | Set to `true`. | | `agentName` | Yes | The agent that should reply. | | `agentVersion` | No | `default`, `draft` or a version number. | | `message` | No | The customer's message for the agent to reply to. | | `sessionId` | No | The `sessionId` from a previous response, to continue the same conversation. Leave it out to start a new one. | | `customerNumber` / `customerEmail` | No | Identifies the customer in your session history. | | `metadata` | No | Customer details used to personalise the reply. | | `attachments` | No | Links to files for the agent to look at, such as an image or a PDF. | | `chatOptions.additionalContext` | No | Extra instructions or background for the agent, for this reply only. | ```json theme={null} { "agentName": "support_bot", "doReturnResponse": true, "message": "Where is my order?", "customerEmail": "john@example.com", "metadata": { "orderId": "ORD-1042" } } ``` To keep chatting, send the next message with the same `sessionId`: ```json theme={null} { "agentName": "support_bot", "doReturnResponse": true, "sessionId": "b7e2d4f1-1c3a-4b5d-8e6f-0a9b8c7d6e5f", "message": "Can I change the delivery address?" } ``` `doReturnResponse` can't be combined with `scheduleTime`, `startWorkingHour` or `endWorkingHour`. *** ## Personalise with metadata Anything you put in `metadata` can be used in your agent's prompts as `${variable_name}`. For example, with this metadata: ```json theme={null} "metadata": { "name": "John Doe", "orderId": "ORD-1042" } ``` an agent prompt containing `Greet ${name} and confirm order ${orderId}` becomes `Greet John Doe and confirm order ORD-1042`. WhatsApp templates don't use `metadata`. Fill template placeholders with `whatsappOptions.templateVariables` instead. *** ## Response ### Message sent or scheduled You get back a `sessionId` for the conversation. Keep it so you can [look up the conversation](/api-reference/session/fetch) later or [cancel](/api-reference/chat/cancel) a scheduled message. ```json theme={null} { "responseCode": 200, "message": "Trigger dispatched", "data": { "sessionId": "a3f1c9e2-7b4d-4e8a-9c21-5d6e7f8a9b0c" } } ``` ### Agent reply (`doReturnResponse`) You get back the `sessionId` and a `transcript` with your message and everything the agent did in reply. ```json theme={null} { "responseCode": 200, "message": "Trigger dispatched", "data": { "sessionId": "b7e2d4f1-1c3a-4b5d-8e6f-0a9b8c7d6e5f", "transcript": [ { "type": "message", "role": "user", "content": [{ "type": "text", "text": "Where is my order?" }], "senderId": "john@example.com", "timestamp": "2026-10-01T10:00:00.000Z" }, { "type": "message", "role": "assistant", "content": [{ "type": "text", "text": "Hi! Your order ORD-1042 has shipped and should arrive by Friday." }], "agentName": "support_bot", "timestamp": "2026-10-01T10:00:02.000Z" } ] } } ``` The transcript may also include tool usage and other entries. See [Transcript Entry Types](/api-reference/session/fetch#transcript-entry-types) for the full list. Links to images and files in the transcript expire after a limited time. Download or save them promptly. *** ## Errors Errors use the same format: ```json theme={null} { "responseCode": 400, "errorCode": "customerNumberRequired", "message": "customerNumber is required for chat channels", "data": null } ``` | Status | `errorCode` | What it means | | - | - | - | | 400 | `customerNumberRequired` | `customerNumber` is missing for a WhatsApp or Web Chat channel. | | 400 | `customerEmailRequired` | `customerEmail` is missing for an Email channel. | | 400 | `messageRequired` | `whatsappOptions.message` is missing for a WhatsApp `say` message. | | 400 | `templateIdRequired` | `whatsappOptions.templateId` is missing for a WhatsApp `template` message. | | 400 | `templateNotSupported` | The WhatsApp channel doesn't support templates. | | 400 | `emailBodyRequired` | `emailOptions.body` is missing for an Email `say` message. | | 400 | `agentNumberNotInChannel` | The `agentNumber` you passed isn't one of the channel's WhatsApp numbers. | | 400 | `noAgentPhoneNumbers` | The WhatsApp channel has no phone numbers set up. | | 400 | `noAgentEmail` | The Email channel has no email address set up. | | 400 | `unsupportedChannelType` | The channel isn't a WhatsApp, Web Chat or Email channel. To place calls, use [Trigger Call](/api-reference/direct-call/trigger). | | 400 | `agentNameRequired` | `agentName` is missing when `doReturnResponse` is `true`. | | 400 | `incompatibleOptions` | `doReturnResponse` was used together with scheduling options. | | 401 | `apiKeyMissing` | The `x-api-key` header is missing. | | 401 | `apiKeyInvalid` | The API key is not valid. | | 403 | `forbidden` | The `sessionId` belongs to a different workspace. | | 404 | `channelNotFound` | No enabled channel with that name was found in your workspace. Check the spelling and that the channel is turned on. | | 404 | `sessionNotFound` | The `sessionId` you passed doesn't exist. | | 404 | `replyToSessionNotFound` | The `emailOptions.replyTo` conversation doesn't exist. | | 422 | `validationError` | A field has the wrong type, e.g. text where `true`/`false` is expected. | | 500 | `internalError` | Something went wrong on our side. Please try again or contact support. | *** ## Code Examples ### cURL ```bash theme={null} curl -X POST https://api-v2.subverseai.com/api/chat-agent/trigger \ -H "x-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "communicationChannel": "Support WhatsApp", "customerNumber": "+919876543210", "metadata": { "name": "John Doe" }, "whatsappOptions": { "messageType": "prompt", "additionalContext": "Remind the customer that their payment is due tomorrow." } }' ``` ### JavaScript ```javascript theme={null} const response = await fetch( "https://api-v2.subverseai.com/api/chat-agent/trigger", { method: "POST", headers: { "x-api-key": "YOUR_API_KEY", "Content-Type": "application/json", }, body: JSON.stringify({ communicationChannel: "Support WhatsApp", customerNumber: "+919876543210", metadata: { name: "John Doe" }, whatsappOptions: { messageType: "prompt", additionalContext: "Remind the customer that their payment is due tomorrow.", }, }), } ); const result = await response.json(); console.log(result.data.sessionId); ``` ### Python ```python theme={null} import requests response = requests.post( "https://api-v2.subverseai.com/api/chat-agent/trigger", headers={"x-api-key": "YOUR_API_KEY"}, json={ "communicationChannel": "Support WhatsApp", "customerNumber": "+919876543210", "metadata": {"name": "John Doe"}, "whatsappOptions": { "messageType": "prompt", "additionalContext": "Remind the customer that their payment is due tomorrow.", }, }, ) print(response.json()["data"]["sessionId"]) ``` ### Node.js (axios) ```javascript theme={null} const axios = require("axios"); const { data } = await axios.post( "https://api-v2.subverseai.com/api/chat-agent/trigger", { communicationChannel: "Support WhatsApp", customerNumber: "+919876543210", metadata: { name: "John Doe" }, whatsappOptions: { messageType: "prompt", additionalContext: "Remind the customer that their payment is due tomorrow.", }, }, { headers: { "x-api-key": "YOUR_API_KEY" } } ); console.log(data.data.sessionId); ``` # Cancel Call Source: https://docs.subverseai.com/api-reference/direct-call/cancel PUT /call/cancel/{callId} Cancels an outbound call that is still queued. Only calls whose call status is `call_in_queue` can be canceled. Removes the pending queued calls and updates call status to canceled. # Generate Signed URL Source: https://docs.subverseai.com/api-reference/direct-call/signed-url GET /call/signed-recording-url Generates a secure, time-limited pre-signed URL for an asset stored in the SubVerse private S3 bucket, such as call recordings or session attachments. You must provide either 'callId' or 'callRecordingUrl' in the query parameters. # Trigger Call Source: https://docs.subverseai.com/api-reference/direct-call/trigger POST /call/trigger Place a call to a customer using your chosen agent and settings. # Get Session Details Source: https://docs.subverseai.com/api-reference/session/fetch GET /session/fetch/{sessionId} Get everything about a single session in one place — who was involved, what was said, how it went, and when it happened. For phone calls, you'll also see the call duration, retry info, and a link to the recording. Retrieve full details of a specific session by its ID. ## Endpoint ``` GET /api/session/fetch/{sessionId} ``` ## Authentication All requests require an API key passed in the `x-api-key` header. ``` x-api-key: your_workspace_api_key ``` Contact your workspace admin if you don't have an API key. ## Path Parameters | Parameter | Type | Required | Description | | - | - | - | - | | `sessionId` | string | Yes | The unique identifier of the session. | ## Response ### Success (200) ```json theme={null} { "responseCode": 200, "message": "Session details found", "data": { "sessionId": "sess_01H8XK3Q9V1YJZ5T7N2A8B9C0D", "agentDetails": { "name": "SupportBot", "number": "+15551234567", "email": "agent@example.com", "version": "v1.2.0" }, "userDetails": { "id": "u_42", "name": "Jane Doe", "number": "+15557654321", "email": "jane@example.com" }, "dynamicVariables": { "plan": "pro", "accountId": "acc_99" }, "communicationChannelType": "inboundSipTrunk", "communicationChannelName": "Inbound Support Line", "transcript": [...], "analysis": { "summary": "User asked about refund status; agent confirmed processing.", "sentiment": "positive" }, "status": "call_hangup", "time": "2026-09-07T10:00:00.000Z", "createdAt": "2026-09-07T10:00:00.000Z", "updatedAt": "2026-09-07T10:03:04.000Z", "duration": 184, "retryAttemptNo": 0, "recordingUrl": "https://s3.example.com/signed/recordings/sess_...wav?sig=..." } } ``` ### Response Fields | Field | Type | Description | | - | - | - | | `sessionId` | string | Unique session identifier. | | `agentDetails` | object | Details of the agent that handled the session. | | `agentDetails.name` | string | Agent name. | | `agentDetails.number` | string \| null | Agent phone number (if applicable). | | `agentDetails.email` | string \| null | Agent email address (if applicable). | | `agentDetails.version` | string \| null | Agent version label. | | `userDetails` | object | Details of the user/customer in the session. | | `userDetails.id` | string | User identifier (phone number, email, or custom ID). | | `userDetails.name` | string \| null | User display name. | | `userDetails.number` | string \| null | User phone number. | | `userDetails.email` | string \| null | User email address. | | `dynamicVariables` | object \| null | Custom variables associated with the session. | | `communicationChannelType` | string | The channel type used for the session. Possible values: `email`, `inboundSipTrunk`, `outboundSipTrunk`, `waChat`, `waVoice`, `sms`, `webChat`. | | `communicationChannelName` | string \| null | Human-readable name of the channel. | | `transcript` | array | Full conversation transcript. See [Transcript Entry Types](#transcript-entry-types) below. | | `analysis` | object \| null | AI-generated post-session analysis (summary, sentiment, tags, etc.). Content depends on your agent's analytics configuration. | | `status` | string | Current session status. See [Session Statuses](#session-statuses) below. | | `time` | string (ISO 8601) | When the session started. | | `createdAt` | string (ISO 8601) | When the session record was created. | | `updatedAt` | string (ISO 8601) | When the session record was last updated. | | `duration` | number \| null | Session duration in seconds. **Only present for call sessions.** | | `retryAttemptNo` | number | Retry attempt number (0 = original, 1+ = retry). **Only present for call sessions.** | | `recordingUrl` | string \| null | Signed URL to the call recording (expires after a limited time). **Only present for call sessions.** | `duration`, `retryAttemptNo`, and `recordingUrl` are only included for call sessions (SIP trunk channels). For chat, email, WhatsApp, and other non-call sessions, these fields are omitted entirely. *** ## Transcript Entry Types The `transcript` array contains entries in chronological order. Each entry has a `type` field that determines its structure. ### 1. Message (`type: "message"`) A text or media message from the user, agent, or background agent. ```json theme={null} { "type": "message", "role": "user", "content": [ { "type": "text", "text": "Hi, I want to check my refund." } ], "senderId": "+15557654321", "senderName": "Jane Doe", "agentName": "SupportBot", "metadata": {}, "timestamp": "2026-09-07T10:00:00.000Z" } ``` | Field | Type | Description | | - | - | - | | `role` | string | Who sent the message: `user`, `assistant`, or `backgroundAgent`. | | `content` | array | One or more content items. See [Content Item Types](#content-item-types). | | `senderId` | string \| null | Sender identifier (phone number or email). | | `senderName` | string \| null | Sender display name. | | `agentName` | string \| null | Agent name (for assistant messages). | | `metadata` | object \| null | Channel-specific extras (e.g. email subject, custom context). | | `timestamp` | string (ISO 8601) | When the message was sent. | ### 2. Function Call (`type: "function_call"`) The agent invoked a tool/function. ```json theme={null} { "type": "function_call", "name": "lookupRefund", "call_id": "call_abc", "arguments": { "accountId": "acc_99" }, "phase": "during", "timestamp": "2026-09-07T10:00:03.000Z" } ``` | Field | Type | Description | | - | - | - | | `name` | string | Name of the tool/function called. | | `call_id` | string | Unique identifier for this tool call. | | `arguments` | object | Arguments passed to the tool. | | `phase` | string \| null | When the tool ran: `pre`, `during`, or `post` session. | | `timestamp` | string (ISO 8601) | When the tool was called. | ### 3. Function Call Output (`type: "function_call_output"`) The result returned by a tool execution. ```json theme={null} { "type": "function_call_output", "name": "lookupRefund", "call_id": "call_abc", "output": "{\"status\":\"processing\"}", "is_error": false, "executionTimeMs": 340, "phase": "during", "timestamp": "2026-09-07T10:00:03.340Z" } ``` | Field | Type | Description | | - | - | - | | `name` | string | Name of the tool that produced this output. | | `call_id` | string | Matches the `call_id` of the corresponding function call. | | `output` | string | The tool's output (typically a JSON string). | | `is_error` | boolean | Whether the tool execution resulted in an error. | | `executionTimeMs` | number \| null | Tool execution time in milliseconds. | | `phase` | string \| null | When the tool ran: `pre`, `during`, or `post` session. | | `timestamp` | string (ISO 8601) | When the output was produced. | ### 4. Thinking (`type: "thinking"`) The agent's internal reasoning for a turn. ```json theme={null} { "type": "thinking", "thinking": "The user is asking about a refund. I should look up their account first.", "timestamp": "2026-09-07T10:00:02.500Z" } ``` | Field | Type | Description | | - | - | - | | `thinking` | string | The agent's reasoning text. | | `timestamp` | string (ISO 8601) | When this reasoning was generated. | ### 5. Summary (`type: "summary"`) A generated summary of the conversation up to a certain point. ```json theme={null} { "type": "summary", "summary": "User asked about refund status, agent confirmed processing.", "timestamp": "2026-09-07T10:01:00.000Z" } ``` | Field | Type | Description | | - | - | - | | `summary` | string | Summary text of the preceding conversation. | | `timestamp` | string (ISO 8601) | When the summary was generated. | *** ## Content Item Types Each message entry's `content` array contains one or more items. The `type` field determines the structure. ### Text ```json theme={null} { "type": "text", "text": "Hello, how can I help you?" } ``` ### Image ```json theme={null} { "type": "image", "mimeType": "image/jpeg", "url": "https://s3.example.com/signed/image.jpg?sig=...", "caption": "Screenshot of the issue" } ``` ### Video ```json theme={null} { "type": "video", "mimeType": "video/mp4", "url": "https://s3.example.com/signed/video.mp4?sig=...", "caption": "Screen recording" } ``` ### Audio ```json theme={null} { "type": "audio", "mimeType": "audio/ogg", "url": "https://s3.example.com/signed/audio.ogg?sig=..." } ``` ### File ```json theme={null} { "type": "file", "mimeType": "application/pdf", "url": "https://s3.example.com/signed/document.pdf?sig=...", "filename": "invoice.pdf" } ``` ### Button (Quick Reply) ```json theme={null} { "type": "button", "text": "Yes, proceed", "payload": "confirm_proceed" } ``` Media URLs (`image`, `video`, `audio`, `file`) are signed and expire after a limited time. Download or cache them promptly. *** ## Session Statuses | Status | Description | | - | - | | `active` | Session is currently in progress. | | `completed` | Session has ended normally. | | `call_in_queue` | Call is queued and waiting to be placed. | | `call_placed` | Call has been placed but not yet answered. | | `call_in_progress` | Call is currently connected. | | `call_errored` | Call encountered an error. | | `call_expired` | Call expired before being answered. | | `call_hangup` | Call was hung up (completed). | | `agent_errored` | Agent encountered an error during the session. | | `call_canceled` | Call was canceled. | | `could_not_connect` | Call could not be connected. | *** ## Errors All errors follow the same response format: ```json theme={null} { "responseCode": , "errorCode": "", "message": "", "data": null } ``` ### 401 — Unauthorized **Missing API key:** ```json theme={null} { "responseCode": 401, "errorCode": "apiKeyMissing", "message": "API key missing", "data": null } ``` **Invalid API key:** ```json theme={null} { "responseCode": 401, "errorCode": "apiKeyInvalid", "message": "Invalid API key", "data": null } ``` ### 404 — Session Not Found The session ID does not exist in the workspace associated with your API key. ```json theme={null} { "responseCode": 404, "errorCode": "sessionNotFound", "message": "Session not found", "data": null } ``` ### 422 — Validation Error The `sessionId` path parameter is missing or empty. ```json theme={null} { "responseCode": 422, "errorCode": "validationError", "message": "Expected string length greater or equal to 1", "data": null } ``` ### 500 — Internal Server Error ```json theme={null} { "responseCode": 500, "errorCode": "internalError", "message": "Internal server error", "data": null } ``` *** ## Code Examples ### cURL ```bash theme={null} curl -s -H "x-api-key: YOUR_API_KEY" \ https://api-v2.subverseai.com/api/session/fetch/SESSION_ID ``` ### JavaScript ```javascript theme={null} const response = await fetch( "https://api-v2.subverseai.com/api/session/fetch/SESSION_ID", { headers: { "x-api-key": "YOUR_API_KEY", }, } ); const result = await response.json(); console.log(result.data); ``` ### Python ```python theme={null} import requests response = requests.get( "https://api-v2.subverseai.com/api/session/fetch/SESSION_ID", headers={"x-api-key": "YOUR_API_KEY"}, ) data = response.json() print(data["data"]) ``` ### Node.js (axios) ```javascript theme={null} const axios = require("axios"); const { data } = await axios.get( "https://api-v2.subverseai.com/api/session/fetch/SESSION_ID", { headers: { "x-api-key": "YOUR_API_KEY" } } ); console.log(data.data); ``` # Troubleshooting Call Issues Source: https://docs.subverseai.com/call-history/troubleshooting Common call issues and their solutions ## Could Not Connect **Possible Causes:** * Invalid or incorrect phone number format * Network connectivity issues * Telephony provider problems * Customer's phone is off or unreachable * Number is blocked or invalid **Solutions:** * Verify phone number format (include country code) * Check telephony integration status in Integrations section * Retry during different times of day * Contact telephony provider for trunk status * Validate number before calling ## Short Duration Calls (\< 10 seconds) **Possible Causes:** * Customer hung up immediately * Poor audio quality * Agent didn't respond quickly enough * Wrong number dialed * Greeting message unclear **Solutions:** * Improve greeting message clarity * Reduce initial response time (adjust Agent Responsiveness) * Verify target audience and phone list quality * Test audio quality with sample calls * Consider greeting type (Prompt vs Listen) ## Long Duration Calls (> 10 minutes) **Possible Causes:** * Agent unable to resolve customer issue * Circular conversation loops * Missing information in knowledge base * Complex customer inquiry beyond agent capability * No clear exit strategy **Solutions:** * Add relevant content to knowledge base * Improve system prompt with clearer instructions * Enable human transfer option for complex cases * Add timeout mechanisms (Max Duration setting) * Define clear end-of-call criteria in prompt ## Incomplete Conversations **Possible Causes:** * Customer lost interest * Agent responses not relevant * Technical issues during call * Customer got what they needed early **Solutions:** * Review transcripts to identify drop-off points * Improve conversation flow in system prompt * Add engagement techniques * Ensure agent addresses customer needs directly # Email Channel Source: https://docs.subverseai.com/communication-channels/email Connect an email inbox to your Email Agent to automatically reply to incoming messages ## Overview An Email Channel connects a real email address to an Email Agent. When an email arrives at the configured address, the linked agent reads it and sends a reply automatically — handling support requests, FAQs, and inquiries without human intervention. Email channels use your SMTP credentials to authorize sending emails from your address. These credentials are stored securely in encrypted form. **When to use an Email Channel:** * You want to automate replies to incoming support or inquiry emails * You need a first-line response bot that can triage or answer FAQs * You want AI-generated replies sent directly from your own email address *** ## How to Set Up 1. Navigate to **Channels** in the left sidebar. 2. Click **Add Channel** and select **Email**. 3. Fill in the channel details (see configuration below). 4. Select or create an **Email Credential**. 5. Under **Agent Configuration**, link an Email Agent. 6. Click **Save**. Once saved, any email sent to the configured address will be processed by the linked Email Agent, which will compose and send a reply. *** ## Configuration | Field | Type | Required | Description | | - | - | - | - | | Name | Text | Yes | A friendly name for this channel (e.g. `Support Inbox`). | | Description | Text | No | Internal description for this channel. | | Email | Text | Yes | The email address that will receive incoming emails and send replies (e.g. `support@company.com`). | | Email Credential | Dropdown | Yes | Select a saved email (SMTP) credential to authorize sending from this address. Click **Create new credentials** to add one under Credentials. | | Email Agent | Dropdown | No | The Email Agent that will handle incoming messages on this channel. | *** ## Credentials Email channels require an **Email credential** containing your SMTP server details (host, port, username, password). This authorizes Subverse to send emails on behalf of your address. Credentials are stored encrypted and never exposed in plaintext after saving. Create and manage your email credentials in the Credentials section Make sure your email address is also configured to receive inbound mail (e.g. via MX records or your provider's inbound routing). Subverse handles the reply logic; your mail server handles delivery. # Communication Channels Source: https://docs.subverseai.com/communication-channels/overview Connect your agents to the channels where your customers communicate ## Overview Communication Channels are the bridges between your Subverse agents and the outside world. Each channel represents a specific communication medium — a phone number, a WhatsApp account, an email inbox, or a website chat endpoint — and is linked to an agent that handles all incoming interactions on that channel. **How it works:** 1. Create a channel for the communication medium you want to support. 2. Attach credentials to authorize the channel (e.g. SIP credentials for voice, WhatsApp API keys, SMTP details for email). 3. Link an agent to the channel. All interactions arriving on that channel are routed to the linked agent automatically. Credentials attached to channels are stored securely in encrypted form and are never exposed in plaintext after saving. *** ## Channel Types | Channel | Protocol | Compatible Agent | Use Case | | - | - | - | - | | [Voice](/communication-channels/voice) | SIP Trunk (Inbound / Outbound) | Voice Agent | Phone calls — inbound customer support, outbound dialing | | [WhatsApp](/communication-channels/whatsapp) | WhatsApp Business API | Chat Agent | Automated messaging via WhatsApp | | [Email](/communication-channels/email) | SMTP / Email | Email Agent | Auto-reply to incoming emails | | [WebChat](/communication-channels/webchat) | Webhooks / API | Chat Agent | Embedded chat widget or API-driven chat on your website | SMS and iMessage channels are coming soon. *** ## Adding a Channel 1. Navigate to **Channels** in the left sidebar. 2. Click **Add Channel**. 3. Select the channel type. 4. Fill in the channel details and attach credentials. 5. Link an agent under **Agent Configuration**. 6. Click **Save**. Once saved, the channel is live and will route all incoming interactions to the linked agent. # Voice Channel Source: https://docs.subverseai.com/communication-channels/voice Connect inbound and outbound phone numbers to your Voice Agents via SIP trunks ## Overview A Voice Channel connects your Voice Agent to real phone numbers using SIP trunks. Subverse gives you a unique **SIP URI** for your workspace — you configure your telephony provider to point calls to this URI, and Subverse routes them to the linked agent. Voice channels support two trunk types: * **Inbound SIP Trunk** — receives incoming calls and routes them to a Voice Agent * **Outbound SIP Trunk** — provides a number the agent uses to make outgoing calls Your workspace **SIP URI** is shown at the top of the Voice Channel setup screen. Copy this and configure it as the destination in your telephony provider (Twilio, Telnyx, Plivo, etc.). To use the live call transfer feature, you must configure an Outbound Trunk for the corresponding number and ensure outbound calling is enabled by your telephony provider. *** ## Inbound SIP Trunk An inbound trunk assigns a phone number that customers can call. Incoming calls on this number are routed directly to the linked Voice Agent. ### Configuration | Field | Type | Required | Description | | - | - | - | - | | Name | Text | Yes | A friendly name for this inbound trunk (e.g. `Support Line`). | | Description | Text | No | Internal description for this channel. | | Numbers | Phone number list | Yes | One or more phone numbers that will receive inbound calls. Click **+ Add number** to add numbers with country code. | | SIP Credential | Dropdown | Yes | Select a saved SIP credential to authenticate this trunk. Click **Create new credentials** to add one under Credentials. | | Agent | Dropdown | No | The Voice Agent to handle calls on this trunk. Link directly here or configure it later. | ### How to Set Up 1. Navigate to **Channels** and click **Add Channel → Voice**. 2. Select **Inbound SIP Trunk for Calls**. 3. Enter a **Name** and optionally a **Description**. 4. Add the **phone number(s)** that will receive calls. 5. Select a **SIP Credential** (or create one). 6. Under **Agent Configuration**, select the Voice Agent to handle calls. 7. Click **Save**. 8. In your telephony provider, point the number's SIP destination to your workspace **SIP URI**. *** ## Outbound SIP Trunk An outbound trunk provides a phone number the Voice Agent uses when placing outgoing calls — either for outbound campaigns or for the test call feature. ### Configuration | Field | Type | Required | Description | | - | - | - | - | | Name | Text | Yes | A friendly name for this outbound trunk (e.g. `Outbound Dialer`). | | Description | Text | No | Internal description for this channel. | | Numbers | Phone number list | Yes | The phone number(s) used as the caller ID for outbound calls. Click **+ Add number** to add numbers with country code. | | SIP Credential | Dropdown | Yes | Select a saved SIP credential authorizing outbound calls. Click **Create new credentials** to add one. | ### How to Set Up 1. Navigate to **Channels** and click **Add Channel → Voice**. 2. Select **Outbound SIP Trunk for Calls**. 3. Enter a **Name** and optionally a **Description**. 4. Add the **phone number(s)** to use as the outbound caller ID. 5. Select a **SIP Credential** (or create one). 6. Click **Save**. *** ## Credentials Voice channels use **SIP Credentials** to authenticate your SIP trunk. These are stored securely in encrypted form and never exposed in plaintext after saving. Create and manage SIP credentials for your voice trunks Overview of all credential types in Subverse Need to set up a telephony provider? See the integration guides for [Twilio](/integrations/telephony-twilio), [Telnyx](/integrations/telephony-telnyx), and [Plivo](/integrations/telephony-plivo). # WebChat Channel Source: https://docs.subverseai.com/communication-channels/webchat Enable automated chat responses on your website via webhooks and APIs ## Overview A WebChat Channel connects a Chat Agent to your website or application via a webhook endpoint. When a user sends a message through your web chat widget or API integration, Subverse receives it at the configured webhook URL, processes it through the linked Chat Agent, and returns a response. WebChat channels use credentials to secure the webhook connection, stored in encrypted form. **When to use a WebChat Channel:** * You want to embed a chat widget powered by a Subverse agent on your website * You're building a custom chat interface and need to connect it to an AI agent via API * You want to handle chat interactions programmatically through webhooks *** ## How to Set Up 1. Navigate to **Channels** in the left sidebar. 2. Click **Add Channel** and select **WebChat**. 3. Fill in the channel details (see configuration below). 4. Select or create a **WebChat Credential**. 5. Under **Agent Configuration**, link a Chat Agent. 6. Click **Save**. Once saved, send incoming chat messages to the configured webhook URL. The linked Chat Agent will process each message and return a response. *** ## Configuration | Field | Type | Required | Description | | - | - | - | - | | Name | Text | Yes | A friendly name for this channel (e.g. `Website Chat`). | | Description | Text | No | Internal description for this channel. | | Webhook URL | URL | Yes | The endpoint Subverse will use to receive and send chat messages (e.g. `https://example.com/webhook/chat`). | | WebChat Credential | Dropdown | Yes | Select a saved WebChat credential to secure this channel. Click **Create new credentials** to add one under Credentials. | | Chat Agent | Dropdown | No | The Chat Agent that will handle incoming messages on this channel. | *** ## Credentials WebChat channels use credentials to authenticate webhook requests, ensuring only authorized sources can send messages to your channel. Credentials are stored encrypted and never exposed in plaintext after saving. Create and manage your WebChat credentials in the Credentials section # WhatsApp Channel Source: https://docs.subverseai.com/communication-channels/whatsapp Connect your WhatsApp Business account to handle automated chats via a Chat Agent ## Overview A WhatsApp Channel connects your WhatsApp Business number to a Chat Agent. When a customer messages your WhatsApp number, the linked agent receives the message and responds automatically — just like a human agent would. WhatsApp channels use your WhatsApp Business API credentials to authorize sending and receiving messages. These credentials are stored securely in encrypted form. **When to use a WhatsApp Channel:** * You want to automate customer support or FAQs over WhatsApp * You need a conversational agent available 24/7 on WhatsApp * You want to qualify leads or handle bookings via WhatsApp messaging *** ## How to Set Up 1. Navigate to **Channels** in the left sidebar. 2. Click **Add Channel** and select **WhatsApp**. 3. Fill in the channel details (see configuration below). 4. Select or create a **WhatsApp Credential**. 5. Under **Agent Configuration**, link a Chat Agent. 6. Click **Save**. Once saved, messages sent to the configured WhatsApp number are routed to the linked Chat Agent. *** ## Configuration | Field | Type | Required | Description | | - | - | - | - | | Name | Text | Yes | A friendly name for this channel (e.g. `Support WhatsApp`). | | Description | Text | No | Internal description for this channel. | | Number | Phone number | Yes | The WhatsApp Business phone number that will receive messages (with country code). | | WhatsApp Credential | Dropdown | Yes | Select a saved WhatsApp credential to authorize this channel. Click **Create new credentials** to add one under Credentials. | | Chat Agent | Dropdown | No | The Chat Agent that will handle incoming WhatsApp messages. | *** ## Credentials WhatsApp channels require a **WhatsApp API credential** containing your WhatsApp Business API token and configuration. Credentials are stored encrypted and never exposed in plaintext after saving. Create and manage WhatsApp API credentials Overview of all credential types in Subverse # Introduction Source: https://docs.subverseai.com/credentials/overview Complete guide to managing credentials in SubverseAI # Credentials Credentials allow your SubverseAI agents to securely connect to external services and APIs. This section covers all supported credential types and how to configure them. ## Getting Started ### How to Create Credentials 1. Navigate to the **Credentials** section in your SubverseAI dashboard 2. Click **Create New Credential** 3. Select the credential type from the list below 4. Follow the specific setup instructions for that credential type 5. Test the connection to verify it works 6. Save the credential to use it in your workflows ### Credential Security * All credentials are encrypted at rest * Sensitive data is masked in the UI * Credentials can be updated or revoked at any time * Audit logs track credential usage and changes ### Supported Credential Types ## AI & Machine Learning * [OpenAI API](./types/openai-api) - OpenAI API credentials for GPT models * [Google AI API](./types/google-ai-api) - Google AI (Gemini) API credentials ## E-commerce * [Shopify API](./types/shopify-api) - Shopify API credentials * [Shopify OAuth2 API](./types/shopify-oauth2-api) - Shopify OAuth2 API credentials * [Shopify Access Token API](./types/shopify-access-token-api) - Shopify Access Token API credentials ## Database & Storage * [Airtable API](./types/airtable-api) - Airtable API credentials * [Airtable OAuth2 API](./types/airtable-oauth2-api) - Airtable OAuth2 API credentials * [Airtable Token API](./types/airtable-token-api) - Airtable Token API credentials * [S3 Storage](./types/s3-storage) - AWS S3 storage credentials ## Communication * [WhatsApp API](./types/whatsapp-api) - WhatsApp API credentials * [WhatsApp Trigger API](./types/whatsapp-trigger-api) - WhatsApp Trigger API credentials * [SIP Credentials](./types/sip-credentials) - SIP credentials for voice communication ## Authentication Standards * [OAuth2 API](./types/oauth2-api) - Generic OAuth2 API credentials * [JWT Auth](./types/jwt-auth) - JWT authentication credentials ## HTTP Authentication * [HTTP Basic Auth](./types/http-basic-auth) - HTTP Basic authentication * [HTTP Bearer Auth](./types/http-bearer-auth) - HTTP Bearer authentication * [HTTP Header Auth](./types/http-header-auth) - HTTP Header authentication ## Need Help? * Check individual credential type documentation for troubleshooting tips * Use environment-specific credentials for development and production * Contact support for credential-specific questions # Airtable API Credentials Source: https://docs.subverseai.com/credentials/types/airtable-api How to create and configure Airtable API credentials for SubverseAI # Airtable API Credentials Airtable API credentials allow your SubverseAI agents to interact with Airtable bases for database operations and data management. ## Overview Airtable credentials provide access to: * Database operations (CRUD) * Table and record management * Data synchronization * Spreadsheet-like database operations * Collaborative data workflows ## Dashboard Screenshot Airtable Developer Hub *Create API tokens in the [Airtable Developer Hub](https://airtable.com/create/tokens)* ## Steps to Create Airtable API Credentials ### 1. Create Airtable Account 1. Visit [Airtable](https://airtable.com) 2. Sign up or sign in to your account 3. Create or select a workspace ### 2. Generate Personal Access Token 1. Navigate to the [Developer Hub](https://airtable.com/create/tokens) 2. Click **Create new token** 3. Enter a token name (e.g., "SubverseAI Integration") 4. Set permissions: * Select the workspaces to access * Choose scopes (read, create, update, delete) 5. Click **Create token** 6. Copy the token immediately - it won't be shown again ### 3. Get Base and Table IDs 1. Open your Airtable base 2. From the URL, copy the **Base ID** (the part after `https://airtable.com/`) 3. Go to **Help** > **API documentation** 4. Select your base to see table IDs 5. Note the **Table IDs** for tables you want to access ### 4. Add to SubverseAI 1. Go to **Credentials** in your SubverseAI dashboard 2. Click **Create New Credential** 3. Select **Airtable API** from the credential types 4. Enter a name for your credential 5. Fill in the required fields: * **Personal Access Token**: Your Airtable API token * **Base ID** (optional): Default base ID for operations 6. Click **Save Credential** ## Required Fields * **Name**: A descriptive name for your credential * **Personal Access Token**: Your Airtable personal access token * **Base ID** (optional): Default base ID for operations ## Usage Tips * Use specific scopes to limit token permissions * Create separate tokens for different environments * Regularly rotate your access tokens * Use base and table IDs rather than names for reliability ## Troubleshooting **Invalid Token**: Ensure you copied the complete token including the `pat` prefix **Permission Denied**: Check that your token has the required scopes and workspace access **Base Not Found**: Verify the Base ID is correct and you have access to that base **Rate Limit Exceeded**: Airtable has API rate limits - implement retry logic ## Next Steps After creating your Airtable credentials: * Set up data synchronization workflows * Create database automation workflows * Build data import/export processes * Configure real-time data updates * Integrate with other data sources # Airtable OAuth2 API Credentials Source: https://docs.subverseai.com/credentials/types/airtable-oauth2-api How to create and configure Airtable OAuth2 API credentials for SubverseAI # Airtable OAuth2 API Credentials Airtable OAuth2 API credentials allow your SubverseAI agents to authenticate with Airtable using the OAuth2 standard for secure API access. ## Overview Airtable OAuth2 credentials provide access to: * OAuth2-based Airtable API authentication * Automatic token refresh * Secure user-specific access * Enterprise integration * Enhanced security workflows ## Dashboard Screenshot Airtable Developer Hub *Create OAuth2 apps in the [Airtable Developer Hub](https://airtable.com/developers/web/api)* ## Steps to Create Airtable OAuth2 API Credentials ### 1. Create Airtable Account 1. Visit [Airtable](https://airtable.com) 2. Sign up or sign in to your account 3. Navigate to the **Developer Hub** ### 2. Create OAuth2 App 1. Go to **Developer Hub** > **OAuth2** 2. Click **Create new OAuth2 application** 3. Enter application details: * **Name**: Descriptive name (e.g., "SubverseAI OAuth2 Integration") * **Description**: Brief description of your integration * **Logo**: Upload app logo (optional) 4. Configure **Redirect URIs**: * Add your SubverseAI callback URL * Format: `https://your-subverseai-domain.com/oauth/callback` 5. Click **Create application** ### 3. Get OAuth2 Credentials From your app settings, collect: * **Client ID**: Your OAuth2 client identifier * **Client Secret**: Your OAuth2 client secret * **Authorization URL**: Airtable OAuth2 authorization endpoint * **Token URL**: Airtable OAuth2 token endpoint ### 4. Add to SubverseAI 1. Go to **Credentials** in your SubverseAI dashboard 2. Click **Create New Credential** 3. Select **Airtable OAuth2 API** from the credential types 4. Enter a name for your credential 5. Fill in the required fields: * **Client ID**: Your Airtable OAuth2 client ID * **Client Secret**: Your Airtable OAuth2 client secret * **Scope**: Required permissions (e.g., "data.records:read data.records:write") * **Redirect URI**: Your OAuth2 callback URL 6. Click **Test Connection** to verify the credentials work 7. Click **Save Credential** ## Required Fields * **Name**: A descriptive name for your credential * **Client ID**: Your Airtable OAuth2 client ID * **Client Secret**: Your Airtable OAuth2 client secret * **Scope**: Required permissions (space-separated) * **Redirect URI**: OAuth2 callback URL ## Usage Tips * Use specific scopes to limit access to required operations * Test with different workspaces and bases * Monitor token refresh and expiration * Use separate apps for development and production ## Troubleshooting **Invalid Client**: Verify Client ID and Secret are correct **Redirect URI Mismatch**: Ensure the redirect URI matches exactly **Scope Insufficient**: Add required Airtable API scopes **Workspace Access**: Ensure the app has access to target workspaces ## Next Steps After creating your Airtable OAuth2 credentials: * Set up OAuth2 authentication workflows * Configure automatic token refresh * Build workspace-specific integrations * Test different base and table access * Monitor authentication success rates # Airtable Token API Credentials Source: https://docs.subverseai.com/credentials/types/airtable-token-api How to create and configure Airtable Token API credentials for SubverseAI # Airtable Token API Credentials Airtable Token API credentials allow your SubverseAI agents to authenticate with Airtable using personal access tokens for direct API access. ## Overview Airtable Token credentials provide access to: * Direct API access with personal tokens * Simplified authentication flow * Personal workspace integration * High-frequency operations * Development and testing workflows ## Dashboard Screenshot Airtable Developer Hub *Create personal access tokens in the [Airtable Developer Hub](https://airtable.com/create/tokens)* ## Steps to Create Airtable Token API Credentials ### 1. Create Airtable Account 1. Visit [Airtable](https://airtable.com) 2. Sign up or sign in to your account 3. Create or select a workspace ### 2. Generate Personal Access Token 1. Navigate to the [Developer Hub](https://airtable.com/create/tokens) 2. Click **Create new token** 3. Enter token details: * **Name**: Descriptive name (e.g., "SubverseAI Token Integration") * **Scopes**: Select required permissions: * `data.records:read` - Read records * `data.records:write` - Create/update/delete records * `data.bases:read` - Read base information * `schema.bases:read` - Read base schema 4. Select workspaces to grant access to 5. Click **Create token** 6. Copy the token immediately - it won't be shown again ### 3. Get Base Information 1. Open your Airtable base 2. From the URL, copy the **Base ID** 3. Note the **Table IDs** for tables you want to access ### 4. Add to SubverseAI 1. Go to **Credentials** in your SubverseAI dashboard 2. Click **Create New Credential** 3. Select **Airtable Token API** from the credential types 4. Enter a name for your credential 5. Fill in the required fields: * **Personal Access Token**: Your Airtable token (starts with `pat`) * **Base ID** (optional): Default base ID for operations 6. Click **Save Credential** ## Required Fields * **Name**: A descriptive name for your credential * **Personal Access Token**: Your Airtable personal access token * **Base ID** (optional): Default base ID for operations ## Usage Tips * Use specific scopes to limit token permissions * Create separate tokens for different environments * Regularly rotate your access tokens * Use base and table IDs rather than names for reliability ## Troubleshooting **Invalid Token**: Ensure you copied the complete token including the `pat` prefix **Permission Denied**: Check that your token has the required scopes and workspace access **Base Not Found**: Verify the Base ID is correct and you have access to that base **Rate Limit Exceeded**: Airtable has API rate limits - implement retry logic ## Next Steps After creating your Airtable Token credentials: * Set up direct API integration workflows * Configure high-frequency data operations * Build real-time data synchronization * Monitor API usage and performance * Implement token rotation procedures # Email (SMTP / IMAP) Credentials Source: https://docs.subverseai.com/credentials/types/email-smtp How to create and configure Email (SMTP / IMAP) credentials for sending emails from SubverseAI # Email (SMTP / IMAP) Credentials Email (SMTP / IMAP) credentials let SubverseAI send emails through your own mail server or provider. They are used by the [Send Email](/agentverse/nodes/email) node and the [`subverseActions.email.send`](/integrations/agentic-functions/custom-function-actions#email-send) custom function action. *** ## Required Fields | Field | Required | Description | | - | - | - | | **Name** | Yes | A descriptive name for the credential, e.g. `Support Mailbox` | | **Username** | Yes | SMTP/IMAP auth username — usually the email address of the account | | **Password** | Yes | Account password or app-specific password | | **SMTP Host** | Yes | Hostname of the outgoing SMTP server | | **SMTP Port** | Yes | Port for the SMTP server | | **Encryption** | Yes | `SSL/TLS`, `STARTTLS`, or `None` | | **IMAP Host** | No | Hostname of the incoming IMAP server (required only to receive emails) | | **IMAP Port** | No | Port for the IMAP server | *** ## Provider Settings ### Gmail / Google Workspace ``` SMTP Host: smtp.gmail.com SMTP Port: 465 Encryption: SSL/TLS Username: your-address@gmail.com Password: ``` Gmail requires an **App Password** when 2-Factor Authentication is enabled. Generate it in your Google Account → Security → App passwords. ### Outlook / Microsoft 365 ``` SMTP Host: smtp.office365.com SMTP Port: 587 Encryption: STARTTLS Username: your-address@company.com Password: ``` ### Zoho Mail ``` SMTP Host: smtp.zoho.com SMTP Port: 587 Encryption: STARTTLS Username: your-address@zoho.com Password: ``` ### Custom SMTP Server Use the hostname, port, and encryption settings provided by your mail server or hosting provider. *** ## Steps to Create 1. Go to **Settings → Credentials → New Credential** 2. Select **Email (SMTP / IMAP)** 3. Enter a descriptive **Name** 4. Fill in **Username**, **Password**, **SMTP Host**, **SMTP Port**, and **Encryption** 5. Add **IMAP Host** and **IMAP Port** only if the credential will also receive emails 6. Save the credential *** ## Usage Once saved, select this credential in: * [Send Email node](/agentverse/nodes/email) — send emails from an orchestration * [`subverseActions.email.send`](/integrations/agentic-functions/custom-function-actions#email-send) — send emails from a custom function *** ## Troubleshooting **Authentication failed** * Use an app password instead of your regular password for Gmail and similar providers * Verify the username matches the full email address * Check that the encryption type matches the port **Connection timed out** * Confirm the SMTP host and port are correct * Check firewall or network restrictions on port 465/587 **Emails going to spam** * Send from a legitimate business domain * Configure SPF, DKIM, and DMARC records for your domain * Avoid spam-like content and excessive punctuation # Freshdesk API Credentials Source: https://docs.subverseai.com/credentials/types/freshdesk-api How to create and configure Freshdesk API credentials for SubverseAI # Freshdesk API Credentials Freshdesk API credentials allow your SubverseAI agents and orchestrations to interact with your Freshdesk support desk. ## Overview Freshdesk credentials provide access to: * Ticket management (create, read, update, delete) * Ticket notes and replies * Agent, group, product, and company lookups * Support workflow automation ## Steps to Create Freshdesk API Credentials ### 1. Access Your Freshdesk Profile 1. Log in to your Freshdesk account at `https://.freshdesk.com` 2. Click your profile icon in the top-right corner 3. Select **Profile Settings** ### 2. Copy Your API Key 1. In the right-hand panel, find your **API Key** 2. Click the copy icon to copy it to your clipboard Treat your API key like a password. Do not share it or commit it to source control. ### 3. Identify Your Domain Your domain is the subdomain of your Freshdesk URL. For example, if your URL is `https://acme.freshdesk.com`, your domain is `acme`. ### 4. Add to SubverseAI 1. Go to **Credentials** in your SubverseAI dashboard 2. Click **Create New Credential** 3. Select **Freshdesk API** from the credential types 4. Enter a name for your credential 5. Fill in the required fields: * **API Key**: Your Freshdesk API key * **Domain**: Your Freshdesk subdomain (e.g., `acme`) 6. Click **Test Connection** to verify the credentials work 7. Click **Save Credential** ## Required Fields * **Name**: A descriptive name for your credential * **API Key**: Your Freshdesk API key * **Domain**: Your Freshdesk subdomain (without `.freshdesk.com`) ## Usage Tips * Use a dedicated API key per integration so you can revoke access independently * Ensure the agent whose API key you use has permission to manage tickets * The credential supports standard Freshdesk API v2 endpoints ## Troubleshooting **Invalid Domain**: Make sure you enter only the subdomain part. Use `acme` instead of `acme.freshdesk.com`. **Authentication Failed**: Verify that the API key is correct and that the agent account is active. **Permission Denied**: Check that the agent has the required Freshdesk role permissions for ticket operations. ## Next Steps After creating your Freshdesk credentials: * Add a [Freshdesk node](../../agentverse/nodes/freshdesk) to an orchestration * Use Freshdesk actions in [custom functions](../../integrations/agentic-functions/custom-function-actions) * Automate ticket creation from voice, chat, or email agents # Google AI API Credentials Source: https://docs.subverseai.com/credentials/types/google-ai-api How to create and configure Google AI (Gemini) API credentials for SubverseAI # Google AI API Credentials Google AI API credentials allow your SubverseAI agents to access Google's Gemini models and other AI services. ## Overview Google AI credentials provide access to: * Gemini Pro and Gemini Pro Vision models * Text generation and multimodal capabilities * Embedding models for vector search * Google's latest AI models and capabilities ## Dashboard Screenshot Google AI Dashboard *View your API keys in the [Google AI Studio](https://makersuite.google.com/app/apikey)* ## Steps to Create Google AI API Credentials ### 1. Create Google Account 1. Visit [Google AI Studio](https://makersuite.google.com) 2. Sign in with your Google account 3. Accept the terms of service ### 2. Generate API Key 1. Navigate to the [API Keys section](https://makersuite.google.com/app/apikey) 2. Click **Create API Key** 3. Give your API key a descriptive name 4. Copy the generated API key ### 3. Add to SubverseAI 1. Go to **Credentials** in your SubverseAI dashboard 2. Click **Create New Credential** 3. Select **Google AI API** from the credential types 4. Enter a name for your credential (e.g., "Production Google AI") 5. Paste your API key in the **API Key** field 6. Click **Save Credential** ## Required Fields * **Name**: A descriptive name for your credential * **API Key**: Your Google AI API key ## Usage Tips * Use different API keys for development and production environments * Monitor your usage in the Google AI Studio dashboard * Google AI offers generous free tiers for testing * Consider setting up billing for production workloads ## Troubleshooting **Invalid API Key**: Ensure you copied the complete API key from Google AI Studio **Quota Exceeded**: Check your usage limits in the Google AI Studio **Model Not Available**: Some models may be region-restricted or require specific API keys ## Next Steps After creating your Google AI credentials: * Use them in AI workflow nodes for text generation * Set up multimodal workflows with Gemini Pro Vision * Configure embedding models for vector search * Experiment with different Gemini models # Google Sheets API Key Credentials Source: https://docs.subverseai.com/credentials/types/google-sheets-api-key How to create and configure Google Sheets API Key credentials for SubverseAI # Google Sheets API Key Credentials Google Sheets API Key credentials allow your SubverseAI agents to read data from **public** Google Sheets without requiring user authentication. ## Overview Google Sheets API Key credentials provide access to: * Reading data from public spreadsheets * Fetching sheet metadata and values * Accessing publicly shared sheet ranges **API Key only works for public sheets.** It does not support private sheets or any write operations (append, update, delete, create). For private sheets or write access, use the [Google Sheets Service Account](/credentials/types/google-sheets-service-account) or [Google Sheets OAuth2 API](/credentials/types/google-sheets-oauth2-api) credential type instead. ## Dashboard Screenshot Google Cloud Console *Create API keys in the [Google Cloud Console](https://console.cloud.google.com/apis/credentials)* ## Steps to Create Google Sheets API Key Credentials ### 1. Set Up a Google Cloud Project 1. Visit the [Google Cloud Console](https://console.cloud.google.com) 2. Sign in with your Google account 3. Create a new project or select an existing one ### 2. Enable the Google Sheets API 1. Navigate to **APIs & Services** > **Library** 2. Search for **Google Sheets API** 3. Click **Enable** ### 3. Create an API Key 1. Go to **APIs & Services** > [Credentials](https://console.cloud.google.com/apis/credentials) 2. Click **Create Credentials** > **API key** 3. Copy the generated API key (starts with `AIzaSy...`) 4. Optionally, click **Restrict Key** to limit it to the Sheets API only ### 4. Make Your Sheet Public 1. Open the Google Sheet you want to access 2. Click **Share** (top-right) 3. Change access to **Anyone with the link** > **Viewer** 4. Copy the **Spreadsheet ID** from the URL: * URL format: `https://docs.google.com/spreadsheets/d//edit` ### 5. Add to SubverseAI 1. Go to **Credentials** in your SubverseAI dashboard 2. Click **Create New Credential** 3. Select **Google Sheets API Key** from the credential types 4. Enter a name for your credential (e.g., "Public Sheet Access") 5. Fill in the required fields: * **API Key**: Your Google API key 6. Click **Save Credential** ## Required Fields * **Name**: A descriptive name for your credential * **API Key**: Your Google API key from Google Cloud Console ## Usage Tips * Restrict your API key to the Sheets API to reduce exposure risk * Only use this credential type for non-sensitive, public data * For any write operations or private sheets, switch to the Service Account credential ## Troubleshooting **403 Forbidden**: The sheet is not public — change sharing settings to "Anyone with the link" **API Key Invalid**: Verify you copied the full key including the `AIzaSy` prefix **API Not Enabled**: Ensure the Google Sheets API is enabled in your Cloud project **Quota Exceeded**: Google Sheets API has per-day request quotas — check your usage in the Cloud Console ## Next Steps After creating your Google Sheets API Key credentials: * Read data from public spreadsheets in workflows * Build data dashboards and reporting automations * For private sheets, configure [Google Sheets Service Account](/credentials/types/google-sheets-service-account) credentials # Google Sheets OAuth2 API Credentials Source: https://docs.subverseai.com/credentials/types/google-sheets-oauth2-api How to create and configure Google Sheets OAuth2 API credentials for SubverseAI # Google Sheets OAuth2 API Credentials Google Sheets OAuth2 API credentials allow your SubverseAI agents to access Google Sheets using your own Google account through the standard OAuth2 flow. This lets you read and write any spreadsheet your Google account can access — no manual sheet sharing required. ## Overview Google Sheets OAuth2 credentials provide access to: * Reading and writing data on any spreadsheet your Google account can access * Creating new spreadsheets owned by your account * Adding, clearing, and deleting rows * Managing sheets (tabs) within a spreadsheet * Automatic token refresh without manual key rotation OAuth2 credentials access sheets as your Google user, so any spreadsheet you can open in Google Sheets is available — including sheets shared with you by others. Unlike the [Service Account](/credentials/types/google-sheets-service-account) credential, you do not need to share each sheet with a service account email. ## Steps to Create Google Sheets OAuth2 API Credentials ### 1. Set Up a Google Cloud Project 1. Visit the [Google Cloud Console](https://console.cloud.google.com) 2. Sign in with the Google account you want to use for sheet access 3. Create a new project or select an existing one ### 2. Enable the Google Sheets API 1. Navigate to **APIs & Services** > **Library** 2. Search for **Google Sheets API** 3. Click **Enable** ### 3. Configure the OAuth Consent Screen 1. Go to **APIs & Services** > [OAuth consent screen](https://console.cloud.google.com/apis/credentials/consent) 2. Choose **External** (or **Internal** if you are on a Google Workspace organisation) 3. Fill in the required app information: * **App name**: e.g. "SubverseAI Sheets Integration" * **User support email**: your email * **Developer contact email**: your email 4. Click **Save and Continue** 5. On the **Scopes** step, add the `https://www.googleapis.com/auth/spreadsheets` scope 6. Click **Save and Continue** 7. If using **External**, add your own Google account email as a **Test user** on the **Test users** step ### 4. Create OAuth2 Client Credentials 1. Go to **APIs & Services** > [Credentials](https://console.cloud.google.com/apis/credentials) 2. Click **Create Credentials** > **OAuth client ID** 3. Select **Web application** as the application type 4. Enter a name (e.g. "SubverseAI OAuth2 Client") 5. Under **Authorized redirect URIs**, add the SubverseAI callback URL shown in the credential creation form 6. Click **Create** 7. Note the **Client ID** and **Client Secret** displayed on the confirmation page ### 5. Add to SubverseAI 1. Go to **Credentials** in your SubverseAI dashboard 2. Click **Create New Credential** 3. Select **Google Sheets OAuth2 API** from the credential types 4. Enter a name for your credential (e.g. "My Google Account") 5. Fill in the required fields: * **Client ID**: The OAuth client ID from step 4 * **Client Secret**: The OAuth client secret from step 4 6. Click **Connect Account** — you will be redirected to Google to grant access 7. After authorizing, you will be returned to SubverseAI and the credential will be saved ## Required Fields * **Name**: A descriptive name for your credential * **Client ID**: Your Google OAuth2 client ID * **Client Secret**: Your Google OAuth2 client secret ## Usage Tips * Use the narrowest scope that covers your needs. The `spreadsheets` scope grants full read/write access to all sheets your account can reach * For automated, server-to-server access to specific sheets, consider the [Service Account](/credentials/types/google-sheets-service-account) credential instead — it does not require a browser-based consent flow * For read-only access to public sheets, use the [API Key](/credentials/types/google-sheets-api-key) credential * Keep your client secret secure and never commit it to version control ## Troubleshooting **Redirect URI Mismatch**: Ensure the redirect URI in your Google Cloud OAuth client exactly matches the callback URL shown in the SubverseAI credential form **Access Blocked (403 access\_denied)**: If your app is in **Testing** mode, make sure your Google account email is listed under **Test users** on the OAuth consent screen. Alternatively, publish the app from the consent screen **API Not Enabled**: Ensure the Google Sheets API is enabled in the same Cloud project where you created the OAuth client **Invalid Client**: Verify the Client ID and Client Secret were copied correctly from the Google Cloud Console **Token Expired**: SubverseAI automatically refreshes OAuth2 tokens. If refresh fails, reconnect the account from the credential edit page ## Next Steps After creating your Google Sheets OAuth2 credentials: * Read and write data in any spreadsheet your Google account can access * Create new spreadsheets and add sheets programmatically * Build reporting and data sync automations without manual sheet sharing * Use the [Google Sheets node](/agentverse/nodes/google-sheets) in AgentVerse workflows # Google Sheets Service Account Credentials Source: https://docs.subverseai.com/credentials/types/google-sheets-service-account How to create and configure Google Sheets Service Account credentials for SubverseAI # Google Sheets Service Account Credentials Google Sheets Service Account credentials allow your SubverseAI agents to read from and write to Google Sheets — including **private sheets** — using server-to-server authentication. ## Overview Google Sheets Service Account credentials provide access to: * Reading and writing data on private and public spreadsheets * Appending, updating, clearing, and deleting rows * Creating new spreadsheets and adding sheets programmatically * Secure, non-interactive authentication without user login Other Google Sheets credential types are also available: [Google Sheets OAuth2 API](/credentials/types/google-sheets-oauth2-api) (sign in with your Google account) and [Google Sheets API Key](/credentials/types/google-sheets-api-key) (read-only, public sheets only). ## Dashboard Screenshot Google Cloud Console *Create service accounts in the [Google Cloud Console](https://console.cloud.google.com/iam-admin/serviceaccounts)* ## Steps to Create Google Sheets Service Account Credentials ### 1. Set Up a Google Cloud Project 1. Visit the [Google Cloud Console](https://console.cloud.google.com) 2. Sign in with your Google account 3. Create a new project or select an existing one ### 2. Enable the Google Sheets API 1. Navigate to **APIs & Services** > **Library** 2. Search for **Google Sheets API** 3. Click **Enable** ### 3. Create a Service Account 1. Go to **IAM & Admin** > [Service Accounts](https://console.cloud.google.com/iam-admin/serviceaccounts) 2. Click **Create Service Account** 3. Enter a name and description (e.g., "SubverseAI Sheets Integration") 4. Click **Create and Continue** 5. Skip optional role grants for now and click **Done** ### 4. Generate a JSON Key File 1. Click on the service account you just created 2. Go to the **Keys** tab 3. Click **Add Key** > **Create new key** 4. Select **JSON** and click **Create** 5. The key file is downloaded — keep it secure ### 5. Share Your Sheet with the Service Account 1. Open the Google Sheet you want to access 2. Click **Share** 3. Add the service account email (e.g., `service-account@project-id.iam.gserviceaccount.com`) as an **Editor** (or **Viewer** for read-only) 4. Click **Send** ### 6. Add to SubverseAI 1. Go to **Credentials** in your SubverseAI dashboard 2. Click **Create New Credential** 3. Select **Google Sheets Service Account** from the credential types 4. Enter a name for your credential (e.g., "Production Service Account") 5. Fill in the required fields from your JSON key file: * **Service Account Email**: The `client_email` field * **Private Key**: The `private_key` field (including `-----BEGIN PRIVATE KEY-----` header) * **Project ID** (optional): The `project_id` field 6. Click **Save Credential** ## Required Fields * **Name**: A descriptive name for your credential * **Service Account Email**: The `client_email` from your JSON key file * **Private Key**: The `private_key` from your JSON key file ## Optional Fields * **Project ID**: The `project_id` from your JSON key file ## Usage Tips * Grant the service account only the minimum necessary permissions on each sheet * Rotate JSON keys periodically for security * Use separate service accounts for different environments (dev/staging/prod) * Store the downloaded JSON key file securely and never commit it to version control ## Troubleshooting **Permission Denied (403)**: Ensure the sheet has been shared with the service account email **Invalid JWT / Private Key Error**: Verify the `private_key` value includes the full PEM block — newlines must be preserved (use `\n` if pasting inline) **API Not Enabled**: Ensure the Google Sheets API is enabled in your Cloud project **Service Account Not Found**: Confirm the `client_email` value was copied correctly from the JSON key file ## Next Steps After creating your Google Sheets Service Account credentials: * Build data entry and update workflows * Automate report generation and sheet population * Sync CRM or database records to Google Sheets * Set up scheduled data exports and imports # HTTP Basic Auth Credentials Source: https://docs.subverseai.com/credentials/types/http-basic-auth How to create and configure HTTP Basic authentication credentials for SubverseAI # HTTP Basic Auth Credentials HTTP Basic Auth credentials allow your SubverseAI agents to authenticate with web services using the standard HTTP Basic authentication scheme. ## Overview HTTP Basic Auth provides access to: * REST APIs requiring username/password authentication * Legacy web services * Simple authentication schemes * Intranet and internal services * Development and testing endpoints ## Dashboard Screenshot API Service Dashboard *Configure basic auth credentials in your service provider's dashboard* ## Steps to Create HTTP Basic Auth Credentials ### 1. Identify Basic Auth Requirements Check your API documentation to confirm it uses HTTP Basic authentication: * Look for "Basic Authentication" or "HTTP Basic Auth" * Check for username/password requirements * Verify the authentication header format ### 2. Get Authentication Credentials From your service provider, collect: * **Username**: Your API username or client ID * **Password**: Your API password or client secret ### 3. Add to SubverseAI 1. Go to **Credentials** in your SubverseAI dashboard 2. Click **Create New Credential** 3. Select **HTTP Basic Auth** from the credential types 4. Enter a name for your credential 5. Fill in the required fields: * **Username**: Your API username * **Password**: Your API password 6. Click **Save Credential** ## Required Fields * **Name**: A descriptive name for your credential * **Username**: Your API username or client ID * **Password**: Your API password or client secret ## Usage Tips * Use HTTPS endpoints to protect credentials in transit * Create dedicated API users for SubverseAI access * Use strong, unique passwords for each service * Regularly rotate credentials for security ## Troubleshooting **401 Unauthorized**: Verify username and password are correct **Invalid Credentials**: Check for typos and ensure credentials are up-to-date **Connection Failed**: Verify the service URL and network connectivity **Encoding Issues**: Ensure special characters in credentials are properly handled ## Next Steps After creating your HTTP Basic Auth credentials: * Set up authenticated API requests * Configure secure web service integrations * Build authentication testing workflows * Monitor authentication success rates * Implement credential rotation procedures # HTTP Bearer Auth Credentials Source: https://docs.subverseai.com/credentials/types/http-bearer-auth How to create and configure HTTP Bearer authentication credentials for SubverseAI # HTTP Bearer Auth Credentials HTTP Bearer Auth credentials allow your SubverseAI agents to authenticate with web services using Bearer tokens for secure API access. ## Overview HTTP Bearer Auth provides access to: * Modern REST APIs using Bearer tokens * OAuth2 token authentication * JWT token authentication * API key authentication * Secure web service integration ## Dashboard Screenshot API Service Dashboard *Generate bearer tokens in your service provider's dashboard* ## Steps to Create HTTP Bearer Auth Credentials ### 1. Identify Bearer Auth Requirements Check your API documentation to confirm it uses Bearer token authentication: * Look for "Bearer Token" or "Authorization: Bearer" * Check for token-based authentication * Verify the token format and source ### 2. Get Bearer Token From your service provider, collect the bearer token: * **OAuth2 Access Token**: From OAuth2 flow * **JWT Token**: From authentication endpoint * **API Key**: Formatted as Bearer token * **Custom Token**: Provider-specific token ### 3. Add to SubverseAI 1. Go to **Credentials** in your SubverseAI dashboard 2. Click **Create New Credential** 3. Select **HTTP Bearer Auth** from the credential types 4. Enter a name for your credential 5. Fill in the required fields: * **Bearer Token**: Your bearer token * **Header Name**: Header name (default: "Authorization") * **Token Prefix**: Token prefix (default: "Bearer") 6. Click **Save Credential** ## Required Fields * **Name**: A descriptive name for your credential * **Bearer Token**: Your bearer token * **Header Name**: Header name (default: "Authorization") * **Token Prefix**: Token prefix (default: "Bearer") ## Usage Tips * Use HTTPS endpoints to protect tokens in transit * Monitor token expiration and refresh as needed * Store tokens securely and rotate regularly * Use environment-specific tokens for different stages ## Troubleshooting **401 Unauthorized**: Verify bearer token is valid and not expired **Invalid Token Format**: Check token format and encoding **Missing Header**: Ensure header name and prefix are correct **Token Expired**: Refresh or obtain a new token from the provider ## Next Steps After creating your HTTP Bearer Auth credentials: * Set up token-based API integrations * Configure automatic token refresh workflows * Build secure web service connections * Monitor token usage and expiration * Implement token validation and renewal # HTTP Custom Auth Credentials Source: https://docs.subverseai.com/credentials/types/http-custom-auth How to create and configure HTTP Custom authentication credentials for SubVerseAI # HTTP Custom Auth Credentials HTTP Custom Auth credentials allow your SubVerseAI agents to authenticate with web services using a custom JSON definition for headers, query parameters, and body fields. ## Overview HTTP Custom Auth provides access to: * Multi-part authentication schemes * Custom header, query, and body combinations * APIs with non-standard authentication requirements * Flexible authentication definitions in JSON * Advanced integration scenarios ## Dashboard Screenshot API Service Dashboard *Configure custom authentication in your service provider's dashboard* ## Steps to Create HTTP Custom Auth Credentials ### 1. Identify Custom Auth Requirements Check your API documentation to determine the required authentication format: * Look for header, query, and body parameters * Check the exact field names and values * Verify whether values need to be nested * Note any required prefixes or formatting ### 2. Build the Authentication JSON Create a JSON object that defines authentication values for the request: ```json theme={null} { "headers": { "X-API-Key": "your-api-key" }, "body": { "token": "your-token" }, "qs": { "api_key": "your-query-key" } } ``` * **headers**: Custom HTTP headers to include * **body**: Fields to add to the request body * **qs**: Query string parameters to append to the URL ### 3. Add to SubverseAI 1. Go to **Credentials** in your SubverseAI dashboard 2. Click **Create New Credential** 3. Select **HTTP Custom Auth** from the credential types 4. Enter a name for your credential 5. Fill in the required field: * **JSON**: The authentication JSON definition 6. Click **Save Credential** ## Required Fields * **Name**: A descriptive name for your credential * **JSON**: A JSON object defining authentication values for headers, body, and query string ## Usage Tips * Use HTTPS endpoints to protect credentials in transit * Validate your JSON format before saving * Store sensitive values securely and rotate them regularly * Test authentication against the target API endpoint ## Troubleshooting **401 Unauthorized**: Verify the JSON values match the API requirements **Invalid JSON**: Ensure the JSON is well-formed and valid **Missing Field**: Confirm the correct keys (`headers`, `body`, `qs`) are used **Request Format Error**: Check that the API expects headers, body, or query parameters as defined ## Next Steps After creating your HTTP Custom Auth credentials: * Build advanced multi-part authentication workflows * Integrate with non-standard APIs * Test authentication across different request types * Monitor authentication success and failure rates # HTTP Header Auth Credentials Source: https://docs.subverseai.com/credentials/types/http-header-auth How to create and configure HTTP Header authentication credentials for SubverseAI # HTTP Header Auth Credentials HTTP Header Auth credentials allow your SubverseAI agents to authenticate with web services using custom HTTP headers for API access. ## Overview HTTP Header Auth provides access to: * Custom header-based authentication * API key authentication in headers * Service-specific authentication schemes * Legacy system integration * Flexible authentication methods ## Dashboard Screenshot API Service Dashboard *Configure header authentication in your service provider's dashboard* ## Steps to Create HTTP Header Auth Credentials ### 1. Identify Header Auth Requirements Check your API documentation to determine the required header format: * Look for custom header authentication * Check for API key in headers * Verify header name and value format * Note any required prefixes or formats ### 2. Get Header Authentication Details From your service provider, collect: * **Header Name**: The custom header name (e.g., "X-API-Key") * **Header Value**: The authentication value or API key * **Prefix** (optional): Any required prefix (e.g., "Bearer ", "Token ") * **Additional Headers** (optional): Any other required headers ### 3. Add to SubverseAI 1. Go to **Credentials** in your SubverseAI dashboard 2. Click **Create New Credential** 3. Select **HTTP Header Auth** from the credential types 4. Enter a name for your credential 5. Fill in the required fields: * **Header Name**: Your custom header name * **Header Value**: Your authentication value or API key * **Prefix** (optional): Required prefix for the header value 6. Click **Save Credential** ## Required Fields * **Name**: A descriptive name for your credential * **Header Name**: Your custom header name * **Header Value**: Your authentication value or API key * **Prefix** (optional): Required prefix for the header value ## Usage Tips * Use HTTPS endpoints to protect headers in transit * Follow the exact header format specified in API documentation * Store API keys securely and rotate regularly * Use environment-specific credentials for different stages ## Troubleshooting **401 Unauthorized**: Verify header name and value are correct **Missing Header**: Ensure the header name matches API requirements exactly **Invalid Format**: Check for required prefixes or formatting **Case Sensitivity**: Header names are case-insensitive but values may be case-sensitive ## Next Steps After creating your HTTP Header Auth credentials: * Set up custom header-based API integrations * Configure service-specific authentication workflows * Build legacy system connections * Test different header formats and values * Monitor authentication success and failure rates # HTTP Query Auth Credentials Source: https://docs.subverseai.com/credentials/types/http-query-auth How to create and configure HTTP Query authentication credentials for SubVerseAI # HTTP Query Auth Credentials HTTP Query Auth credentials allow your SubVerseAI agents to authenticate with web services by appending a query parameter to the request URL. ## Overview HTTP Query Auth provides access to: * API key authentication in query strings * Token-based URL parameters * Simple third-party API integrations * Services that require `?api_key=` or `?token=` style authentication * Legacy APIs that do not support header-based authentication ## Dashboard Screenshot API Service Dashboard *Configure query authentication in your service provider's dashboard* ## Steps to Create HTTP Query Auth Credentials ### 1. Identify Query Auth Requirements Check your API documentation to determine the required query parameter: * Look for query string authentication * Check the parameter name (e.g., `api_key`, `token`, `key`) * Verify the parameter value format * Note whether the parameter should be URL-encoded ### 2. Get Query Authentication Details From your service provider, collect: * **Parameter Name**: The query parameter name (e.g., `api_key`, `token`) * **Parameter Value**: The authentication value or API key ### 3. Add to SubVerseAI 1. Go to **Credentials** in your SubVerseAI dashboard 2. Click **Create New Credential** 3. Select **HTTP Query Auth** from the credential types 4. Enter a name for your credential 5. Fill in the required fields: * **Name**: The query parameter name * **Value**: The query parameter value 6. Click **Save Credential** ## Required Fields * **Name**: A descriptive name for your credential * **Name**: The query parameter name (e.g., `api_key`) * **Value**: The query parameter value ## Usage Tips * Use HTTPS endpoints to protect query parameters in transit * Avoid using query parameters for highly sensitive credentials when possible * Verify that the API encodes query parameters correctly * Use environment-specific credentials for different stages ## Troubleshooting **401 Unauthorized**: Verify the query parameter name and value are correct **Invalid Parameter**: Check the API documentation for the exact parameter name **Encoding Issues**: Ensure special characters in the value are properly URL-encoded **Parameter Missing**: Confirm the parameter is being appended to the request URL ## Next Steps After creating your HTTP Query Auth credentials: * Set up query-parameter based API integrations * Configure third-party service connections * Test authentication across different endpoints * Monitor authentication success and failure rates # JWT Auth Credentials Source: https://docs.subverseai.com/credentials/types/jwt-auth How to create and configure JWT authentication credentials for SubverseAI # JWT Auth Credentials JWT authentication credentials allow your SubverseAI agents to authenticate with services using JSON Web Tokens for secure API access. ## Overview JWT credentials provide access to: * Modern API services using JWT authentication * Microservices architecture * Stateless authentication systems * Token-based APIs * Secure web services ## Dashboard Screenshot JWT Provider Dashboard *Generate JWT tokens in your service provider's dashboard* ## Steps to Create JWT Auth Credentials ### 1. Identify JWT Requirements Check your API documentation to confirm it uses JWT authentication: * Look for "JWT" or "JSON Web Token" authentication * Check for token endpoint and format requirements * Verify any additional claims needed ### 2. Get JWT Credentials From your service provider, collect: * **JWT Token**: Your JSON Web Token * **Header Name**: Usually "Authorization" (default) * **Token Prefix**: Usually "Bearer" (default) ### 3. Add to SubverseAI 1. Go to **Credentials** in your SubverseAI dashboard 2. Click **Create New Credential** 3. Select **JWT Auth** from the credential types 4. Enter a name for your credential 5. Fill in the required fields: * **JWT Token**: Your JSON Web Token * **Header Name**: Header name for the token (default: "Authorization") * **Token Prefix**: Token prefix (default: "Bearer") 6. Click **Save Credential** ## Required Fields * **Name**: A descriptive name for your credential * **JWT Token**: Your JSON Web Token * **Header Name**: Header name for the token (default: "Authorization") * **Token Prefix**: Token prefix (default: "Bearer") ## Usage Tips * Check token expiration and refresh as needed * Use HTTPS endpoints to protect tokens in transit * Store JWT tokens securely and rotate regularly * Verify token claims match service requirements ## Troubleshooting **Invalid Token**: Verify JWT token is valid and not expired **Malformed Token**: Check token format and encoding **401 Unauthorized**: Ensure token has required claims and permissions **Header Missing**: Verify header name and prefix are correct ## Next Steps After creating your JWT credentials: * Set up JWT-based API integrations * Configure token refresh workflows * Build secure microservice connections * Monitor token expiration and renewal * Implement token validation checks # OpenAI API Credentials Source: https://docs.subverseai.com/credentials/types/openai-api How to create and configure OpenAI API credentials for SubverseAI # OpenAI API Credentials OpenAI API credentials allow your SubverseAI agents to access GPT models and other OpenAI services for AI-powered workflows. ## Overview OpenAI credentials provide access to: * GPT-3.5, GPT-4, and GPT-4 Turbo models * Text completion and chat completion APIs * Embedding models for vector search * Fine-tuning capabilities * DALL-E image generation ## Dashboard Screenshot OpenAI Dashboard *View your OpenAI API keys in the [OpenAI Dashboard](https://platform.openai.com/api-keys)* ## Steps to Create OpenAI API Credentials ### 1. Create OpenAI Account 1. Visit [OpenAI Platform](https://platform.openai.com) 2. Click **Sign up** and create your account 3. Verify your email address ### 2. Generate API Key 1. Navigate to the [API Keys section](https://platform.openai.com/api-keys) 2. Click **Create new secret key** 3. Give your key a descriptive name (e.g., "SubverseAI Production") 4. Copy the secret key immediately - it won't be shown again ### 3. Add to SubverseAI 1. Go to **Credentials** in your SubverseAI dashboard 2. Click **Create New Credential** 3. Select **OpenAI API** from the credential types 4. Enter a name for your credential (e.g., "Production OpenAI") 5. Paste your API key in the **API Key** field 6. Optionally specify an **Organization ID** if you're part of an OpenAI organization 7. Click **Save Credential** ## Required Fields * **Name**: A descriptive name for your credential * **API Key**: Your OpenAI API secret key (starts with `sk-`) * **Organization ID** (optional): Your OpenAI organization ID ## Usage Tips * Use different API keys for development and production environments * Monitor your API usage in the OpenAI dashboard to avoid unexpected charges * Consider setting usage limits in your OpenAI account settings * Rotate your API keys regularly for security ## Troubleshooting **Invalid API Key**: Ensure you copied the full key including the `sk-` prefix **Rate Limit Exceeded**: Check your usage limits in the OpenAI dashboard **Organization Required**: If you're part of an organization, make sure to include the Organization ID ## Next Steps After creating your OpenAI credentials: * Use them in AI workflow nodes for text generation * Set up chat completion workflows * Configure embedding models for vector search * Monitor usage and costs in your SubverseAI dashboard # S3 Storage Credentials Source: https://docs.subverseai.com/credentials/types/s3-storage How to create and configure AWS S3 storage credentials for SubverseAI # S3 Storage Credentials S3 credentials allow your SubverseAI agents to store and retrieve files from Amazon S3 and S3-compatible storage services. ## Overview S3 credentials provide access to: * File storage and retrieval * Bucket management operations * Object upload/download * S3-compatible storage services * Cloud file management workflows ## Dashboard Screenshot AWS Console *Create IAM credentials in the [AWS Console](https://console.aws.amazon.com/iam/)* ## Steps to Create S3 Credentials ### 1. Create AWS Account 1. Visit [AWS Console](https://console.aws.amazon.com) 2. Sign up or sign in to your AWS account 3. Navigate to the IAM service ### 2. Create IAM Policy 1. Go to **Policies** in IAM 2. Click **Create policy** 3. Select **JSON** tab and paste: ```json theme={null} { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:GetObject", "s3:PutObject", "s3:DeleteObject", "s3:ListBucket" ], "Resource": [ "arn:aws:s3:::your-bucket-name", "arn:aws:s3:::your-bucket-name/*" ] } ] } ``` 4. Replace `your-bucket-name` with your actual bucket name 5. Click **Next**, give the policy a name (e.g., "SubverseAI-S3-Access") 6. Click **Create policy** ### 3. Create IAM User 1. Go to **Users** in IAM 2. Click **Create user** 3. Enter a username (e.g., "subverseai-s3-user") 4. Select **Access key - Programmatic access** 5. Click **Next** 6. Attach the policy you created in step 2 7. Click **Next**, **Create user** ### 4. Get Access Keys 1. Copy the **Access key ID** and **Secret access key** 2. Store these securely - you won't see the secret key again ### 5. Add to SubverseAI 1. Go to **Credentials** in your SubverseAI dashboard 2. Click **Create New Credential** 3. Select **S3 Storage** from the credential types 4. Enter a name for your credential 5. Fill in the required fields: * **Access Key ID**: Your AWS access key * **Secret Access Key**: Your AWS secret key * **Region**: AWS region (e.g., `us-east-1`) * **Bucket Name**: Your S3 bucket name * **Endpoint** (optional): For S3-compatible services 6. Click **Save Credential** ## Required Fields * **Name**: A descriptive name for your credential * **Access Key ID**: Your AWS access key ID * **Secret Access Key**: Your AWS secret access key * **Region**: AWS region for your bucket * **Bucket Name**: Your S3 bucket name * **Endpoint** (optional): Custom endpoint for S3-compatible services ## Usage Tips * Use IAM users instead of root account credentials * Grant minimum required permissions only * Use different buckets for different environments * Enable S3 versioning for important data * Configure bucket policies for additional security ## Troubleshooting **Access Denied**: Check IAM permissions and bucket policies **Invalid Credentials**: Verify access key and secret key are correct **Bucket Not Found**: Ensure bucket name is correct and in the right region **Endpoint Error**: For non-AWS S3 services, configure the custom endpoint ## Next Steps After creating your S3 credentials: * Set up file upload/download workflows * Configure automated backups * Build file processing pipelines * Integrate with other cloud storage services * Monitor storage usage and costs # Shopify Access Token API Credentials Source: https://docs.subverseai.com/credentials/types/shopify-access-token-api How to create and configure Shopify Access Token API credentials for SubverseAI # Shopify Access Token API Credentials Shopify Access Token API credentials allow your SubverseAI agents to authenticate with Shopify stores using pre-generated access tokens for direct API access. ## Overview Shopify Access Token credentials provide access to: * Direct API access with access tokens * Private app integration * Custom app development * Simplified authentication flow * High-frequency API operations ## Video Tutorial ## Dashboard Screenshot Shopify Admin Dashboard *Generate access tokens in your [Shopify Admin](https://www.shopify.com/admin)* ## Steps to Create Shopify Access Token API Credentials ### 1. Create Private App 1. Log in to your [Shopify Admin](https://www.shopify.com/admin) 2. Navigate to **Settings** > **Apps** 3. Click **Develop apps** 4. Click **Create a legacy custom app** 5. Enter app name (e.g., "SubverseAI Token Access") 6. Select the app developer 7. Click **Create app** ### 2. Configure Admin API Integration 1. Go to the **Configuration** tab 2. In Admin API integration, Click **Configure** 3. Select the required Admin API access scopes: * `read_products`, `write_products` for product management * `read_orders`, `write_orders` for order processing * Additional scopes as needed 4. Click **Save** ### 3. Install App and Generate Token 1. Click **Install app** 2. Confirm the installation 3. Go to the **API credentials** tab 4. Copy the **Admin API access token** \[Will be generated after app installation and visible only once] 5. Note the **API key** and **API secret key** ### 4. Add to SubverseAI 1. Go to **Credentials** in your SubverseAI dashboard 2. Click **Create New Credential** 3. Select **Shopify Access Token API** from the credential types 4. Enter a name for your credential 5. Fill in the required fields: * **Store URL**: Your Shopify store sub domain * **Access Token**: Your Admin API access token * **API Key**: Your app API key 6. Click **Save Credential** ## Required Fields * **Name**: A descriptive name for your credential * **Store URL**: Your Shopify store sub domain (e.g., `your-store` from `your-store.myshopify.com`) * **Access Token**: Your Admin API access token * **API Key**: Your app API key ## Usage Tips * Use access tokens for high-frequency operations * Store tokens securely and rotate regularly * Monitor API usage to avoid rate limits * Use separate tokens for different environments ## Troubleshooting **Invalid Access Token**: Regenerate the token from the app settings **Store Not Found**: Verify the store URL is correct **Permission Denied**: Check that the app has required Admin API scopes **Rate Limit Exceeded**: Monitor API usage and implement rate limiting ## Next Steps After creating your Shopify Access Token credentials: * Set up direct API integration workflows * Configure high-frequency operations * Build real-time data synchronization * Monitor API usage and performance * Implement token rotation procedures # Shopify API Credentials Source: https://docs.subverseai.com/credentials/types/shopify-api How to create and configure Shopify API credentials for SubverseAI # Shopify API Credentials Shopify API credentials allow your SubverseAI agents to interact with Shopify stores for e-commerce automation and integration. ## Overview Shopify credentials provide access to: * Store management operations * Product and inventory management * Order processing and fulfillment * Customer data management * Analytics and reporting ## Dashboard Screenshot Shopify Dashboard *Create API credentials in your [Shopify Admin](https://www.shopify.com/admin)* ## Steps to Create Shopify API Credentials ### 1. Access Shopify Admin 1. Log in to your [Shopify Admin](https://www.shopify.com/admin) 2. Navigate to **Settings** > **Apps and sales channels** 3. Click **Develop apps** ### 2. Create Custom App 1. Click **Create an app** 2. Enter an app name (e.g., "SubverseAI Integration") 3. Select the app developer (your store owner) 4. Click **Create app** ### 3. Configure Admin API Access 1. Go to the **Configuration** tab 2. Click **Configure Admin API access** 3. Select the required permissions: * `read_products`, `write_products` for product management * `read_orders`, `write_orders` for order processing * `read_customers`, `write_customers` for customer data * `read_inventory`, `write_inventory` for inventory management 4. Click **Save** ### 4. Install App and Get Credentials 1. Go to the **API credentials** tab 2. Click **Install app** 3. Confirm the installation 4. Copy the **API key** and **API secret key** 5. Copy the **Access token** (generated after installation) ### 5. Add to SubverseAI 1. Go to **Credentials** in your SubverseAI dashboard 2. Click **Create New Credential** 3. Select **Shopify API** from the credential types 4. Enter a name for your credential 5. Fill in the required fields: * **Store URL**: Your Shopify store URL (e.g., `mystore.myshopify.com`) * **API Key**: Your app's API key * **API Secret Key**: Your app's API secret key * **Access Token**: The access token generated after installation 6. Click **Save Credential** ## Required Fields * **Name**: A descriptive name for your credential * **Store URL**: Your Shopify store domain * **API Key**: Your Shopify app API key * **API Secret Key**: Your Shopify app API secret * **Access Token**: The access token for API access ## Usage Tips * Grant only the permissions your workflows actually need * Use different apps for development and production * Regularly review and update app permissions * Monitor API usage in your Shopify admin ## Troubleshooting **Invalid Store URL**: Ensure you're using the correct `.myshopify.com` domain **Permission Denied**: Check that your app has the required Admin API permissions **Token Expired**: Regenerate the access token if authentication fails ## Next Steps After creating your Shopify credentials: * Set up product synchronization workflows * Automate order processing and fulfillment * Create customer management automations * Build inventory tracking systems # Shopify OAuth2 API Credentials Source: https://docs.subverseai.com/credentials/types/shopify-oauth2-api How to create and configure Shopify OAuth2 API credentials for SubverseAI # Shopify OAuth2 API Credentials Shopify OAuth2 API credentials allow your SubverseAI agents to authenticate with Shopify stores using the OAuth2 standard for secure API access. ## Overview Shopify OAuth2 credentials provide access to: * OAuth2-based Shopify API authentication * Automatic token refresh * Secure app integration * Multi-store management * Enhanced security workflows ## Dashboard Screenshot Shopify Partners Dashboard *Create OAuth2 apps in the [Shopify Partners Dashboard](https://partners.shopify.com)* ## Steps to Create Shopify OAuth2 API Credentials ### 1. Create Shopify Partners Account 1. Visit [Shopify Partners](https://partners.shopify.com) 2. Create a Partners account or sign in 3. Navigate to **Apps** > **Create app** ### 2. Create OAuth2 App 1. Click **Create app** 2. Select **Build an app** 3. Enter app name (e.g., "SubverseAI OAuth2 Integration") 4. Select the app developer 5. Click **Create app** ### 3. Configure OAuth2 Settings 1. Go to the **Configuration** tab 2. In the **App credentials** section, note: * **API key** (Client ID) * **API secret key** (Client Secret) 3. Set the **Redirection URL** to your SubverseAI callback URL 4. Configure the required Admin API access scopes ### 4. Add to SubverseAI 1. Go to **Credentials** in your SubverseAI dashboard 2. Click **Create New Credential** 3. Select **Shopify OAuth2 API** from the credential types 4. Enter a name for your credential 5. Fill in the required fields: * **Client ID**: Your Shopify app API key * **Client Secret**: Your Shopify app API secret * **Store URL**: Your Shopify store domain * **Scope**: Required permissions (comma-separated) * **Redirect URI**: OAuth2 callback URL 6. Click **Test Connection** to verify the credentials work 7. Click **Save Credential** ## Required Fields * **Name**: A descriptive name for your credential * **Client ID**: Your Shopify app API key * **Client Secret**: Your Shopify app API secret * **Store URL**: Your Shopify store domain * **Scope**: Required permissions (comma-separated) * **Redirect URI**: OAuth2 callback URL ## Usage Tips * Use the minimum required scopes for your use case * Test with development stores before production * Monitor token refresh and expiration * Use separate apps for different environments ## Troubleshooting **Invalid Client**: Verify Client ID and Secret are correct **Redirect URI Mismatch**: Ensure the redirect URI matches exactly **Scope Insufficient**: Add required Admin API scopes **Store Not Found**: Verify the store URL is correct and accessible ## Next Steps After creating your Shopify OAuth2 credentials: * Set up OAuth2 authentication workflows * Configure automatic token refresh * Build multi-store management systems * Test API endpoints and permissions * Monitor authentication success rates # SIP Credentials Source: https://docs.subverseai.com/credentials/types/sip-credentials How to create and configure SIP credentials for SubverseAI voice communication # SIP Credentials SIP credentials allow your SubverseAI agents to make and receive voice calls through SIP trunk providers for voice communication workflows. ## Overview SIP credentials provide access to: * Voice call initiation and reception * SIP trunk integration * VoIP telephony services * Interactive voice response (IVR) systems * Call routing and management ## Dashboard Screenshot SIP Provider Dashboard *Configure SIP accounts in your VoIP provider dashboard* ## Steps to Create SIP Credentials ### 1. Choose a SIP Provider Select a SIP trunk provider that supports your needs: * Twilio * Vonage * Plivo * Telnyx * Or any other SIP-compatible provider ### 2. Create SIP Account 1. Sign up for an account with your chosen provider 2. Navigate to the SIP/voice section 3. Create a new SIP trunk or account 4. Configure your account settings (region, codecs, etc.) ### 3. Get SIP Credentials From your provider dashboard, collect: * **Username**: Your SIP account username (optional for unauthenticated trunks) * **Password**: Your SIP account password (optional for unauthenticated trunks) * **SIP Address**: SIP server address (required for outbound trunks, optional for inbound) ### 4. Add to SubverseAI 1. Go to **Credentials** in your SubverseAI dashboard 2. Click **Create New Credential** 3. Select **SIP Credentials** from the credential types 4. Enter a name for your credential 5. Fill in the fields: * **Username**: Your SIP username (optional for unauthenticated trunks) * **Password**: Your SIP password (optional for unauthenticated trunks) * **SIP Address**: SIP server address (required for outbound trunks, optional for inbound) 6. Click **Save Credential** ## Fields * **Name**: A descriptive name for your credential * **Username**: Your SIP account username (optional for unauthenticated trunks) * **Password**: Your SIP account password (optional for unauthenticated trunks) * **SIP Address**: SIP server address (required for outbound trunks, optional for inbound) **Note**: All fields are optional as SIP credentials can be used for both authenticated and unauthenticated trunks depending on your use case. ## Usage Tips * Use secure SIP (SIPS) with port 5061 for encrypted communications * Configure firewall rules to allow SIP traffic * Test with different codecs for optimal audio quality * Monitor call quality and latency ## Troubleshooting **Connection Failed**: Verify server address, port, and firewall settings **Authentication Failed**: Double-check username and password **Audio Issues**: Check codec compatibility and network bandwidth **Registration Timeout**: Verify server settings and network connectivity ## Next Steps After creating your SIP credentials: * Set up voice call workflows * Configure IVR systems * Build call routing logic * Integrate with AI agents for voice interactions * Monitor call quality and metrics **Note for SIP Type**: After creating SIP credentials, you'll need to configure inbound and outbound trunks to handle call routing. See the [Trunk Configuration](/integrations/telephony) documentation for next steps. # WhatsApp API Credentials Source: https://docs.subverseai.com/credentials/types/whatsapp-api How to create and configure WhatsApp API credentials for SubverseAI messaging # WhatsApp API Credentials WhatsApp API credentials allow AgentVerse nodes and custom function actions to access the Meta WhatsApp Business Cloud API. The credential stores: * **Access Token** — authenticates requests to the Meta Graph API * **Business Account ID** — loads sender phone numbers and approved message templates The sender **Phone Number ID** is not stored in this credential. Select it in the WhatsApp node, or pass it explicitly as `options.phoneNumberId` to a WhatsApp custom function action. ## Dashboard Screenshot Meta Business Suite *Configure WhatsApp API in [Meta Business Suite](https://business.facebook.com)* ## Steps to Create WhatsApp API Credentials ### 1. Create Meta Business Account 1. Visit [Meta Business Suite](https://business.facebook.com) 2. Create a Meta Business account 3. Verify your business information ### 2. Set Up WhatsApp Business Account 1. In Meta Business Suite, navigate to **WhatsApp** 2. Click **Get Started** 3. Register your phone number for WhatsApp Business 4. Verify your phone number ### 3. Create WhatsApp App 1. Go to **Apps** in Meta Business Suite 2. Click **Create App** 3. Select **Business** app type 4. Enter app name (e.g., "SubverseAI WhatsApp") 5. Click **Create App** ### 4. Configure WhatsApp Product 1. In your app dashboard, click **Add Products** 2. Select **WhatsApp** 3. Configure WhatsApp settings: * Choose your WhatsApp Business Account * Set up message templates * Configure webhook URL (optional) ### 5. Get API Credentials 1. In Meta Business Suite, go to **WhatsApp** > **API Setup** 2. Generate or copy your permanent **Access Token** 3. Copy your **WhatsApp Business Account ID** 4. Note the **Phone Number ID** separately; actions require it at execution time ### 6. Add to SubverseAI 1. Go to **Credentials** in your SubverseAI dashboard 2. Click **Create New Credential** 3. Select **WhatsApp API** from the credential types 4. Enter a name for your credential (e.g., Customer Support) 5. Fill in the required fields: * **Access Token**: Your permanent WhatsApp Cloud API access token * **Business Account ID**: Your WhatsApp Business Account ID 6. Click **Save Credential** ## Required Fields * **Name**: A descriptive name for your credential * **Access Token**: Your WhatsApp Cloud API access token * **Business Account ID**: Your WhatsApp Business Account ID ## Usage Tips * Use message templates for outbound messages to comply with WhatsApp policies * Set up webhooks to receive incoming messages in real-time * Monitor message quality metrics in Meta Business Suite * Use different phone numbers for different use cases ## Troubleshooting **Invalid Access Token**: Regenerate the access token in Meta Business Suite **Phone Number Not Verified**: Ensure your WhatsApp Business account is properly verified **Message Template Rejected**: Follow WhatsApp's template guidelines and policies **Webhook Not Working**: Verify webhook URL and SSL certificate ## Usage Once saved, use this credential with: * [WhatsApp Business Cloud node](/agentverse/nodes/whatsapp) * [`subverseActions.whatsapp.sendTextMessage`](/integrations/agentic-functions/custom-function-actions#whatsapp-send-text-message) * [`subverseActions.whatsapp.sendTemplateMessage`](/integrations/agentic-functions/custom-function-actions#whatsapp-send-template-message) * [`subverseActions.whatsapp.sendMediaMessage`](/integrations/agentic-functions/custom-function-actions#whatsapp-send-media-message) Use the separate [WhatsApp Trigger API credential](/credentials/types/whatsapp-trigger-api) for incoming-message trigger webhooks. # WhatsApp OAuth API Credentials Source: https://docs.subverseai.com/credentials/types/whatsapp-trigger-api How to create and configure WhatsApp OAuth API credentials for SubverseAI # WhatsApp OAuth API Credentials WhatsApp OAuth API credentials allow your SubverseAI agents to authenticate with the WhatsApp Business Platform using OAuth client credentials for messaging workflows. ## Overview WhatsApp OAuth API credentials provide access to: * WhatsApp webhook configuration * Message trigger setup * Real-time message reception * Event-driven workflows * Automated response systems ## Dashboard Screenshot Meta Business Suite *Configure webhooks in [Meta Business Suite](https://business.facebook.com)* ## Steps to Create WhatsApp OAuth API Credentials ### 1. Set Up WhatsApp Business Account 1. Visit [Meta Business Suite](https://business.facebook.com) 2. Create or select your WhatsApp Business account 3. Verify your business information and phone number ### 2. Create WhatsApp App 1. Go to **Apps** in Meta Business Suite 2. Click **Create App** 3. Select **Business** app type 4. Enter app name (e.g., "SubverseAI WhatsApp Triggers") 5. Click **Create App** ### 3. Configure WhatsApp Product 1. In your app dashboard, click **Add Products** 2. Select **WhatsApp** 3. Configure WhatsApp settings: * Choose your WhatsApp Business Account * Set up message templates * Configure webhook settings ### 4. Set Up Webhook 1. In WhatsApp settings, go to **Webhooks** 2. Click **Configure** 3. Enter your webhook URL: `https://your-subverseai-domain.com/webhooks/whatsapp` 4. Select webhook events: * **Messages**: Incoming messages * **Message Status**: Delivery and read receipts * **Account Updates**: Account status changes 5. Click **Verify and Save** ### 5. Get OAuth Credentials 1. Go to the [Meta Developer Console](https://developers.facebook.com) 2. Select your WhatsApp Business app 3. Go to **App Settings** > **Basic** 4. Copy the **App ID** as your **Client ID** 5. Copy the **App Secret** as your **Client Secret** ### 6. Add to SubverseAI 1. Go to **Credentials** in your SubverseAI dashboard 2. Click **Create New Credential** 3. Select **WhatsApp OAuth API** from the credential types 4. Enter a name for your credential (e.g., Main WhatsApp) 5. Fill in the required fields: * **Client ID**: Your WhatsApp Business Platform OAuth Client ID from the Meta Developer Console * **Client Secret**: Your WhatsApp Business Platform OAuth Client Secret from the Meta Developer Console 6. Click **Save Credential** ## Required Fields * **Name**: A descriptive name for your credential * **Client ID**: Your WhatsApp Business Platform OAuth Client ID from the Meta Developer Console * **Client Secret**: Your WhatsApp Business Platform OAuth Client Secret for secure authentication ## Usage Tips * Use HTTPS URLs for webhooks * Test webhook endpoints before going live * Monitor webhook delivery and failures * Use message templates for outbound messages * Set up proper error handling for webhook failures ## Troubleshooting **Invalid Client ID or Client Secret**: Verify the App ID and App Secret copied from the Meta Developer Console **Message Not Received**: Check webhook event subscriptions and phone number status **Rate Limit Exceeded**: Monitor message sending rates and implement throttling **Template Rejected**: Follow WhatsApp's message template guidelines ## Next Steps After creating your WhatsApp OAuth API credentials: * Set up real-time message handling workflows * Configure automated response systems * Build customer support automations * Monitor webhook performance and delivery * Test message templates and interactive messages # Getting Started Source: https://docs.subverseai.com/dashboard/getting-started Learn how to access and navigate the SubVerse AI platform ## Accessing the Platform SubVerse AI provides a comprehensive web-based dashboard for managing all aspects of your AI agents and workflows. Access the platform at [dashboard.subverseai.com](https://dashboard.subverseai.com). ## Creating Your Account ### Sign Up Process 1. Navigate to the SubVerse dashboard 2. Click on **Sign Up** if you're a new user 3. Fill in the required information: * **Name**: Your full name * **Email**: Business email address * **Username**: Choose a unique username * **Phone**: Contact number with country code * **Password**: Create a secure password * **Country**: Select your country 4. Accept the Terms & Conditions and Privacy Policy 5. Click **Signup** to create your account You'll receive a verification email to confirm your account. Make sure to check your spam folder if you don't see it in your inbox. ### Logging In For existing users: 1. Go to [dashboard.subverseai.com](https://dashboard.subverseai.com) 2. Enter your **Username/Email** 3. Enter your **Password** 4. Click **Login** to access your dashboard If you've forgotten your password, click on **Forgot password?** to reset it. ## Dashboard Overview Once logged in, you'll see the main dashboard with key metrics and navigation options. ### Navigation Menu The left sidebar provides access to all platform features: **Main Sections:** * **Dashboard**: Overview of your platform metrics and performance * **Agents**: Manage your conversational AI agents * **Call History**: View and analyze all call records * **Workflow**: Build and manage automated workflows * **Reports**: Access detailed analytics and reports * **Integrations**: Configure external integrations * **API Key**: Manage API keys for programmatic access **Additional Resources:** * **API Reference**: Documentation for REST APIs ## Quick Actions From the dashboard, you can quickly: 1. **Create a New Agent**: Click **+ Add Voice Agent** to start building 2. **View Call History**: Monitor recent interactions 3. **Check Performance**: Review metrics and KPIs 4. **Access Integrations**: Configure telephony and tools 5. **Generate Reports**: Export data for analysis ## Dashboard Features ### Real-Time Updates The dashboard updates in real-time, showing: * Active calls in progress * Recent call completions * Agent status changes * System notifications ### Filtering and Search Use the filter options to: * View specific time periods (Last 30 Days, custom ranges) * Filter by agent type * Search for specific calls or agents * Export filtered data ### Responsive Design The dashboard is fully responsive and works on: * Desktop computers * Tablets * Mobile devices (limited functionality) ## Next Steps Now that you're familiar with the dashboard, you can: Learn how to build and configure AI agents Track and analyze call performance Connect telephony and external systems Automate business processes ## Support and Help If you need assistance: * **Documentation**: Browse our comprehensive guides * **Support**: Contact us at [support@subverseai.com](mailto:support@subverseai.com) * **Community**: Join our user community for tips and best practices Keep your login credentials secure and never share your API keys. Enable two-factor authentication for enhanced security. # Platform Overview Source: https://docs.subverseai.com/dashboard/overview Understanding the SubVerse AI Agentic Orchestration Platform ## What is SubVerse AI? SubVerse AI is a comprehensive **Agentic AI Orchestration Platform** designed to empower enterprises with intelligent automation across both client-facing and back-office operations. The platform enables businesses to deploy sophisticated AI agents that can handle complex conversations, execute workflows, and integrate seamlessly with existing systems. ## Platform Capabilities ### Client-Facing Conversational Agents Build intelligent voice and chat agents that can: * Handle customer inquiries with natural, human-like conversations * Access knowledge bases for accurate information retrieval * Execute actions through integrated tools and functions * Transfer to human agents when needed * Support multiple languages and voice options ### Back-Office Automation Agents Orchestrate complex workflows for internal operations: * Automate repetitive business processes * Connect multiple data sources and systems * Execute multi-step workflows with AI decision-making * Process and analyze data at scale * Trigger actions based on business rules ## Core Components Create conversational AI agents for phone-based customer interactions Build automated workflows with AI-powered decision nodes Connect with external systems, databases, and telephony providers Track performance, analyze conversations, and optimize operations ## Getting Started Create your SubVerse account and access the dashboard Choose from templates or build a custom agent Connect your telephony, knowledge bases, and tools Test your agent and deploy to production Track performance and continuously improve Start with a pre-built template to get up and running quickly, then customize based on your specific requirements. ## Platform Architecture SubVerse AI is built on a modern, cloud-native architecture that ensures: * **High Availability**: Multi-region deployment with automatic failover * **Real-time Processing**: Sub-second response times for voice interactions * **Data Privacy**: SOC 2 compliant with data encryption at rest and in transit * **Extensibility**: Open APIs and webhook support for custom integrations ## Next Steps Learn how to navigate and use the SubVerse dashboard Step-by-step guide to building your first AI agent # Overview Source: https://docs.subverseai.com/integrations/agentic-functions Extend your agents with custom logic at every phase of a session Agentic Functions let you hook into an agent's lifecycle at three distinct phases — before a session starts, during an active session, and after a session ends. Each phase gives you different capabilities depending on whether the LLM is involved. ## How Agentic Functions Secure Your Agent SubVerse AI follows a **strict allow-list model** for everything an LLM can do. The LLM only has access to tools you have explicitly attached — it cannot reach outside that boundary. This means: * **No open internet access by default.** Even if the underlying model supports web search or URL fetching, those capabilities are gated. The LLM cannot search the web or retrieve a URL unless you have explicitly added that function to the agent. * **No implicit tool use.** The LLM cannot call any function, fetch any data, or trigger any system unless it has been attached and described in the agent's function configuration. * **Every capability is declared.** Each function you attach comes with a name and description. The LLM reasons over that list to decide what to call and when — it has no visibility into tools that have not been added. **Example:** A Claude-based agent has access to `web_fetch` and `web_search` natively in the underlying model — but those tools are not available to your agent unless you add them under Default Functions. The LLM will not attempt to use them, and SubVerse AI will not execute them, if they are not attached. This model ensures your agents behave exactly as designed, with no unexpected side effects. If you want your agent to search the web, retrieve URLs, execute code, or access any external resource, you must add the corresponding function explicitly. See [Default Functions](/integrations/agentic-functions/default-functions) for the full list of available platform and LLM-native tools. *** ## Session Phases Run before the agent activates. Fetch customer data, validate inputs, or halt execution before a session begins. Functions the LLM can invoke in real time during an active conversation. Run after the session ends. Save transcripts, trigger follow-ups, or sync data to external systems. *** ## Pre-Session Functions Pre-session functions execute **before** the agent is activated, with no LLM involvement. Use them to prepare context for the session — fetch customer records, validate caller data, or conditionally stop the session from launching. **Available function types:** Trigger an asynchronous agent to run preparatory tasks before the session starts. Call your own API or webhook to pre-fetch data, validate customers, or set dynamic variables. **Key capabilities:** * **Dynamic Variables** — Return data from your function in `response.dynamicVariables` to inject real-time context into the agent's prompt. * **Terminate Agent** — Set `response.terminateAgent: true` to cancel the session before the agent connects (e.g., block spam callers or unauthenticated users). The LLM is not active during this phase. LLM-generated parameters are not available in pre-session functions. *** ## During-Session Functions During-session functions are tools the **LLM can call** while it is actively in conversation. These enable real-time actions like fetching order details, transferring calls, or triggering background tasks — all without interrupting the conversation flow. **Available function types:** Built-in platform functions like transferring a call or ending a session. Seamlessly route the conversation to a different specialized agent. Trigger an async agent mid-conversation without blocking the LLM. Call your own API or webhook with LLM-extracted parameters. Explicitly instruct the agent in its system prompt to call a function when needed — for example: *"If the user has no further questions, call `end_call` to hang up."* *** ## Post-Session Functions Post-session functions run **after the session ends**, once the conversation is fully complete. The LLM is no longer active, so `params` (LLM-extracted parameters) are not populated — but the full request body is available, including `analysis`, `dynamicVariables`, `recordingUrl`, `transcript`, and all session metadata. Use the `analysis` field to act on what happened in the session: save summaries to your CRM, trigger follow-up messages, route based on sentiment, or sync data to any external system. **Available function types:** Trigger a follow-up agent to act on the session body after the call ends. Post session data to your own API — read `analysis`, `dynamicVariables`, or `recordingUrl` to drive your logic. `params` is not populated in post-session functions since the LLM is no longer active. Use `analysis` for post-call outcomes (summary, sentiment, custom fields) and `dynamicVariables` for any data carried forward from earlier functions in the session. See the full [session body reference](/integrations/agentic-functions/custom-functions#session-body). # Agent Handoff Source: https://docs.subverseai.com/integrations/agentic-functions/agent-handoff Route an active conversation to a different specialized agent Agent Handoff lets the LLM seamlessly transfer the ongoing session to another agent on your SubVerse workspace. Use it to route customers to the right specialist — for example, escalating from a general support agent to a billing agent — without dropping the conversation. ## How It Works When the LLM determines a handoff is needed (based on your instructions or the conversation context), it calls the handoff function. The session is transferred to the target agent, which picks up with the full conversation context passed along. ## Configuring an Agent Handoff 1. Navigate to **Integrations** → **Agentic Functions** and select your agent. 2. Under **During-Session Functions**, click **+ Add Function** and choose **Agent Handoff**. 3. Select the **Target Agent** to hand off to. 4. Provide a **Description** so the LLM understands when to trigger this handoff (e.g., *"Hand off to the billing agent when the customer asks about invoices or payments"*). 5. Save the function. Write a clear, specific description. The LLM uses the description to decide when to call the handoff function — vague descriptions lead to incorrect or missed handoffs. ## Availability | Phase | Available | | - | - | | Pre-Session | No | | During-Session | Yes | | Post-Session | No | ## Next Steps Trigger async tasks mid-conversation without blocking the LLM Built-in platform actions available to every agent # Background Agent Source: https://docs.subverseai.com/integrations/agentic-functions/background-agent Delegate complex tasks to powerful LLM agents while keeping the customer-facing agent fast A Background Agent is a separate, independently configured agent that handles heavy or complex tasks on behalf of the main communication agent. The main agent — typically a small, fast model — stays focused on the conversation, while background agents running large, capable models do the heavy lifting in parallel. ## How It Works Customer-facing agents need to be fast and responsive. But some tasks — analysing an image, generating a PDF, processing a video, or running complex reasoning — are better suited to large, powerful models like Claude Sonnet or Gemini 2.5 Pro. Running those tasks inline would slow down the entire conversation. Background Agents solve this by separating concerns: * The **main agent** uses a lightweight, low-latency model to talk directly to the customer. * **Background agents** use large, capable models to execute complex tasks in parallel. * The main agent delegates tasks to background agents based on instructions in its prompt, then communicates the outcome back to the customer once available. You can attach multiple background agents to a single main agent — each specialised for a different kind of task. **Example architecture:** ``` Customer ↕ Main Agent (fast model — e.g. GPT-4o mini) ├── Background Agent A: Image Analysis (Claude Sonnet) ├── Background Agent B: Document Generation (Gemini 2.5 Pro) └── Background Agent C: Video Processing (Claude Sonnet) ``` The main agent routes the task to the right background agent based on its prompt. The customer receives a holding response while the background agent works, and the result is returned once ready. ## Use Cases | Task | Background Agent Role | | - | - | | Image analysis | Analyse an uploaded image and return a structured summary | | PDF / document creation | Generate formatted documents from conversation data | | Video processing | Transcribe, summarise, or extract data from a video file | | Complex data reasoning | Run multi-step analysis that would exceed a small model's capability | | Long-context tasks | Process large documents or datasets without impacting conversation latency | ## Configuring a Background Agent 1. Navigate to **Integrations** → **Agentic Functions** and select your agent. 2. Choose the phase where you want to add the background agent (Pre-Session, During-Session, or Post-Session). 3. Click **+ Add Function** and choose **Background Agent**. 4. Select the **Target Background Agent** from your workspace — this is a fully configured agent with its own model, prompt, and tools. 5. Map any input variables that should be passed to the background agent. 6. Save the function. In your main agent's system prompt, explicitly define when and how to delegate to each background agent. For example: *"When the customer uploads an image for analysis, delegate the task to the Image Analysis agent and tell the customer you are processing it."* ## Availability | Phase | Available | | - | - | | Pre-Session | Yes | | During-Session | Yes | | Post-Session | Yes | ### Pre-Session Trigger a background agent before the session starts — for example, use a powerful model to enrich or analyse customer data before the conversation begins, then pass the results back as dynamic variables. ### During-Session The main agent delegates tasks mid-conversation. The customer receives an acknowledgement while the background agent processes the request, keeping conversation latency low regardless of the complexity of the underlying task. ### Post-Session Trigger a background agent after the session ends to act on the full session analysis — for example, generating a detailed report, creating a follow-up document, or running a post-call analysis with a large model. ## Next Steps Call your own API with session or LLM-extracted data Route the active conversation to another agent # Custom Function Actions Source: https://docs.subverseai.com/integrations/agentic-functions/custom-function-actions Built-in actions available to your custom function code — connect to HTTP APIs, Airtable, Google Sheets, WhatsApp, Shopify, and SubVerse agents without writing any integration boilerplate Custom Function Actions are pre-built integrations you can call directly from your custom function code via `subverseActions`. When you build a custom function, you select which actions you want to use and attach the required credentials. The Code Assistant is aware of your selected actions and credentials, so you can describe what you want in plain English and it will generate the correct code for you. Actions that require credentials will prompt you to select a saved credential when you add the action to your function. Credentials are stored securely and injected at runtime — your code never contains secrets. *** ## HTTP Send Request Make an outbound HTTP request to any URL. Supports all standard methods, custom headers, query parameters, and request body. Optionally authenticates using a stored credential. **Compatible credentials:** HTTP Basic Auth, HTTP Bearer Auth, HTTP Header Auth (API Key), HTTP Digest Auth, HTTP Query Auth, HTTP Custom Auth | Parameter | Required | Description | | - | - | - | | `options.method` | Yes | HTTP method: `GET`, `POST`, `PUT`, `PATCH`, `DELETE`, `HEAD`, `OPTIONS` | | `options.url` | Yes | Target URL — must start with `http://` or `https://` | | `options.headers` | No | Array of `{ name, value }` pairs for custom request headers | | `options.query` | No | Array of `{ name, value }` pairs appended as URL query parameters | | `options.body` | No | Request payload — object (auto-serialised as JSON) or raw string | | `credentialId` | No | ID of the saved credential to use | | `options.options.timeout` | No | Request timeout in milliseconds. Default `30000`, max `300000` | | `options.options.followRedirects` | No | Follow 301/302 redirects. Default `true` | | `options.options.ignoreSSL` | No | Bypass SSL certificate validation. Default `false` | | `options.options.responseFormat` | No | Force response format: `autodetect` \| `json` \| `text` \| `base64`. Default `autodetect`. Use `base64` for binary files. | | `options.options.fullResponse` | No | Return `statusCode`, `headers`, and `body` instead of just the body. Default `false` | | `options.options.ignoreResponseCode` | No | Don't throw on 4xx/5xx — handle the error response yourself. Default `false` | ```javascript theme={null} const response = await subverseActions.http.sendRequest({ credentialId: 'CREDENTIAL_ID', //optional options: { method: 'POST', url: 'https://api.example.com/orders', headers: [ { name: 'custom-headers', value: 'custom-value' } ], body: { customerId: body.params.customer_id, status: 'confirmed' }, options: { timeout: 10000, ignoreResponseCode: true // handle 4xx without throwing } } }); // response.responseCode — HTTP status code // response.data — parsed response body // response.message — status text ``` *** ## Airtable List Records Fetch a list of records from an Airtable table. Supports filtering, sorting, field selection, and pagination. | Parameter | Required | Description | | - | - | - | | `credentialId` | Yes | Airtable credential ID | | `options.baseId` | Yes | Airtable Base ID — e.g. `appXXXXXXXXXXXXXX` | | `options.tableIdOrName` | Yes | Table name or table ID — e.g. `tblXXXXXXXXXXXXXX` | | `options.filters.filterByFormula` | No | Airtable formula to filter records | | `options.filters.fields` | No | Array of field names to return. Omit for all fields | | `options.filters.sort` | No | Array of `{ "Field Name": "asc" \| "desc" }` objects | | `options.filters.pageSize` | No | Records per page, max `100` | | `options.filters.maxRecords` | No | Total cap on records returned | | `options.filters.view` | No | Name or ID of a specific view to apply | ```javascript theme={null} const result = await subverseActions.airtable.getRecordList({ credentialId: 'CREDENTIAL_ID', options: { baseId: 'appXXXXXXXXXXXXXX', tableIdOrName: 'Customers', filters: { filterByFormula: `{Email} = '${body.params.email}'`, fields: ['Name', 'Email', 'Status'], pageSize: 10 } } }); // result.records — array of { id, createdTime, fields } const customer = result.records[0]; ``` ## Airtable Get Record by ID Retrieve a single Airtable record by its record ID. | Parameter | Required | Description | | - | - | - | | `credentialId` | Yes | Airtable credential ID | | `options.baseId` | Yes | Airtable Base ID | | `options.tableIdOrName` | Yes | Table name or table ID | | `options.recordId` | Yes | Record ID — e.g. `recXXXXXXXXXXXXXX` | ```javascript theme={null} const record = await subverseActions.airtable.getRecordById({ credentialId: 'CREDENTIAL_ID', options: { baseId: 'appXXXXXXXXXXXXXX', tableIdOrName: 'Orders', recordId: body.params.record_id } }); // record.id, record.createdTime, record.fields ``` ## Airtable Create Record Create one or more records in an Airtable table. Use `fields` for a single record or `records` for bulk creation. | Parameter | Required | Description | | - | - | - | | `credentialId` | Yes | Airtable credential ID | | `options.baseId` | Yes | Airtable Base ID | | `options.tableIdOrName` | Yes | Table name or table ID | | `options.fields` | One of | Field key-value pairs for a single record | | `options.records` | One of | Array of `{ fields: { ... } }` objects for bulk creation | | `options.typecast` | No | Auto-convert strings to match field types. Default `false` | ```javascript theme={null} // Single record const created = await subverseActions.airtable.createRecord({ credentialId: 'CREDENTIAL_ID', options: { baseId: 'appXXXXXXXXXXXXXX', tableIdOrName: 'Leads', fields: { Name: body.params.name, Email: body.params.email, Source: 'Voice Call' } } }); // created.id — new record ID ``` ## Airtable Update Record Update specific fields of an existing Airtable record. Only provided fields are changed; others remain untouched. | Parameter | Required | Description | | - | - | - | | `credentialId` | Yes | Airtable credential ID | | `options.baseId` | Yes | Airtable Base ID | | `options.tableIdOrName` | Yes | Table name or table ID | | `options.recordId` | Yes | Record ID to update | | `options.fields` | Yes | Object of fields to update | | `options.typecast` | No | Auto-convert strings to match field types. Default `false` | ```javascript theme={null} const updated = await subverseActions.airtable.updateRecord({ credentialId: 'CREDENTIAL_ID', options: { baseId: 'appXXXXXXXXXXXXXX', tableIdOrName: 'Orders', recordId: body.params.record_id, fields: { Status: 'Completed', ResolvedAt: new Date().toISOString() } } }); ``` ## Airtable Delete Record Permanently delete a single Airtable record by its record ID. | Parameter | Required | Description | | - | - | - | | `credentialId` | Yes | Airtable credential ID | | `options.baseId` | Yes | Airtable Base ID | | `options.tableIdOrName` | Yes | Table name or table ID | | `options.recordId` | Yes | Record ID to delete | ```javascript theme={null} const result = await subverseActions.airtable.deleteRecord({ credentialId: 'CREDENTIAL_ID', options: { baseId: 'appXXXXXXXXXXXXXX', tableIdOrName: 'TempRecords', recordId: body.params.record_id } }); // result.deleted — true on success ``` *** ## Google Sheets Read Rows Read values from a range in a Google Sheet. Returns a 2D array where each inner array is a row. Optionally filter rows by column values in-memory — no extra API calls needed. **Compatible credentials:** Google Sheets Service Account, Google Sheets OAuth2 API, Google Sheets API Key (public sheets only) | Parameter | Required | Description | | - | - | - | | `credentialId` | No | Required for service account and OAuth2. Optional for API key on public sheets | | `options.spreadsheetId` | Yes | Spreadsheet ID from the URL: `/spreadsheets/d/{spreadsheetId}/` | | `options.range` | Yes | A1 notation range — e.g. `Sheet1!A1:D10` or just `Sheet1` | | `options.valueRenderOption` | No | `FORMATTED_VALUE` (default), `FORMULA`, or `UNFORMATTED_VALUE` | | `options.filters` | No | Array of `{ columnName, value }` filters. The first row of the range is treated as the header row. Only matching data rows are returned | | `options.combineFilters` | No | `AND` (default) requires all filters to match; `OR` requires any filter to match | ```javascript theme={null} const data = await subverseActions.googleSheets.readRows({ credentialId: 'CREDENTIAL_ID', options: { spreadsheetId: 'YOUR_SPREADSHEET_ID', range: 'Customers!A1:D50', valueRenderOption: 'FORMATTED_VALUE' } }); // data.values — 2D array; data.values[0] is usually the header row const headers = data.values[0]; const rows = data.values.slice(1); ``` ### Read Rows with Filtering Filter rows in-memory by column name without making extra API calls. The first row of the range is used as the header row for column name lookup. ```javascript theme={null} // Return only rows where Status = 'Active' const data = await subverseActions.googleSheets.readRows({ credentialId: 'CREDENTIAL_ID', options: { spreadsheetId: 'YOUR_SPREADSHEET_ID', range: 'Customers!A1:D50', filters: [{ columnName: 'Status', value: 'Active' }] } }); // Multiple filters with OR logic const data2 = await subverseActions.googleSheets.readRows({ credentialId: 'CREDENTIAL_ID', options: { spreadsheetId: 'YOUR_SPREADSHEET_ID', range: 'Customers!A1:D50', filters: [ { columnName: 'Status', value: 'Active' }, { columnName: 'Status', value: 'Pending' } ], combineFilters: 'OR' } }); ``` ## Google Sheets Append Rows Append rows to the end of a Google Sheet after the last row with data. Rows can be positional arrays or key-value objects — when objects are used, the executor reads the sheet header and auto-maps values to columns by name. **Compatible credentials:** Google Sheets Service Account, Google Sheets OAuth2 API | Parameter | Required | Description | | - | - | - | | `credentialId` | Yes | Google Sheets credential ID (service account or OAuth2) | | `options.spreadsheetId` | Yes | Spreadsheet ID | | `options.range` | Yes | Sheet name or range — only the sheet name matters for append (e.g. `Sheet1`) | | `options.rows` | Yes | Array of rows to append. Each row is either an array of cell values (positional) or a key-value object whose keys match column header names (auto-mapped) | | `options.valueInputOption` | No | `RAW` (as-is) or `USER_ENTERED` (parsed). Default `USER_ENTERED` | | `options.headerRow` | No | 1-based row number containing column headers. Used only when rows are objects. Default `1` | ```javascript theme={null} const result = await subverseActions.googleSheets.appendRows({ credentialId: 'CREDENTIAL_ID', options: { spreadsheetId: 'YOUR_SPREADSHEET_ID', range: 'Leads', rows: [ [body.params.name, body.params.email, new Date().toISOString()] ] } }); // result.updates.updatedRows — number of rows added ``` ### Append Rows with Auto-Mapping (Object Rows) Pass key-value objects instead of positional arrays. The executor reads the header row and maps each key to the corresponding column automatically. ```javascript theme={null} const result = await subverseActions.googleSheets.appendRows({ credentialId: 'CREDENTIAL_ID', options: { spreadsheetId: 'YOUR_SPREADSHEET_ID', range: 'Leads', rows: [ { Name: body.params.name, Email: body.params.email, CreatedAt: new Date().toISOString() } ] } }); // If the sheet has a title in row 1 and metadata in row 2, set headerRow: 3 const result2 = await subverseActions.googleSheets.appendRows({ credentialId: 'CREDENTIAL_ID', options: { spreadsheetId: 'YOUR_SPREADSHEET_ID', range: 'Leads!A1:Z', rows: [{ Name: 'Alice', Email: 'alice@example.com' }], headerRow: 3 } }); ``` ## Google Sheets Update Rows Overwrite existing rows at a specific range. The data dimensions must match the range provided. Optionally, use `keyColumn` + `keyValue` to find a specific row by column name and update only that row — when combined with object rows, only the provided fields are written (partial update), preserving other column values. **Compatible credentials:** Google Sheets Service Account, Google Sheets OAuth2 API | Parameter | Required | Description | | - | - | - | | `credentialId` | Yes | Google Sheets credential ID (service account or OAuth2) | | `options.spreadsheetId` | Yes | Spreadsheet ID | | `options.range` | Yes | A1 notation range to overwrite — e.g. `Sheet1!A2:C2`. When `keyColumn` is used, this range is read to locate the matching row | | `options.rows` | Yes | Array of rows. Each row is either an array of cell values (positional) or a key-value object (auto-mapped) | | `options.valueInputOption` | No | `RAW` or `USER_ENTERED`. Default `USER_ENTERED` | | `options.headerRow` | No | 1-based row number containing column headers. Default `1` | | `options.keyColumn` | No | When set, finds the first row where this column's value equals `keyValue` and updates only that row | | `options.keyValue` | No | Required when `keyColumn` is set. The value to search for in the key column | ```javascript theme={null} const result = await subverseActions.googleSheets.updateRows({ credentialId: 'CREDENTIAL_ID', options: { spreadsheetId: 'YOUR_SPREADSHEET_ID', range: `Customers!B${body.params.row_number}:C${body.params.row_number}`, rows: [ ['Completed', new Date().toISOString()] ] } }); ``` ### Update Rows with Key-Based Find-and-Update Find a row by column name and value, then update only that row in a single call. No need to read the sheet first or compute row numbers manually. ```javascript theme={null} // Find the row where Email = 'john@example.com' and update the Status column const result = await subverseActions.googleSheets.updateRows({ credentialId: 'CREDENTIAL_ID', options: { spreadsheetId: 'YOUR_SPREADSHEET_ID', range: 'Customers!A1:D50', rows: [{ Status: 'Paid' }], // only update Status, preserve other columns keyColumn: 'Email', keyValue: 'john@example.com' } }); ``` ### Update Rows with Auto-Mapping (Object Rows) When `keyColumn` is not set, object rows are auto-mapped to positional arrays using the sheet header and the entire range is overwritten. ```javascript theme={null} const result = await subverseActions.googleSheets.updateRows({ credentialId: 'CREDENTIAL_ID', options: { spreadsheetId: 'YOUR_SPREADSHEET_ID', range: 'Customers!A2:C2', rows: [{ Name: 'Updated', Email: 'updated@example.com', Status: 'Active' }] } }); ``` ## Google Sheets Append or Update Rows Upsert rows by a lookup column. For each row, if an existing row has a matching value at the lookup column, that row is updated in place; otherwise the row is appended after the last row with data. The lookup column can be specified by index (`lookupColumnIndex`) or by name (`keyColumn`). Rows can be positional arrays or key-value objects that are auto-mapped to columns by header name. **Compatible credentials:** Google Sheets Service Account, Google Sheets OAuth2 API | Parameter | Required | Description | | - | - | - | | `credentialId` | Yes | Google Sheets credential ID (service account or OAuth2) | | `options.spreadsheetId` | Yes | Spreadsheet ID | | `options.range` | Yes | A1 notation range to search and write within (e.g. `Sheet1!A1:D` or `Sheet1`) | | `options.rows` | Yes | Array of rows to upsert. Each row is either an array of cell values (positional) or a key-value object (auto-mapped) | | `options.lookupColumnIndex` | No\* | 0-based column index used to match rows (0 = column A). Either this or `keyColumn` is required | | `options.keyColumn` | No\* | Header name of the column used to match rows (e.g. `Email`). Either this or `lookupColumnIndex` is required | | `options.valueInputOption` | No | `RAW` or `USER_ENTERED`. Default `USER_ENTERED` | | `options.headerRow` | No | 1-based row number containing column headers. Used for `keyColumn` resolution and auto-mapping. Default `1` | \* Either `lookupColumnIndex` or `keyColumn` must be provided. ```javascript theme={null} const result = await subverseActions.googleSheets.appendOrUpdateRows({ credentialId: 'CREDENTIAL_ID', options: { spreadsheetId: 'YOUR_SPREADSHEET_ID', range: 'Customers!A1:D', rows: [ [body.params.email, body.params.name, body.params.phone, 'Active'] ], lookupColumnIndex: 0 // match on column A (email) } }); // result.appendResult — present if new rows were appended // result.updateResults — array of update results for matched rows ``` ### Append or Update with Key Column by Name Use `keyColumn` instead of `lookupColumnIndex` to reference the lookup column by its header name. The executor reads the header row and resolves the index dynamically. ```javascript theme={null} const result = await subverseActions.googleSheets.appendOrUpdateRows({ credentialId: 'CREDENTIAL_ID', options: { spreadsheetId: 'YOUR_SPREADSHEET_ID', range: 'Customers!A1:D', rows: [ { Email: 'john@example.com', Name: 'John', Phone: '555-1234', Status: 'Active' }, { Email: 'jane@example.com', Name: 'Jane', Phone: '555-5678', Status: 'Inactive' } ], keyColumn: 'Email' } }); ``` ### Append or Update with Mixed Batch A single call can update existing rows and append new ones. Rows matching an existing value in the key column are updated; the rest are appended. ```javascript theme={null} const result = await subverseActions.googleSheets.appendOrUpdateRows({ credentialId: 'CREDENTIAL_ID', options: { spreadsheetId: 'YOUR_SPREADSHEET_ID', range: 'Customers!A1:D', rows: [ { Email: 'john@example.com', Name: 'John Updated', Status: 'Active' }, // existing → updated { Email: 'new@example.com', Name: 'New User', Status: 'Pending' } // new → appended ], keyColumn: 'Email' } }); // result.updateResults — array of update results for matched rows // result.appendResult — present if new rows were appended ``` ## Google Sheets Clear Range Clear values from a range in a Google Sheet. Cell values are removed but formatting and data validation rules are preserved. **Compatible credentials:** Google Sheets Service Account, Google Sheets OAuth2 API | Parameter | Required | Description | | - | - | - | | `credentialId` | Yes | Google Sheets credential ID (service account or OAuth2) | | `options.spreadsheetId` | Yes | Spreadsheet ID | | `options.range` | Yes | A1 notation range to clear — e.g. `Sheet1!A1:D10` | ```javascript theme={null} const result = await subverseActions.googleSheets.clearRange({ credentialId: 'CREDENTIAL_ID', options: { spreadsheetId: 'YOUR_SPREADSHEET_ID', range: 'Sheet1!A2:D100' } }); // result.cleared — true on success ``` ## Google Sheets Create Sheet Create a new sheet (tab) within an existing Google Spreadsheet. Returns the new sheet's numeric ID and title. **Compatible credentials:** Google Sheets Service Account, Google Sheets OAuth2 API | Parameter | Required | Description | | - | - | - | | `credentialId` | Yes | Google Sheets credential ID (service account or OAuth2) | | `options.spreadsheetId` | Yes | Spreadsheet to add the sheet to | | `options.title` | Yes | Title for the new tab — must be non-empty and unique | | `options.rowCount` | No | Number of rows. Default `1000` | | `options.columnCount` | No | Number of columns. Default `26` | ```javascript theme={null} const result = await subverseActions.googleSheets.createSheet({ credentialId: 'CREDENTIAL_ID', options: { spreadsheetId: 'YOUR_SPREADSHEET_ID', title: 'February 2025', rowCount: 500, columnCount: 10 } }); // result.sheetId — numeric ID of the new sheet // result.title — the title of the new sheet ``` ## Google Sheets Delete Sheet Permanently delete a sheet (tab) from a Google Spreadsheet by its numeric sheet ID. This action cannot be undone. **Compatible credentials:** Google Sheets Service Account, Google Sheets OAuth2 API | Parameter | Required | Description | | - | - | - | | `credentialId` | Yes | Google Sheets credential ID (service account or OAuth2) | | `options.spreadsheetId` | Yes | Spreadsheet ID | | `options.sheetId` | Yes | Numeric ID of the sheet (tab) to delete | ```javascript theme={null} const result = await subverseActions.googleSheets.deleteSheet({ credentialId: 'CREDENTIAL_ID', options: { spreadsheetId: 'YOUR_SPREADSHEET_ID', sheetId: 1234567890 } }); // result.deleted — true on success ``` ## Google Sheets Delete Rows or Columns Delete one or more ranges of rows or columns from a Google Sheet. Uses 0-based indices — rows or columns after the deleted range shift to fill the gap. Supports deleting multiple non-contiguous ranges in a single request. **Compatible credentials:** Google Sheets Service Account, Google Sheets OAuth2 API | Parameter | Required | Description | | - | - | - | | `credentialId` | Yes | Google Sheets credential ID (service account or OAuth2) | | `options.spreadsheetId` | Yes | Spreadsheet ID | | `options.dimension` | Yes | `ROWS` or `COLUMNS` | | `options.ranges` | Yes | Array of `{ sheetId, startIndex, endIndex }` — at least one required | | `options.ranges[].sheetId` | Yes | Numeric sheet ID (tab ID) | | `options.ranges[].startIndex` | Yes | 0-based index of first row/column to delete (row 1 = index 0) | | `options.ranges[].endIndex` | Yes | 0-based index after the last row/column to delete (must be > startIndex) | ```javascript theme={null} const result = await subverseActions.googleSheets.deleteRowsOrColumns({ credentialId: 'CREDENTIAL_ID', options: { spreadsheetId: 'YOUR_SPREADSHEET_ID', dimension: 'ROWS', ranges: [ { sheetId: 0, startIndex: 2, endIndex: 5 } // deletes rows 3, 4, 5 (1-based) ] } }); // result.deleted — true on success ``` ## Google Sheets Create Spreadsheet Create a new Google Spreadsheet owned by the authenticated account. Requires a title. Returns the new spreadsheet ID and URL. **Compatible credentials:** Google Sheets Service Account, Google Sheets OAuth2 API | Parameter | Required | Description | | - | - | - | | `credentialId` | Yes | Google Sheets credential ID (service account or OAuth2) | | `options.title` | Yes | Spreadsheet title — must be non-empty | | `options.locale` | No | Spreadsheet locale (e.g. `en_US`). Default `en_US` | ```javascript theme={null} const result = await subverseActions.googleSheets.createSpreadsheet({ credentialId: 'CREDENTIAL_ID', options: { title: 'Monthly Sales Report', locale: 'en_US' } }); // result.spreadsheetId — ID of the new spreadsheet // result.spreadsheetUrl — URL to open the spreadsheet in Google Sheets ``` ## Google Sheets Delete Spreadsheet Move a Google Spreadsheet to trash by its ID. Uses the Google Drive API — the spreadsheet is trashed (not permanently destroyed) and can be restored from Google Drive trash. **Compatible credentials:** Google Sheets Service Account, Google Sheets OAuth2 API | Parameter | Required | Description | | - | - | - | | `credentialId` | Yes | Google Sheets credential ID (service account or OAuth2) | | `options.spreadsheetId` | Yes | Spreadsheet ID to delete | ```javascript theme={null} const result = await subverseActions.googleSheets.deleteSpreadsheet({ credentialId: 'CREDENTIAL_ID', options: { spreadsheetId: 'YOUR_SPREADSHEET_ID' } }); // result.deleted — true on success ``` *** ## SubVerse Agents Trigger Voice Call All agent trigger actions authenticate via an `httpHeaderAuth` credential carrying the workspace API key. Set the header name to `x-api-key` and value to your workspace API key. Trigger an outbound voice call to a customer phone number. The call is queued immediately and dispatched by the voice infrastructure. | Parameter | Required | Description | | - | - | - | | `credentialId` | Yes | `httpHeaderAuth` credential with `x-api-key` value | | `options.phoneNumber` | Yes | Customer number in E.164 format — e.g. `+919876543210` | | `options.agentName` | Yes | Name of the agent (use case) to run for this call | | `options.agentNumber` | No | Outbound caller ID. Uses workspace default if omitted | | `options.metadata` | No | Key-value pairs passed into the agent session — use `{{key}}` in prompts | | `options.scheduleTime` | No | ISO 8601 UTC datetime to place the call — e.g. `2025-06-01T09:00:00Z` | | `options.startWorkingHour` | No | Earliest time to call, `HH:MM` format — e.g. `09:00` | | `options.endWorkingHour` | No | Latest time to call, `HH:MM` format — e.g. `18:00` | | `options.timezone` | No | IANA timezone for working hours — e.g. `Asia/Kolkata` | | `options.noOfRetries` | No | Retry count on failure. Default `0` | | `options.callPriority` | No | Queue priority `1` (highest) – `100` (lowest). Default `10` | | `options.options.initialMessage` | No | Opening line spoken when the call connects | | `options.options.additionalContext` | No | Extra prompt instructions for this call only | ```javascript theme={null} const call = await subverseActions.agent.callOutboundTrigger({ credentialId: 'CREDENTIAL_ID', options: { phoneNumber: body.params.phone_number, agentName: 'payment-reminder', metadata: { customerName: body.params.name, amountDue: body.params.amount }, options: { initialMessage: `Hello ${body.params.name}, this is a reminder about your upcoming payment.` }, startWorkingHour: '09:00', endWorkingHour: '18:00', timezone: 'Asia/Kolkata' } }); // call.responseCode — 200 on success // call.data.jobId — queue job ID for tracking ``` ## SubVerse Agents Trigger Chat Message Send a WhatsApp message or start a chat agent session for a customer. | Parameter | Required | Description | | - | - | - | | `credentialId` | Yes | `httpHeaderAuth` credential with `x-api-key` value | | `options.communicationChannel` | Yes | Name of the WhatsApp channel in your workspace | | `options.customerNumber` | Yes | Recipient WhatsApp number in E.164 format | | `options.whatsappOptions.messageType` | No | `say` (verbatim) \| `prompt` (LLM-generated) \| `template`. Default `prompt` | | `options.whatsappOptions.message` | No | Message text — required when `messageType` is `say` | | `options.whatsappOptions.additionalContext` | No | Injected into LLM prompt — used when `messageType` is `prompt` | | `options.whatsappOptions.templateId` | No | WhatsApp template name — required when `messageType` is `template` | | `options.whatsappOptions.templateLanguage` | No | BCP-47 language code for the template (e.g. `en`, `en_US`, `hi`). Default `en` | | `options.whatsappOptions.templateVariables` | No | Key/value pairs substituted into the WhatsApp template body placeholders. Only used when `messageType` is `template` | | `options.metadata` | No | Key-value pairs passed into the agent session | | `options.scheduleTime` | No | ISO 8601 datetime to schedule the send | | `options.agentName` | No | Override the channel's default agent | ```javascript theme={null} const chat = await subverseActions.agent.chatTrigger({ credentialId: 'CREDENTIAL_ID', options: { communicationChannel: 'whatsapp-support', customerNumber: body.params.whatsapp_number, whatsappOptions: { messageType: 'say', message: `Hi ${body.params.name}, your order #${body.params.order_id} has been shipped!` }, metadata: { customerName: body.params.name } } }); // chat.data.sessionId — session ID for the triggered conversation ``` When `messageType` is `template`, provide `templateId`, `templateLanguage`, and `templateVariables` to fill the template's placeholders. `templateVariables` is decoupled from `metadata` — only `templateVariables` is used for template substitution. ```javascript theme={null} const chat = await subverseActions.agent.chatTrigger({ credentialId: 'CREDENTIAL_ID', options: { communicationChannel: 'whatsapp-support', customerNumber: body.params.whatsapp_number, whatsappOptions: { messageType: 'template', templateId: 'order_confirmation', templateLanguage: 'en_US', templateVariables: { customer_name: body.params.name, order_id: body.params.order_id } } } }); ``` ## SubVerse Agents Trigger Email Send an email or start an email agent session for a customer. | Parameter | Required | Description | | - | - | - | | `credentialId` | Yes | `httpHeaderAuth` credential with `x-api-key` value | | `options.communicationChannel` | Yes | Name of the Email channel in your workspace | | `options.customerEmail` | Yes | Recipient email address | | `options.emailOptions.messageType` | No | `say` (verbatim body) \| `prompt` (LLM-generated). Default `prompt` | | `options.emailOptions.subject` | No | Email subject line | | `options.emailOptions.body` | No | Email body (HTML or plain text) — required when `messageType` is `say` | | `options.emailOptions.additionalContext` | No | Injected into LLM prompt — used when `messageType` is `prompt` | | `options.emailOptions.replyTo` | No | Optional sessionId of the existing email session to reply to. When provided, the outbound email is threaded onto that session with the correct In-Reply-To/References, accumulated Cc/Bcc, and quoted context. Omit to start a fresh email thread | | `options.emailOptions.cc` | No | CC recipients — comma-separated | | `options.metadata` | No | Key-value pairs passed into the agent session | | `options.scheduleTime` | No | ISO 8601 datetime to schedule the send | ```javascript theme={null} const email = await subverseActions.agent.emailTrigger({ credentialId: 'CREDENTIAL_ID', options: { communicationChannel: 'email-support', customerEmail: body.params.email, emailOptions: { messageType: 'say', subject: `Your order #${body.params.order_id} is confirmed`, body: `

Hi ${body.params.name},

Thank you for your order. We'll notify you when it ships.

` }, metadata: { customerName: body.params.name } } }); // email.data.sessionId — session ID for the triggered conversation ``` *** ## Email Send Send an email directly through an SMTP server using a saved **Email (SMTP / IMAP)** credential. This action is useful for transactional emails, alerts, and reports from a custom function. **Compatible credentials:** [Email (SMTP / IMAP)](/credentials/types/email-smtp) | Parameter | Required | Description | | - | - | - | | `credentialId` | Yes | Email (SMTP / IMAP) credential ID | | `options.fromEmail` | No | Sender address in `sender@example.com` or `Name ` format. Defaults to the credential username when omitted | | `options.toEmail` | Yes | Recipient email address | | `options.subject` | Yes | Email subject line | | `options.emailFormat` | No | `text`, `html`, or `both`. Default `both` | | `options.text` | No | Plain text body. Provide it when `emailFormat` is `text` or `both` | | `options.html` | No | HTML body. Provide it when `emailFormat` is `html` or `both` | | `options.ccEmail` | No | CC recipient address | | `options.bccEmail` | No | BCC recipient address | | `options.replyTo` | No | Reply-To address | | `options.attachments` | No | Array of `{ fileUrl, fileName? }` objects. `fileUrl` is required and must be a valid URL; `fileName` is optional and is derived from the URL when omitted | | `options.ignoreSSL` | No | Bypass SSL certificate validation. Default `false` | | `options.appendAttribution` | No | Append a "Sent via SubverseAI" footer. Default `false` | ```javascript theme={null} const result = await subverseActions.email.send({ credentialId: 'CREDENTIAL_ID', options: { toEmail: body.params.customer_email, subject: `Your order #${body.params.order_id} is confirmed`, emailFormat: 'both', text: `Hi ${body.params.name}, your order has been confirmed.`, html: `

Hi ${body.params.name},

Your order #${body.params.order_id} is confirmed.

`, attachments: [ { fileUrl: body.params.invoice_url, fileName: 'invoice.pdf' } ] } }); // result.messageId — SMTP message ID // result.accepted — array of accepted addresses // result.rejected — array of rejected addresses ``` *** ## Shopify The Shopify actions below connect to a Shopify store via a saved Shopify credential. All actions support `credentialId` plus an `options` object. **Compatible credentials:** Shopify API Key, Shopify Access Token, Shopify OAuth2 ### Shopify Create Order Create a new order in Shopify. Requires at least one line item. Supports billing/shipping addresses, discount codes, fulfillment options, and email notifications. | Parameter | Required | Description | | - | - | - | | `credentialId` | Yes | Credential ID for the Shopify store | | `options.lineItems` | Yes | Array of line items. Each item requires `quantity`; `variantId`, `productId`, `title`, or `price` are optional | | `options.email` | No | Customer email address | | `options.fulfillmentStatus` | No | `fulfilled`, `null`, `partial`, or `restocked` | | `options.inventoryBehaviour` | No | `bypass`, `decrementIgnoringPolicy`, or `decrementObeyingPolicy` | | `options.locationId` | No | ID of the location that processed the order | | `options.note` | No | Order note | | `options.sendFulfillmentReceipt` | No | Send a shipping confirmation email | | `options.sendReceipt` | No | Send an order confirmation email | | `options.sourceName` | No | Source identifier, e.g. `web` | | `options.tags` | No | Comma-separated tags | | `options.test` | No | Mark as a test order. Default `true` | | `options.billingAddress` | No | Billing address object | | `options.shippingAddress` | No | Shipping address object | | `options.discountCodes` | No | Array of `{ amount, code, type }` discounts | ```javascript theme={null} const order = await subverseActions.shopify.createOrder({ credentialId: 'CREDENTIAL_ID', options: { lineItems: [{ variantId: body.params.variant_id, quantity: 1 }], email: body.params.email, shippingAddress: { firstName: body.params.first_name, lastName: body.params.last_name, city: body.params.city, country: body.params.country }, sendReceipt: true } }); // order.id — new Shopify order ID ``` ### Shopify Get Order Retrieve a single Shopify order by its ID. | Parameter | Required | Description | | - | - | - | | `credentialId` | Yes | Credential ID for the Shopify store | | `options.orderId` | Yes | Numeric ID of the Shopify order | | `options.fields` | No | Comma-separated fields to include in the response | ```javascript theme={null} const order = await subverseActions.shopify.getOrder({ credentialId: 'CREDENTIAL_ID', options: { orderId: body.params.order_id, fields: 'id,email,financial_status' } }); ``` ### Shopify Get All Orders Retrieve a list of Shopify orders with optional filtering and pagination. | Parameter | Required | Description | | - | - | - | | `credentialId` | Yes | Credential ID for the Shopify store | | `options.returnAll` | No | Auto-paginate to fetch all matching orders | | `options.limit` | No | Max orders to return (default `50`, max `250`) | | `options.status` | No | `open`, `closed`, `cancelled`, or `any` | | `options.financialStatus` | No | e.g. `paid`, `pending`, `refunded` | | `options.fulfillmentStatus` | No | e.g. `shipped`, `unshipped`, `partial` | | `options.createdAtMin` / `options.createdAtMax` | No | ISO 8601 datetime range for created at | | `options.updatedAtMin` / `options.updatedAtMax` | No | ISO 8601 datetime range for updated at | | `options.processedAtMin` / `options.processedAtMax` | No | ISO 8601 datetime range for processed at | | `options.sinceId` | No | Return only orders after this ID | | `options.ids` | No | Comma-separated order IDs | | `options.attributionAppId` | No | Filter by attribution app ID | | `options.fields` | No | Comma-separated fields to include | ```javascript theme={null} const orders = await subverseActions.shopify.getAllOrders({ credentialId: 'CREDENTIAL_ID', options: { status: 'open', limit: 50 } }); // orders — array of order objects ``` ### Shopify Update Order Update an existing Shopify order by ID. | Parameter | Required | Description | | - | - | - | | `credentialId` | Yes | Credential ID for the Shopify store | | `options.orderId` | Yes | Numeric ID of the order to update | | `options.email` | No | Updated customer email | | `options.note` | No | Internal note | | `options.tags` | No | Comma-separated tags replacing existing tags | | `options.sourceName` | No | Source identifier | | `options.locationId` | No | Location ID | | `options.shippingAddress` | No | Updated shipping address | ```javascript theme={null} const updated = await subverseActions.shopify.updateOrder({ credentialId: 'CREDENTIAL_ID', options: { orderId: body.params.order_id, note: 'Customer requested expedited handling', tags: 'vip,priority' } }); ``` ### Shopify Delete Order Permanently delete a Shopify order. Only test orders can be deleted via the API. | Parameter | Required | Description | | - | - | - | | `credentialId` | Yes | Credential ID for the Shopify store | | `options.orderId` | Yes | Numeric ID of the order to delete | ```javascript theme={null} const result = await subverseActions.shopify.deleteOrder({ credentialId: 'CREDENTIAL_ID', options: { orderId: body.params.order_id } }); // result.success — true on success ``` ### Shopify Create Product Create a new product in your Shopify store. A title is required. | Parameter | Required | Description | | - | - | - | | `credentialId` | Yes | Credential ID for the Shopify store | | `options.title` | Yes | Product name | | `options.bodyHtml` | No | HTML description | | `options.handle` | No | URL-friendly handle | | `options.productType` | No | Product type category | | `options.publishedAt` | No | ISO 8601 datetime to publish. Set `null` to unpublish | | `options.publishedScope` | No | `global` (Online Store + POS) or `web` (Online Store only) | | `options.tags` | No | Comma-separated tags | | `options.templateSuffix` | No | Liquid template suffix | | `options.vendor` | No | Brand or vendor name | ```javascript theme={null} const product = await subverseActions.shopify.createProduct({ credentialId: 'CREDENTIAL_ID', options: { title: body.params.title, bodyHtml: body.params.description, vendor: body.params.vendor, productType: body.params.product_type } }); // product.id — new Shopify product ID ``` ### Shopify Get Product Retrieve a single Shopify product by its ID. | Parameter | Required | Description | | - | - | - | | `credentialId` | Yes | Credential ID for the Shopify store | | `options.productId` | Yes | Numeric ID of the Shopify product | | `options.fields` | No | Comma-separated fields to include in the response | ```javascript theme={null} const product = await subverseActions.shopify.getProduct({ credentialId: 'CREDENTIAL_ID', options: { productId: body.params.product_id, fields: 'id,title,variants' } }); ``` ### Shopify Get All Products Retrieve a list of Shopify products with optional filtering and pagination. | Parameter | Required | Description | | - | - | - | | `credentialId` | Yes | Credential ID for the Shopify store | | `options.returnAll` | No | Auto-paginate to fetch all matching products | | `options.limit` | No | Max products to return (default `50`, max `250`) | | `options.title` | No | Filter by exact title | | `options.vendor` | No | Filter by vendor | | `options.handle` | No | Filter by handle | | `options.productType` | No | Filter by product type | | `options.status` | No | `active`, `archived`, or `draft` | | `options.publishedStatus` | No | `published`, `unpublished`, or `any` | | `options.ids` | No | Comma-separated product IDs | | `options.sinceId` | No | Return only products after this ID | | `options.createdAtMin` / `options.createdAtMax` | No | ISO 8601 datetime range | | `options.updatedAtMin` / `options.updatedAtMax` | No | ISO 8601 datetime range | | `options.publishedAtMin` / `options.publishedAtMax` | No | ISO 8601 datetime range | | `options.fields` | No | Comma-separated fields to include | ```javascript theme={null} const products = await subverseActions.shopify.getAllProducts({ credentialId: 'CREDENTIAL_ID', options: { vendor: body.params.vendor, status: 'active', limit: 50 } }); // products — array of product objects ``` ### Shopify Update Product Update an existing Shopify product by ID. | Parameter | Required | Description | | - | - | - | | `credentialId` | Yes | Credential ID for the Shopify store | | `options.productId` | Yes | Numeric ID of the product to update | | `options.title` | No | Updated product title | | `options.bodyHtml` | No | Updated HTML description | | `options.handle` | No | Updated URL-friendly handle | | `options.productType` | No | Updated product type | | `options.publishedAt` | No | ISO 8601 datetime. Set `null` to unpublish | | `options.publishedScope` | No | `global` or `web` | | `options.tags` | No | Updated comma-separated tags | | `options.templateSuffix` | No | Updated Liquid template suffix | | `options.vendor` | No | Updated vendor name | ```javascript theme={null} const updated = await subverseActions.shopify.updateProduct({ credentialId: 'CREDENTIAL_ID', options: { productId: body.params.product_id, title: body.params.title, tags: body.params.tags } }); ``` ### Shopify Delete Product Permanently delete a Shopify product by its ID. This cannot be undone. | Parameter | Required | Description | | - | - | - | | `credentialId` | Yes | Credential ID for the Shopify store | | `options.productId` | Yes | Numeric ID of the product to delete | ```javascript theme={null} const result = await subverseActions.shopify.deleteProduct({ credentialId: 'CREDENTIAL_ID', options: { productId: body.params.product_id } }); // result.success — true on success ``` *** ## WhatsApp The WhatsApp actions let you send messages directly through the Meta WhatsApp Business Cloud API using a saved **WhatsApp API** credential. All three actions require a `credentialId`, the recipient's phone number, and your sender's **Phone Number ID** (not stored in the credential — supply it explicitly in `options`). **Compatible credentials:** [WhatsApp API](/credentials/types/whatsapp-api) (`whatsAppApi`, with Access Token and Business Account ID) ### WhatsApp Send Text Message Send a plain text message to a WhatsApp number. | Parameter | Required | Description | | - | - | - | | `credentialId` | Yes | WhatsApp credential ID | | `options.phoneNumberId` | Yes | Your WhatsApp Business sender phone number ID | | `options.to` | Yes | Recipient phone number in E.164 format — e.g. `+919876543210` | | `options.message` | Yes | The text content to send | | `options.previewUrl` | No | Show a URL preview inside the message. Default `false` | ```javascript theme={null} const result = await subverseActions.whatsapp.sendTextMessage({ credentialId: 'CREDENTIAL_ID', options: { phoneNumberId: '1234567890', to: body.params.customer_number, message: `Hi ${body.params.name}, your booking is confirmed for ${body.params.date}.` } }); // result.messages[0].id — WhatsApp message ID // result.contacts[0].wa_id — recipient's WhatsApp ID ``` ### WhatsApp Send Template Message Send an approved WhatsApp message template. Templates must be created and approved in your Meta Business account before use. | Parameter | Required | Description | | - | - | - | | `credentialId` | Yes | WhatsApp credential ID | | `options.phoneNumberId` | Yes | Your WhatsApp Business sender phone number ID | | `options.to` | Yes | Recipient phone number in E.164 format | | `options.templateName` | Yes | Exact name of the approved template | | `options.languageCode` | Yes | Template language code — e.g. `en_US` | | `options.components` | No | Array of component objects to fill template variables. Each object has a `type` (`header`, `body`, or `button`) and `parameters` array | ```javascript theme={null} const result = await subverseActions.whatsapp.sendTemplateMessage({ credentialId: 'CREDENTIAL_ID', options: { phoneNumberId: '1234567890', to: body.params.customer_number, templateName: 'order_shipped', languageCode: 'en_US', components: [ { type: 'body', parameters: [ { type: 'text', text: body.params.order_id }, { type: 'text', text: body.params.tracking_number } ] } ] } }); // result.messages[0].id — WhatsApp message ID ``` ### WhatsApp Send Media Message Send an image, video, audio file, document, or sticker to a WhatsApp number. | Parameter | Required | Description | | - | - | - | | `credentialId` | Yes | WhatsApp credential ID | | `options.phoneNumberId` | Yes | Your WhatsApp Business sender phone number ID | | `options.to` | Yes | Recipient phone number in E.164 format | | `options.mediaType` | Yes | Type of media: `image`, `video`, `audio`, `document`, or `sticker` | | `options.mediaUrl` | One of | Public URL of the media file | | `options.mediaId` | One of | WhatsApp media ID of a previously uploaded file. Provide either `mediaUrl` or `mediaId` | | `options.caption` | No | Caption text shown with the media (supported for `image`, `video`, `document`) | | `options.filename` | No | Display filename shown to the recipient (documents only) | ```javascript theme={null} const result = await subverseActions.whatsapp.sendMediaMessage({ credentialId: 'CREDENTIAL_ID', options: { phoneNumberId: '1234567890', to: body.params.customer_number, mediaType: 'document', mediaUrl: body.params.invoice_url, caption: `Invoice for order #${body.params.order_id}`, filename: `invoice-${body.params.order_id}.pdf` } }); // result.messages[0].id — WhatsApp message ID ``` *** ## Freshdesk The Freshdesk actions connect to your Freshdesk support desk using a saved **Freshdesk API** credential. All actions require a `credentialId` plus an `options` object. **Compatible credentials:** [Freshdesk API](/credentials/types/freshdesk-api) ### Freshdesk Create Ticket Create a new support ticket in Freshdesk. Requires a requester identifier and value. | Parameter | Required | Description | | - | - | - | | `credentialId` | Yes | Freshdesk API credential ID | | `options.requester` | No | Requester identifier: `email`, `facebookId`, `phone`, `requesterId`, `twitterId`, `uniqueExternalId`. Default `requesterId` | | `options.requesterIdentificationValue` | Yes | Value for the selected requester identifier | | `options.status` | No | `open`, `pending`, `resolved`, or `closed`. Default `open` | | `options.priority` | No | `low`, `medium`, `high`, or `urgent`. Default `low` | | `options.source` | No | `chat`, `email`, `feedbackWidget`, `mobileHelp`, `OutboundEmail`, `phone`, or `portal`. Default `portal` | | `options.name` | No | Name of the requester | | `options.subject` | No | Subject of the ticket | | `options.description` | No | HTML content of the ticket | | `options.type` | No | Ticket type, e.g. `Question`, `Incident`, `Problem`, `Feature Request`, `Refund` | | `options.agent` | No | Agent ID to assign the ticket to | | `options.company` | No | Company ID of the requester | | `options.product` | No | Product ID associated with the ticket | | `options.group` | No | Group ID to assign the ticket to | | `options.ccEmails` | No | Comma-separated CC email addresses | | `options.tags` | No | Comma-separated tags | | `options.dueBy` | No | ISO 8601 datetime when the ticket is due | | `options.frDueBy` | No | ISO 8601 datetime when the first response is due | | `options.emailConfigId` | No | Email config ID | ```javascript theme={null} const ticket = await subverseActions.freshdesk.createTicket({ credentialId: 'CREDENTIAL_ID', options: { requester: 'email', requesterIdentificationValue: body.params.customer_email, subject: `Support request from ${body.params.customer_name}`, description: `

${body.params.issue_description}

`, priority: 'high', source: 'phone', type: 'Incident' } }); // ticket.id — new Freshdesk ticket ID ``` ### Freshdesk Get Ticket Retrieve a single Freshdesk ticket by ID. | Parameter | Required | Description | | - | - | - | | `credentialId` | Yes | Freshdesk API credential ID | | `options.ticketId` | Yes | ID of the ticket to retrieve | ```javascript theme={null} const ticket = await subverseActions.freshdesk.getTicket({ credentialId: 'CREDENTIAL_ID', options: { ticketId: body.params.ticket_id } }); ``` ### Freshdesk Get All Tickets List Freshdesk tickets with optional filters and pagination. | Parameter | Required | Description | | - | - | - | | `credentialId` | Yes | Freshdesk API credential ID | | `options.returnAll` | No | Auto-paginate to fetch all matching tickets | | `options.limit` | No | Max tickets to return (default `5`, max `100`) | | `options.companyId` | No | Filter by company ID | | `options.include` | No | Array of related data to include: `company`, `description`, `requester`, `stats` | | `options.order` | No | Sort order: `asc` or `desc`. Default `desc` | | `options.orderBy` | No | Sort by `createdAt`, `dueBy`, or `updatedAt` | | `options.requesterEmail` | No | Filter by requester email address | | `options.requesterId` | No | Filter by requester ID | | `options.updatedSince` | No | ISO 8601 timestamp — tickets updated after this time | ```javascript theme={null} const tickets = await subverseActions.freshdesk.getAllTickets({ credentialId: 'CREDENTIAL_ID', options: { requesterEmail: body.params.customer_email, limit: 10 } }); // tickets — array of ticket objects ``` ### Freshdesk Update Ticket Update an existing Freshdesk ticket by ID. Only provided fields are changed. | Parameter | Required | Description | | - | - | - | | `credentialId` | Yes | Freshdesk API credential ID | | `options.ticketId` | Yes | ID of the ticket to update | | `options.requester` | No | Requester identifier. If provided, `requesterIdentificationValue` is also required | | `options.requesterIdentificationValue` | No | Required when `requester` is provided | | `options.status` | No | `open`, `pending`, `resolved`, or `closed` | | `options.priority` | No | `low`, `medium`, `high`, or `urgent` | | `options.source` | No | `chat`, `email`, `feedbackWidget`, `mobileHelp`, `OutboundEmail`, `phone`, or `portal` | | `options.name` | No | Name of the requester | | `options.subject` | No | Subject of the ticket | | `options.description` | No | HTML content of the ticket | | `options.type` | No | Ticket type | | `options.agent` | No | Agent ID to assign the ticket to | | `options.company` | No | Company ID of the requester | | `options.product` | No | Product ID associated with the ticket | | `options.group` | No | Group ID to assign the ticket to | | `options.ccEmails` | No | Comma-separated CC email addresses | | `options.tags` | No | Comma-separated tags | | `options.dueBy` | No | ISO 8601 datetime when the ticket is due | | `options.frDueBy` | No | ISO 8601 datetime when the first response is due | | `options.emailConfigId` | No | Email config ID | ```javascript theme={null} const updated = await subverseActions.freshdesk.updateTicket({ credentialId: 'CREDENTIAL_ID', options: { ticketId: body.params.ticket_id, status: 'resolved', priority: 'medium' } }); ``` ### Freshdesk Delete Ticket Delete a Freshdesk ticket by ID. | Parameter | Required | Description | | - | - | - | | `credentialId` | Yes | Freshdesk API credential ID | | `options.ticketId` | Yes | ID of the ticket to delete | ```javascript theme={null} const result = await subverseActions.freshdesk.deleteTicket({ credentialId: 'CREDENTIAL_ID', options: { ticketId: body.params.ticket_id } }); // result.success — true on success ``` ### Freshdesk Add Ticket Note Add a reply or private note to a Freshdesk ticket. | Parameter | Required | Description | | - | - | - | | `credentialId` | Yes | Freshdesk API credential ID | | `options.ticketId` | Yes | ID of the ticket to add the note to | | `options.noteBody` | Yes | Content of the note or reply | | `options.private` | No | If `true`, the note is private (internal). Default `false` | | `options.notifyEmails` | No | Comma-separated email addresses to notify | | `options.incoming` | No | Whether the note appears as created from outside the web portal. Default `true` | ```javascript theme={null} const note = await subverseActions.freshdesk.addTicketNote({ credentialId: 'CREDENTIAL_ID', options: { ticketId: body.params.ticket_id, noteBody: `Customer called about ${body.params.issue}. Escalated to L2.`, private: true } }); // note.id — new note ID ``` *** ## Next Steps Write and test custom function code using these actions Set up and manage the credentials used by your actions # Custom Functions Source: https://docs.subverseai.com/integrations/agentic-functions/custom-functions Write code, connect integrations, and call your own logic at any phase of an agent session Custom Functions give you full control over what your agent can do. You can connect to your own API endpoint, use any integration available in AgentVerse, or write custom code directly in the platform — no external server required. And if you've never written code before, that's fine. The built-in **Code Assistant** will write it for you. ## What You Can Do With Custom Functions * **Call your own API or webhook** — POST session data to your backend and return a response. * **Use AgentVerse integrations** — Connect to Shopify, Airtable, Slack, WhatsApp, Freshdesk, and other platforms without writing any integration code yourself. * **Write custom code** — Define exactly what happens using code that runs securely on SubVerse infrastructure. No server needed. *** ## Code Assistant — No Coding Experience Required Writing a custom function is as simple as having a conversation. The **Code Assistant** is built into the function editor. Describe what you want your function to do in plain English, and the Code Assistant writes the code for you — in 5 to 10 minutes. You don't need to know how to code. You don't need to set up a server. Just describe the task, review what it generates, and ship it. **How the Code Assistant works:** 1. Open the function editor and open the Code Assistant panel. 2. Describe what you want the function to do — for example: *"Look up the customer's order status from Shopify using their email, and return the latest order details."* 3. The Code Assistant writes the code, aware of the session body structure and the integrations you have enabled. 4. Review the generated code and request changes by chatting with the assistant. 5. Once satisfied, **request approval**. ### Code Review and Approval Every piece of custom code goes through an automated review before it can run in production. Once you submit for approval, SubVerse AI's code analytics pipeline evaluates the code for safety and correctness and either approves it or returns comments explaining what needs to change — instantly. This keeps your functions secure and your agent stable, without requiring a manual review process. ### Sandbox Testing Once approved, use the **Test** button to run the function in a sandbox environment. You'll see exactly what the function returns — including the full response object — before the agent ever uses it in a live session. This lets you verify the response shape and configure the LLM to interpret it correctly. *** ## Adding Parameters Parameters define the inputs your function receives. During a session, the LLM extracts these values from the conversation and passes them to your function automatically. | Field | Description | | - | - | | **Data Type** | `string`, `number`, or `boolean`. | | **Identifier** | The key name passed to your function (e.g., `customer_email`). | | **Description** | Helps the LLM understand what to extract for this parameter (during-session only). | ## Configuration | Field | Description | | - | - | | **Function Name** | A unique identifier for the function (e.g., `fetch_order_status`). | | **Description** | Explains what the function does. The LLM uses this during-session to decide when to call it. | | **Webhook URL** | Your API endpoint — or leave this empty and use the built-in code editor instead. | | **Error Message** | What the agent says if the function fails (e.g., *"I wasn't able to retrieve that — I'll follow up after the call."*). | | **Return Message** | Used when the function runs in the background (e.g., *"I've sent that request — you'll hear back shortly."*). | | **Background Task** | Toggle on to run the function without blocking the agent's response. Toggle off when the agent needs the result before replying (e.g., fetching order details). | *** ## Session Body Every custom function receives a consistent request body regardless of phase. Use any of these fields inside your function code. ```json theme={null} { "sessionId": "test_session_id", "direction": "inbound", "agentDetails": { "name": "agent_name", "version": "default - v9" }, "userDetails": { "id": "user@example.com", "email": "user@example.com", // For email agent "number": "1234567890" // For chat agent }, "communicationChannelName": "test-channel", "communicationChannelId": "test-channel-id", "threadId": ["message-1", "message-2"], // For email agent "recordingUrl": "https://test.com/recording.mp3", // For voice agents "dynamicVariables": { "currentTime": "2026-04-28T07:13:23.915Z" }, "createdAt": "2026-04-28T07:13:23.915Z", // Session creation date "time": "2026-04-28T07:13:23.915Z", // Last session updation date "params": { }, "analysis": { }, "llmResponse": "" } ``` | Field | Description | | - | - | | `sessionId` | Unique identifier for this session. | | `direction` | `"inbound"` or `"outbound"`. | | `agentDetails.name` | The name of the agent that handled the session. | | `agentDetails.version` | The agent version. Format is one of: `"v9"`, `"draft - v8"`, `"default - v5"`. | | `userDetails.id` | Unique identifier for the customer or user. | | `userDetails.email` | Customer email address. Populated for email agents. | | `userDetails.number` | Customer phone or chat number. Populated for voice and chat agents. | | `communicationChannelName` | The name of the channel the session came through. | | `communicationChannelId` | Unique ID of the communication channel. | | `threadId` | Array of message thread IDs. Populated for email agents. | | `recordingUrl` | URL to the session recording. Populated for voice agents. | | `dynamicVariables` | Variables set by earlier functions in the session — available to every subsequent function. | | `createdAt` | Session creation timestamp in ISO 8601 format. | | `time` | Timestamp of the last session update in ISO 8601 format. | | `params` | LLM-extracted parameters defined for this function. Populated during-session only. | | `analysis` | Post-call analysis data. Populated in post-session functions only. | | `llmResponse` | Optional. Sent in the post-call of a background agent. | *** ## Phase Behaviour ### Pre-Session No LLM is involved. Your function runs before the agent activates. Use it to validate the customer, pre-fetch data, or block the session entirely. Your function can return: ```json theme={null} { "dynamicVariables": { "customer_name": "Jane Smith", "account_tier": "premium", "open_tickets": 2 }, "terminateAgent": false } ``` * **`dynamicVariables`** — Key-value pairs injected into the agent's context and available to all subsequent functions. * **`terminateAgent: true`** — Abort the session before the agent activates. Acts as a security gateway — the LLM is never initialised, so no LLM cost is incurred. Returning `terminateAgent: true` is the recommended way to block unauthorised or invalid sessions. The agent is never started, which also means zero LLM cost for rejected sessions. ### During-Session The LLM calls the function based on the conversation context and its description. LLM-extracted `params` are populated from the conversation. Your function can return `dynamicVariables` to pass data forward to the next function in the chain. If **Background Task** is off, the agent waits for your function's response before replying to the customer — keep response time under 3 seconds for the best experience. ### Post-Session The function runs automatically after the session ends. `analysis` is populated with the full post-call analysis. Use it to write session outcomes to your database, trigger follow-up messages, or update your CRM. *** ## Using Actions in Your Code Custom functions can call built-in actions — HTTP requests, Airtable, Google Sheets, and SubVerse agent triggers — without writing any integration code. Select the actions you need when creating your function, attach the required credentials, and the Code Assistant will use them when generating your code. Browse all available actions with input options and code examples *** ## Next Steps Delegate complex tasks to a powerful model in parallel See all function types and session phases # Default Functions Source: https://docs.subverseai.com/integrations/agentic-functions/default-functions Built-in platform actions and LLM-native tools available to every agent Default functions are pre-built actions provided by SubVerse AI and the underlying LLM provider. They are always available to the LLM during an active session — no webhook or custom code required. Simply enable the ones you need and instruct the agent when to use them. ## Available Default Functions ### Core Platform Functions These functions are available regardless of which LLM you use. | Function | Description | | - | - | | `end_session` | End the session when the conversation is complete. | | `schedule_communication` | Schedule a follow-up call, message, or email for a future time. | | `query_knowledge_base` | Fetch relevant information from the agent's connected knowledge base. | | `fetch_memory` | Retrieve previously stored memory for this customer or session. [Read more](#fetch_memory) | | `update_memory` | Write new information to memory for use in future sessions. [Read more](#update_memory) | ### OpenAI LLM Functions Available when your agent uses an OpenAI model. | Function | Description | | - | - | | `web_search` | Search the web for up-to-date information. | | `code_interpreter` | Execute Python code in a sandboxed environment for calculations, data analysis, or file generation. | ### Claude LLM Functions Available when your agent uses an Anthropic Claude model. | Function | Description | | - | - | | `web_search` | Search the web for up-to-date information. | | `web_fetch` | Retrieve the contents of a specific URL. | | `code_execution` | Run code in a sandboxed environment. | | `bash` | Execute bash commands in a sandboxed environment. | ### Google Gemini LLM Functions Available when your agent uses a Google Gemini model. | Function | Description | | - | - | | `google_search` | Search Google for up-to-date information. | | `url_context` | Retrieve and reason over the contents of a URL. | | `google_maps` | Look up locations, directions, and place information. | | `code_execution` | Run code in a sandboxed environment. | ## When to Use Default Functions Default functions cover the most common actions an agent needs during a session. You do not need to create or configure them — just enable the ones relevant to your use case and instruct the agent in its system prompt when to call them. **Common patterns:** * End the session automatically once the user's query is resolved. * Search the web when the agent needs real-time or external information. * Store customer preferences in memory to personalise future sessions. * Query the knowledge base for product details or policy documents. Be explicit in the agent's system prompt about when to call each function. For example: *"When the customer says goodbye or their issue is resolved, call `end_session`."* or *"Use `web_search` only when the knowledge base does not contain a definitive answer."* ## fetch\_memory `fetch_memory` is a **pre-session** function that retrieves previously stored memory and injects it into the agent's context before the conversation begins. The retrieved memory is placed into a dynamic variable that you define, which you can then reference anywhere in the agent's system prompt. ### How It Works When a session starts, `fetch_memory` looks up the memory stored under the given `memoryId` and makes it available as a dynamic variable named by `paramName`. From that point on, you can reference the memory in your system prompt using the standard double-curly-brace syntax — `{{ paramName }}`. ### Parameters | Parameter | Type | Required | Description | | - | - | - | - | | `memoryId` | string | Yes | ID of the memory to retrieve. Accepts dynamic variables — use a session variable like `{{ claimId }}` or a nested tool body field like `{{ body.userDetails.id }}`. | | `paramName` | string | Yes | Name of the dynamic variable the retrieved memory will be injected into. | `memoryId` supports both top-level session variables (`{{ claimId }}`) and nested tool body paths (`{{ body.userDetails.id }}`). This makes it straightforward to scope memory to the specific customer or entity being passed in the request payload — no extra configuration needed. ### Example ``` // Tool params memoryId: {{ claimId }} paramName: claimMemory // Tool response { "dynamicVariables": { "claimMemory": "Previous conversation memory for this claim..." } } // System prompt usage Here is the previous claim memory which you can refer to if needed: {{ claimMemory }} ``` Memory is **shared across all agents and customers in your workspace**. Always use a customer-specific `memoryId` — such as the customer's user ID or claim ID — to prevent one customer's memory from being accessible to another. If no memory exists for the given `memoryId`, the dynamic variable returns `null`. Handle this gracefully in your system prompt — for example: *"If `{{ claimMemory }}` is empty, treat this as a new customer with no prior history."* *** ## update\_memory `update_memory` is a **post-session** function that extracts key information from the conversation and saves it under a given `memoryId`. If memory already exists at that ID, the function merges the new conversation with the prior memory to produce an updated record — nothing is lost. ### How It Works After the session ends, the LLM reads the full conversation alongside your `prompt` instructions, extracts the relevant information, and writes it to the `memoryId`. If existing memory is found at that ID, it is combined with the new extraction so the stored record stays cumulative across sessions. ### Parameters | Parameter | Type | Required | Description | | - | - | - | - | | `memoryId` | string | Yes | ID under which the memory will be stored. Accepts dynamic variables (e.g. `{{ claimId }}`). | | `prompt` | string | Yes | Instructions telling the LLM what to extract and save from the conversation. This field is required — `update_memory` will not run without it. | ### Example ``` // Tool params memoryId: {{ claimId }} prompt: Store what has been discussed for this claim with dates and issues ``` Be specific in your `prompt`. A vague instruction like *"summarise the conversation"* produces vague memory that is less useful on retrieval. Instead, describe exactly what to capture — dates, decisions, open issues, customer preferences — so the stored memory is immediately actionable next session. *** ## Availability | Function | Pre-Session | During-Session | Post-Session | | - | - | - | - | | `end_session` | No | Yes | No | | `schedule_communication` | No | Yes | No | | `query_knowledge_base` | No | Yes | No | | `fetch_memory` | Yes | No | No | | `update_memory` | No | No | Yes | | LLM-native functions | No | Yes | No | ## Next Steps Route conversations to a specialized agent Add your own API calls for the LLM to execute # API Keys Source: https://docs.subverseai.com/integrations/api-keys API keys to inetgrate with your systems API keys enable secure integration between your AI agent and external applications. 1. Create a New API Key by entering a **Name** and **Description**. 2. The generated API key will be displayed to you only once. 3. Copy and save it securely. You can also copy the key later from API dashboard. # Introduction Source: https://docs.subverseai.com/integrations/introduction Connect your AI agents with external systems and services SubVerse AI provides powerful integration capabilities to connect your AI agents with various external systems, services, and data sources. These integrations enable your agents to access real-time information, perform actions, and communicate through multiple channels. ## Available Integrations Hook into pre-session, during-session, and post-session phases with custom functions, background agents, and handoffs Store and manage documents that your AI agents can reference during interactions Integrate with your telephony system using SIP trunking for inbound and outbound calls Receive real-time event notifications when calls complete or workflows execute Manage secure API keys for integrating your AI agents with external applications ## Getting Started 1. **Choose Your Integration** - Select the integration type that fits your use case 2. **Configure Settings** - Follow the setup guide for your chosen integration 3. **Connect to Agents** - Link the integration to your voice agents or workflows 4. **Test & Deploy** - Verify the integration works as expected before going live Most integrations can be used with both voice agents and workflows, giving you flexibility in how you deploy your AI solutions. # Knowledge Base Source: https://docs.subverseai.com/integrations/knowledge-base Manage your company knowledge base documents The Knowledge Base allows you to store and manage essential documents and information that your AI agents can reference during conversations. ## Create a Knowledge Base 1. Visit Knowledge Base section in your Dashboard and select **Add New** 2. Enter a short, descriptive **name** for your knowledge base (e.g., "Company Policy Manual") ## Add Documents You can either upload documents or input text. Multiple file uploads is also supported. * Click **+ Add Text** to input text manually, make sure to give it short and descriptive name. * Click **+ Add File** to upload relevant documents. ## Save & Manage 1. Once the uploading is complete, the documents will appear under **Selected Files**. 2. Click **Save** to finalize the knowledge base. ## Start Using 1. Once saved, it takes 2-3 minutes to be ready to use. You can click on your knowledge base to check the status on the top right side of the box. 2. Once green dot for ready to use appears, you can either use it in [agent configurations](/agents/agent-configurations#knowledge-base-settings) or [AI Query Agent workflows](/workflow/ai-query-agent-node). # Connect Shopify store Source: https://docs.subverseai.com/integrations/shopify-setup Install SubVerse plugin and add integrate agents with your shopify store ## Install plugin 1. Install SubVerse plugin by visiting [this link](https://apps.shopify.com/) or search for SubVerse AI in [Shopify app store](https://apps.shopify.com/). 2. Grant necessary permissions and proceed with the installation. ## Use Cases Select the use cases you want to use the app for: * **Customer support calls**: Handle incoming calls * **Abandoned checkout or cart**: Capture customers who didn't make payment after checkout * **Abandoned browse**: Capture customers who browsed products but didn't add to cart * **Return request**: Call customers who have raised return request and push for replacement * **Order feedback**: Collect order feedback after fulfillment * **Resolve negative review**: Contact customers who have given bad public review and try to resolve the issue * **COD confirmation**: Confirm availability and interest before delivery for COD orders You can also create your own use cases from SubVerse dashboard. ## Setup voice agents Customize voice agents as per your use cases, branding guidelines, product types, SOPs, etc.\ Refer to this [quickstarter](/dashboard/getting-started) on how to setup your voice agents, telephony, and API key in just 10 minutes. ## Configure Shopify workflows Once you have obtained a phone number, API key, and customized voiec agents on SubVerse interface, you will need to setup workflows to trigger actions based on customer behavior such as cart drop, order placement, reviews. Below is the list of SubVerse templates, you can either search them or just click on the hyperlink: * [SubVerse Recover abandoned checkout](https://admin.shopify.com/store/voicebottest/apps/flow/editor/templates/) * [SubVerse Convert abandoned product browse](https://admin.shopify.com/store/voicebottest/apps/flow/editor/templates/) * [SubVerse Recover abandoned cart](https://admin.shopify.com/store/voicebottest/apps/flow/editor/templates/) * [SubVerse COD confirmation](https://admin.shopify.com/store/voicebottest/apps/flow/editor/templates/) * [SubVerse Collect feedback](https://admin.shopify.com/store/voicebottest/apps/flow/editor/templates/) * [SubVerse Negative Review feedback](https://admin.shopify.com/store/voicebottest/apps/flow/editor/templates/) * [SubVerse Resolve Return request](https://admin.shopify.com/store/voicebottest/apps/flow/editor/templates/) 1. Install these workflow templates one by one. 2. For every workflow, click **Edit** and select the last block **Send HTTP Request** 3. Enter `API key` as value in **Headers** section besides `x-api-key`. 4. In **Body** section, enter `your virtual number` in `botNumber` and update `useCase` name if necessary. Best practices for agent prompting and other settings Take more actions by setting up workflow automation See transcripts, recordings, analysis of agent-customer interactions API docs to trigger calls from Shopify and other external platforms. # Telephony: Inbound and Outbound Calls Source: https://docs.subverseai.com/integrations/telephony Integrate with your telephony system using SIP trunk Integrate your telephony system with SIP trunking to handle inbound and outbound calls through your voice agent. ## Provider-Specific Configuration Guides For detailed step-by-step instructions on configuring SIP trunks with specific providers: Complete Twilio SIP trunk setup guide Complete Telnyx SIP trunk setup guide Complete Plivo SIP trunk setup guide ## Outbound trunk Setup your voice agent to make outgoing calls from your number. ### Create a SIP trunk 1. Buy a virtual number from your cloud telephony service provider. 2. There are 2 methods for authentication: IP whitelisting, or auth credentials. 3. Currently SubVerse SIP server does not have a static IP, so if you opt for the IP route, you need to whitelist all the IP addresses in the range like this: `0.0.0.0/1`, `128.0.0.0/1`. 4. It is recommended that you also setup Auth Username and Password for secure communication. 5. For detailed provider-specific instructions, see our configuration guides for [Twilio](/integrations/telephony-twilio), [Telnyx](/integrations/telephony-telnyx), or [Plivo](/integrations/telephony-plivo). ### Link to the voice agent 1. Provide a **Name** for the connection. 2. Input the **Phone Number** with country code. 3. Select your **SIP Credentials** from the dropdown menu. These credentials contain the SIP address and authentication details needed for the trunk. * [Learn how to create SIP credentials](/credentials/types/sip-credentials) * All credential fields are **encrypted** for security 4. You can start using this number for making calls through voice agents interface, workflows, or call APIs. ## Inbound trunk Setup your voice agent to accept incoming calls on your number. ### Create a SIP trunk 1. Buy a virtual number from your cloud telephony service provider. 2. Get your **Origination URI** from the SubVerse Telephony dashboard (it will look like: `sip:xxxxx.sip.livekit.cloud`). 3. Configure an inbound SIP trunk in your provider's dashboard using the Origination URI from SubVerse. 4. It is recommended that you also setup Auth Username and Password for secure communication. 5. For detailed provider-specific instructions, see our configuration guides for [Twilio](/integrations/telephony-twilio), [Telnyx](/integrations/telephony-telnyx), or [Plivo](/integrations/telephony-plivo). Use `xxxxxxxxx.india.sip.livekit.cloud` for region pinning to India SIP servers. ### Link to the voice agent 1. Provide a **Name** for the connection. 2. Input the **Phone Number** with country code. 3. Select your **SIP Credentials** from the dropdown menu. These credentials contain the authentication details needed for the trunk. * [Learn how to create SIP credentials](/credentials/types/sip-credentials) * All credential fields are **encrypted** for security 4. Configure voice agent mapping (optional): * **Agent**: Select the voice agent you want to use while accepting calls * **Agent Version**: Choose version number or use "default"/"draft" (defaults to "default") Every time you remove and again map the voice agent use case, make sure to map it again to the number to ensure it has the updated context and settings. ## Troubleshooting ### Credential Selection Issues **No SIP credentials appear in dropdown** * Ensure you have [created SIP credentials](/credentials/types/sip-credentials) first * Check that your credentials have been saved successfully * Verify you have the necessary permissions to access credentials **Selected credentials not working** * Test your SIP credentials in the [Credentials section](/credentials/overview) * Verify the SIP address and authentication details are correct * Check if your SIP provider account is active and properly configured **Connection failed after selecting credentials** * Verify network connectivity to your SIP provider * Check firewall settings allow SIP traffic (ports 5060/5061) * Ensure your SIP provider supports the authentication method used * Contact your SIP provider if the issue persists **Call quality issues** * Check your network bandwidth and latency * Verify codec compatibility with your SIP provider * Test with different audio quality settings in your voice agent configuration # Configure with Plivo Source: https://docs.subverseai.com/integrations/telephony-plivo Step-by-step guide to configure Plivo SIP trunk with SubVerse ## Overview This guide walks you through configuring a Plivo SIP trunk to work with SubVerse AI for both inbound and outbound calls. ## Prerequisites * Active Plivo account * [Purchase a Plivo phone number](https://console.plivo.com/phone-numbers/search/) * Access to Plivo Console ## Step 1: Get Your SubVerse SIP URI Before configuring Plivo, you need to obtain your SIP URI from SubVerse: 1. Log in to your SubVerse dashboard 2. Navigate to **Integrations** → **Telephony** 3. Copy your **SIP URI** (it will look like: `sip:xxxxx.sip.livekit.cloud`) Keep this SIP URI handy - you'll need it in the next steps. ## Step 2: Create SIP Endpoint (For Outbound) ### Create Endpoint 1. Log in to [Plivo Console](https://console.plivo.com) 2. Navigate to **Voice** → **SIP Endpoints** 3. Click **Create New Endpoint** 4. Enter: * **Username**: Your chosen username * **Password**: Your chosen strong password * **Alias**: Descriptive name (e.g., "SubVerse Endpoint") 5. Click **Create Endpoint** Save these credentials securely - you'll need to enter them in SubVerse dashboard. ## Step 3: Configure Outbound Trunk (Termination) Plivo uses the concept of "Trunks" for routing calls. ### Create Outbound Trunk 1. In Plivo Console, navigate to **Voice** → **Trunks** 2. Click **Add New Trunk** 3. Select **Termination** (for outbound calls from SubVerse) 4. Configure: * **Name**: Descriptive name (e.g., "SubVerse Outbound") * **Termination Type**: IP Address or SIP Endpoint * **IP Address/SIP URI**: Your Plivo SIP endpoint URI 5. Click **Create** ### Get Termination URI After creating the trunk: 1. Note your **Termination URI** 2. It will look like: `sip.plivo.com` or your custom domain 3. Copy this URI - you'll need it for SubVerse configuration ## Step 4: Configure Inbound Trunk (Origination) Configure the trunk to route incoming calls to SubVerse. ### Create Origination Trunk 1. In Plivo Console, navigate to **Voice** → **Trunks** 2. Click **Add New Trunk** 3. Select **Origination** (for inbound calls to SubVerse) 4. Configure: * **Name**: Descriptive name (e.g., "SubVerse Inbound") * **Origination Type**: SIP URI * **SIP URI**: Your SubVerse SIP URI (from Step 1) * **Priority**: 1 5. Enable **Send SIP OPTIONS** for health checks 6. Click **Create** For region-specific routing, use region-based SIP endpoints provided in your SubVerse Telephony dashboard. ### Configure Authentication 1. In your Origination trunk settings, go to **Authentication** 2. Select authentication method: * **IP Authentication**: Add IP ranges `0.0.0.0/1` and `128.0.0.0/1` * **Credential Authentication**: Use username/password (recommended) 3. If using credentials: * **Username**: Same as SIP endpoint username * **Password**: Same as SIP endpoint password 4. Click **Save** ## Step 5: Associate Phone Number ### Assign Number to Application 1. Navigate to **Phone Numbers** → **Your Numbers** 2. Click on your phone number 3. Under **Application Type**, select **XML Application** or **PHLO** 4. For XML Application: * Create an application that forwards to your trunk * Or use direct SIP forwarding 5. For inbound calls, ensure the number routes through your Origination trunk 6. Click **Update Number** ### Alternative: Direct SIP Configuration 1. In your phone number settings 2. Set **Answer URL** to forward to your SubVerse SIP URI 3. Or configure to use your Origination trunk 4. Click **Save** ## Step 6: Configure in SubVerse Dashboard Now that Plivo is configured, add the trunk to SubVerse: ### For Outbound Calls 1. Go to SubVerse **Integrations** → **Telephony** 2. Click **Add Outbound Trunk** 3. Enter: * **Name**: Descriptive name (e.g., "Plivo Outbound") * **Phone Number**: Your Plivo number with country code (e.g., +1xxxxxxxxxx) * **SIP Address**: Your Plivo termination URI (e.g., `sip.plivo.com`) * **Auth Username**: Username from Step 2 * **Auth Password**: Password from Step 2 4. Click **Save** ### For Inbound Calls 1. Go to SubVerse **Integrations** → **Telephony** 2. Click **Add Inbound Trunk** 3. Enter: * **Name**: Descriptive name (e.g., "Plivo Inbound") * **Phone Number**: Your Plivo number with country code (e.g., +1xxxxxxxxxx) * **Auth Username**: Username from Step 2 * **Auth Password**: Password from Step 2 4. Click **Map Voicebot Usecase** and select your voice agent 5. Click **Save** ## Testing Your Configuration ### Test Inbound Calls 1. Call your Plivo phone number 2. The call should be routed to your SubVerse voice agent 3. Check the call appears in SubVerse **Call History** ### Test Outbound Calls 1. Create a workflow or use the voice agent interface 2. Make a test call using your configured Plivo number 3. Verify the call connects successfully 4. Check the call appears in SubVerse **Call History** ## Troubleshooting ### Inbound Calls Not Working **Check:** * Origination trunk is correctly configured in Plivo * SIP URI matches exactly what's shown in SubVerse dashboard * Phone number is associated with the correct application/trunk * Voice agent is mapped to the inbound trunk in SubVerse **Solution:** * Verify SIP URI in Plivo matches SubVerse * Check Plivo call logs for errors * Ensure phone number routing is correct * Verify trunk status is "Active" ### Outbound Calls Not Working **Check:** * SIP endpoint credentials are correct * Username and password match in both Plivo and SubVerse * Termination URI is correctly configured * SIP address in SubVerse matches Plivo endpoint **Solution:** * Verify credentials are correct * Check Plivo endpoint status * Review call logs for authentication errors * Ensure sufficient Plivo account balance ### Call Quality Issues **Check:** * Codec configuration * Network connectivity * Plivo service status * Region-specific routing **Solution:** * Verify codec settings (G.711 recommended) * Use region-based SIP endpoints for better latency * Check Plivo status page * Contact SubVerse support for assistance ### Authentication Failures **Check:** * Credentials are entered correctly * IP authentication ranges (if using IP auth) * SIP endpoint is enabled **Solution:** * Re-enter credentials carefully * Verify IP ranges include required addresses * Check endpoint status in Plivo console ## Advanced Configuration ### Codec Settings For best call quality: * Enable `PCMU` (G.711 μ-law) * Enable `PCMA` (G.711 A-law) * Configure in both trunk and endpoint settings ### DTMF Configuration Configure DTMF for interactive voice response: * **Recommended**: RFC 2833 * **Alternative**: SIP INFO * Ensure consistent configuration across Plivo and SubVerse ### Call Recording Enable call recording in Plivo: 1. In your application settings 2. Enable **Record** option 3. Configure recording format and storage 4. Recordings will be available in Plivo dashboard ### Failover Configuration Set up multiple origination URIs for redundancy: 1. Create multiple origination trunks 2. Set different priorities 3. Enable health checks with SIP OPTIONS 4. Plivo will automatically failover if primary fails ## Monitoring and Analytics ### Call Logs Access detailed call logs: 1. Navigate to **Voice** → **Call Logs** 2. Filter by date, number, or status 3. View detailed call information 4. Download logs for analysis ### Real-time Monitoring Monitor active calls: 1. Go to **Voice** → **Live Calls** 2. View currently active calls 3. Check call duration and status 4. Identify any issues in real-time ## Additional Resources * [Plivo SIP Trunking Documentation](https://www.plivo.com/docs/sip-trunking) * [Plivo Inbound Trunks Guide](https://www.plivo.com/docs/sip-trunking#inbound-trunks-origination) * [Plivo Outbound Trunks Guide](https://www.plivo.com/docs/sip-trunking#outbound-trunks-termination) * [Plivo Console](https://console.plivo.com) * [Plivo Support](https://support.plivo.com) ## Next Steps Set up Twilio SIP trunk Set up Telnyx SIP trunk Build your first AI voice agent Monitor your calls Remember to update the voice agent mapping in SubVerse whenever you modify your agent's configuration to ensure calls use the latest settings. # Configure with Telnyx Source: https://docs.subverseai.com/integrations/telephony-telnyx Step-by-step guide to configure Telnyx SIP trunk with SubVerse ## Overview This guide walks you through configuring a Telnyx SIP trunk to work with SubVerse AI for both inbound and outbound calls. ## Prerequisites * Active Telnyx account * [Purchase a Telnyx phone number](https://portal.telnyx.com/#/app/numbers/my-numbers) * Access to Telnyx Mission Control Portal ## Step 1: Get Your SubVerse SIP URI Before configuring Telnyx, you need to obtain your SIP URI from SubVerse: 1. Log in to your SubVerse dashboard 2. Navigate to **Integrations** → **Telephony** 3. Copy your **SIP URI** (it will look like: `sip:xxxxx.sip.livekit.cloud`) Keep this SIP URI handy - you'll need it in the next steps. ## Step 2: Create a SIP Connection 1. Log in to [Telnyx Mission Control Portal](https://portal.telnyx.com) 2. Navigate to **Voice** → **SIP Connections** 3. Click **Create SIP Connection** 4. Select **Credentials** as the authentication method 5. Enter a **Connection Name** (e.g., "SubVerse AI Connection") 6. Click **Create** ## Step 3: Configure Authentication ### Set Up Credentials 1. In your SIP Connection settings, go to **Authentication** 2. Click **Add Credential** 3. Enter: * **Username**: Your chosen username * **Password**: Your chosen strong password 4. Click **Save** Save these credentials securely - you'll need to enter them in SubVerse dashboard. ### Configure IP Authentication (Optional) If you prefer IP-based authentication: 1. In **Authentication** settings, enable **IP Authentication** 2. Add IP ranges: * `0.0.0.0/1` * `128.0.0.0/1` 3. Click **Save** Credential authentication is recommended for better security. ## Step 4: Configure for Inbound Calls Configure the connection to route incoming calls to SubVerse. ### Set Inbound Settings 1. In your SIP Connection, go to **Inbound** 2. Under **Inbound Settings**, configure: * **Codecs**: Select `PCMU` and `PCMA` * **DTMF Type**: `RFC 2833` or `Inband` * **Inbound SIP URI**: Your SubVerse SIP URI (from Step 1) 3. Enable **Send SIP OPTIONS** 4. Click **Save** ### Configure Origination URI 1. In the **Inbound** section, find **Origination URI** 2. Enter your SubVerse SIP URI 3. Set **Priority**: 1 4. Enable the URI 5. Click **Save** For region-specific routing, use region-based SIP endpoints provided in your SubVerse Telephony dashboard. ## Step 5: Configure for Outbound Calls Configure settings for outbound calls from SubVerse through Telnyx. ### Set Outbound Settings 1. In your SIP Connection, go to **Outbound** 2. Under **Outbound Settings**, configure: * **Outbound Voice Profile**: Select or create a profile * **Codecs**: Select `PCMU` and `PCMA` * **Localization**: Select your preferred region 3. Enable **Generate Ring Tone** 4. Click **Save** ### Configure Termination URI 1. In the **Outbound** section, note your **Termination SIP URI** 2. It will look like: `sip:yourconnection.sip.telnyx.com` 3. Copy this URI - you'll need it for SubVerse configuration ## Step 6: Associate Phone Number ### Assign Number to SIP Connection 1. Navigate to **Numbers** → **My Numbers** 2. Find your phone number 3. Click on the number to edit 4. Under **Connection**, select your SIP Connection 5. Configure: * **Connection Type**: SIP Connection * **Connection**: Select your SubVerse connection 6. Click **Save** ## Step 7: Configure in SubVerse Dashboard Now that Telnyx is configured, add the trunk to SubVerse: ### For Outbound Calls 1. Go to SubVerse **Integrations** → **Telephony** 2. Click **Add Outbound Trunk** 3. Enter: * **Name**: Descriptive name (e.g., "Telnyx Outbound") * **Phone Number**: Your Telnyx number with country code (e.g., +1xxxxxxxxxx) * **SIP Address**: Your Telnyx termination URI (e.g., `yourconnection.sip.telnyx.com`) * **Auth Username**: Username from Step 3 * **Auth Password**: Password from Step 3 4. Click **Save** ### For Inbound Calls 1. Go to SubVerse **Integrations** → **Telephony** 2. Click **Add Inbound Trunk** 3. Enter: * **Name**: Descriptive name (e.g., "Telnyx Inbound") * **Phone Number**: Your Telnyx number with country code (e.g., +1xxxxxxxxxx) * **Auth Username**: Username from Step 3 * **Auth Password**: Password from Step 3 4. Click **Map Voicebot Usecase** and select your voice agent 5. Click **Save** ## Testing Your Configuration ### Test Inbound Calls 1. Call your Telnyx phone number 2. The call should be routed to your SubVerse voice agent 3. Check the call appears in SubVerse **Call History** ### Test Outbound Calls 1. Create a workflow or use the voice agent interface 2. Make a test call using your configured Telnyx number 3. Verify the call connects successfully 4. Check the call appears in SubVerse **Call History** ## Troubleshooting ### Inbound Calls Not Working **Check:** * Origination URI is correctly configured in Telnyx * SIP URI matches exactly what's shown in SubVerse dashboard * Phone number is associated with the SIP connection * Voice agent is mapped to the inbound trunk in SubVerse **Solution:** * Verify SIP URI in Telnyx matches SubVerse * Check Telnyx call logs for errors * Ensure phone number is active * Verify SIP connection status is "Active" ### Outbound Calls Not Working **Check:** * Credentials are correctly configured * Username and password match in both Telnyx and SubVerse * Termination URI is correctly configured * SIP address in SubVerse matches Telnyx connection **Solution:** * Verify credentials are correct * Check Telnyx connection status * Review call logs for authentication errors * Ensure sufficient Telnyx account balance ### Call Quality Issues **Check:** * Codec configuration (PCMU/PCMA recommended) * Network connectivity * Telnyx service status * Region-specific routing **Solution:** * Verify codec settings match on both sides * Use region-based SIP endpoints for better latency * Check Telnyx status page * Contact SubVerse support for assistance ### Authentication Failures **Check:** * Credentials are entered correctly * IP authentication ranges (if using IP auth) * SIP connection is enabled **Solution:** * Re-enter credentials carefully * Verify IP ranges include required addresses * Check SIP connection status in Telnyx portal ## Advanced Configuration ### Codec Optimization For best call quality: * Enable `PCMU` (G.711 μ-law) - Primary * Enable `PCMA` (G.711 A-law) - Secondary * Disable other codecs unless specifically needed ### DTMF Configuration Configure DTMF for interactive voice response: * **Recommended**: RFC 2833 * **Alternative**: Inband * Ensure both Telnyx and SubVerse use the same method ### Failover Configuration Set up multiple origination URIs for redundancy: 1. Add primary SubVerse SIP URI with Priority 1 2. Add backup SIP URI with Priority 2 3. Enable both URIs ## Additional Resources * [Telnyx SIP Trunking Documentation](https://developers.telnyx.com/docs/v2/sip-trunking) * [Telnyx SIP Configuration Guide](https://support.telnyx.com/en/articles/8096455-how-to-configure-a-sip-trunk) * [Telnyx Mission Control Portal](https://portal.telnyx.com) * [Telnyx Support](https://support.telnyx.com) ## Next Steps Set up Twilio SIP trunk Set up Plivo SIP trunk Build your first AI voice agent Monitor your calls Remember to update the voice agent mapping in SubVerse whenever you modify your agent's configuration to ensure calls use the latest settings. # Configure with Twilio Source: https://docs.subverseai.com/integrations/telephony-twilio Step-by-step guide to configure Twilio SIP trunk with SubVerse ## Overview This guide walks you through configuring a Twilio SIP trunk to work with SubVerse AI for both inbound and outbound calls. ## Prerequisites * Active Twilio account * [Purchase a Twilio phone number](https://help.twilio.com/articles/223135247-How-to-Search-for-and-Buy-a-Twilio-Phone-Number-from-Console) * [Install the Twilio CLI](https://www.twilio.com/docs/twilio-cli/getting-started/install) (optional, for CLI method) * [Create a Twilio profile](https://www.twilio.com/docs/twilio-cli/general-usage/profiles) (optional, for CLI method) ## Step 1: Get Your SubVerse SIP URI Before configuring Twilio, you need to obtain your SIP URI from SubVerse: 1. Log in to your SubVerse dashboard 2. Navigate to **Integrations** → **Telephony** 3. Copy your **SIP URI** (it will look like: `sip:xxxxx.sip.livekit.cloud`) Keep this SIP URI handy - you'll need it in the next steps. ## Step 2: Create a SIP Trunk ### Using Twilio Console (Recommended) 1. Sign in to the [Twilio Console](https://console.twilio.com) 2. Navigate to **Elastic SIP Trunking** → **Trunks** 3. Click **Create new SIP Trunk** 4. Enter a **Friendly Name** (e.g., "SubVerse AI Trunk") 5. Click **Create** ### Using Twilio CLI The domain name for your SIP trunk must end in `pstn.twilio.com`: ```bash theme={null} twilio api:trunking:v1:trunks:create \ --friendly-name "SubVerse AI Trunk" \ --domain-name "subverse-trunk.pstn.twilio.com" ``` Copy the trunk SID from the output for use in the following steps. ## Step 3: Configure for Inbound Calls Configure the trunk to route incoming calls to SubVerse. ### Using Twilio Console 1. In your SIP trunk settings, go to **Origination** 2. Click **Add new Origination URI** 3. Enter the following details: * **Origination SIP URI**: Your SubVerse SIP URI (from Step 1) * **Priority**: 1 * **Weight**: 1 * **Enabled**: Check this box * **Friendly Name**: "SubVerse SIP URI" 4. Click **Add** 5. Click **Save** ### Using Twilio CLI Replace `` with your SubVerse SIP URI and `` with your trunk SID: ```bash theme={null} twilio api:trunking:v1:trunks:origination-urls:create \ --trunk-sid \ --friendly-name "SubVerse SIP URI" \ --sip-url "" \ --weight 1 \ --priority 1 \ --enabled ``` For region-specific routing, use region-based SIP endpoints provided in your SubVerse Telephony dashboard. ## Step 4: Configure for Outbound Calls Configure authentication for outbound calls from SubVerse through Twilio. ### Create Credential List 1. In Twilio Console, navigate to **Voice** → **Manage** → **Credential Lists** 2. Click **Create new Credential List** 3. Enter a name (e.g., "SubVerse Credentials") 4. Click **Create** 5. Click **Add Credential** 6. Enter: * **Username**: Your chosen username * **Password**: Your chosen password 7. Click **Save** Save these credentials securely - you'll need to enter them in SubVerse dashboard. ### Associate Credential List with Trunk 1. Go back to your SIP trunk settings 2. Navigate to **Termination** → **Authentication** 3. Under **Credential Lists**, select the credential list you just created 4. Click **Save** ### Configure Termination URI 1. In your SIP trunk, go to **Termination** 2. Click **Add new Termination URI** 3. Enter: * **Termination SIP URI**: This will be provided by Twilio (usually your trunk domain) * **Priority**: 1 * **Weight**: 1 * **Enabled**: Check this box 4. Click **Save** ## Step 5: Associate Phone Number with Trunk ### Using Twilio Console 1. In your SIP trunk settings, go to **Numbers** 2. Click **Add an Existing Number** or **Buy a Number** 3. Select your phone number 4. Click **Add** ### Using Twilio CLI ```bash theme={null} twilio api:trunking:v1:trunks:phone-numbers:create \ --trunk-sid \ --phone-number-sid ``` To list your phone numbers and trunks: ```bash theme={null} # List phone numbers twilio phone-numbers:list # List trunks twilio api:trunking:v1:trunks:list ``` ## Step 6: Configure in SubVerse Dashboard Now that Twilio is configured, add the trunk to SubVerse: ### For Outbound Calls 1. Go to SubVerse **Integrations** → **Telephony** 2. Click **Add Outbound Trunk** 3. Enter: * **Name**: Descriptive name (e.g., "Twilio Outbound") * **Phone Number**: Your Twilio number with country code (e.g., +1xxxxxxxxxx) * **SIP Address**: Your Twilio termination URI (e.g., `subverse-trunk.pstn.twilio.com`) * **Auth Username**: Username from Step 4 * **Auth Password**: Password from Step 4 4. Click **Save** ### For Inbound Calls 1. Go to SubVerse **Integrations** → **Telephony** 2. Click **Add Inbound Trunk** 3. Enter: * **Name**: Descriptive name (e.g., "Twilio Inbound") * **Phone Number**: Your Twilio number with country code (e.g., +1xxxxxxxxxx) * **Auth Username**: Username from Step 4 (if configured) * **Auth Password**: Password from Step 4 (if configured) 4. Click **Map Voicebot Usecase** and select your voice agent 5. Click **Save** ## Testing Your Configuration ### Test Inbound Calls 1. Call your Twilio phone number 2. The call should be routed to your SubVerse voice agent 3. Check the call appears in SubVerse **Call History** ### Test Outbound Calls 1. Create a workflow or use the voice agent interface 2. Make a test call using your configured Twilio number 3. Verify the call connects successfully 4. Check the call appears in SubVerse **Call History** ## Troubleshooting ### Inbound Calls Not Working **Check:** * Origination URI is correctly configured in Twilio * SIP URI matches exactly what's shown in SubVerse dashboard * Phone number is associated with the trunk * Voice agent is mapped to the inbound trunk in SubVerse **Solution:** * Verify SIP URI in Twilio matches SubVerse * Check Twilio debugger logs for errors * Ensure phone number is active and not in use elsewhere ### Outbound Calls Not Working **Check:** * Credential list is associated with the trunk * Username and password match in both Twilio and SubVerse * Termination URI is correctly configured * SIP address in SubVerse matches Twilio trunk domain **Solution:** * Verify credentials are correct * Check Twilio trunk status is active * Review Twilio debugger for authentication errors * Ensure sufficient Twilio account balance ### Call Quality Issues **Check:** * Network connectivity * Twilio service status * Region-specific routing configuration **Solution:** * Use region-based SIP endpoints for better latency * Check Twilio status page * Contact SubVerse support for assistance ## Additional Resources * [Twilio SIP Trunking Documentation](https://www.twilio.com/docs/sip-trunking) * [Twilio Elastic SIP Trunking Setup](https://www.twilio.com/en-us/blog/elastic-sip-trunking-step-by-step-setup) * [Twilio Console](https://console.twilio.com) * [Twilio Support](https://support.twilio.com) ## Next Steps Set up Telnyx SIP trunk Set up Plivo SIP trunk Build your first AI voice agent Monitor your calls Remember to update the voice agent mapping in SubVerse whenever you modify your agent's configuration to ensure calls use the latest settings. # Webhooks Integration Source: https://docs.subverseai.com/integrations/webhooks-integration Receive real-time event notifications from SubVerse AI ## Overview Webhooks allow your applications to receive real-time notifications when specific events occur in SubVerse AI, such as call completions, workflow executions, or agent interactions. This enables you to build responsive integrations and automate workflows based on SubVerse events. ## How Webhooks Work When an event occurs in SubVerse AI (like a call completing or workflow finishing), we send an HTTP POST request to your configured webhook URL with relevant event data. This enables you to: * Track call outcomes and analytics in your systems * Trigger downstream processes automatically * Update your CRM or database in real-time * Send notifications to your team * Integrate with third-party tools ## Creating a Webhook ### Step 1: Navigate to Webhooks 1. Log in to your SubVerse dashboard 2. Go to **Integrations** → **Webhooks** 3. Click **+ Add Webhook** ### Step 2: Configure Webhook URL **Webhook URL** * Enter your endpoint URL that will receive webhook events * Must be a publicly accessible HTTPS URL * Format: `https://your-server.com/webhook` **Example URLs:** * `https://api.yourcompany.com/subverse/webhook` * `https://your-app.com/api/v1/webhooks/subverse` * `https://hooks.zapier.com/hooks/catch/123456/abcdef` Your webhook URL must be publicly accessible and use HTTPS. Local development URLs (localhost, 127.0.0.1) will not work in production. ### Step 3: Select Agents (Optional) Choose specific agents whose events you want to receive: * **Select All**: Receive events from all agents * **Specific Agents**: Select individual agents from the dropdown **Use Cases:** * Monitor specific high-priority agents * Route different agents to different endpoints * Filter events by agent type ### Step 4: Select Workflows (Optional) Choose specific workflows whose events you want to receive: * **Select All**: Receive events from all workflows * **Specific Workflows**: Select individual workflows from the dropdown **Use Cases:** * Track specific campaign workflows * Monitor critical business processes * Separate workflow events by type ### Step 5: Configure Custom Headers (Optional) Add custom HTTP headers to webhook requests for authentication or metadata: **Common Use Cases:** * **Authentication**: `Authorization: Bearer your-token-here` * **API Keys**: `X-API-Key: your-api-key` * **Custom Metadata**: `X-Client-ID: your-client-id` **To Add Headers:** 1. Click **+ Add** in the Custom Headers section 2. Enter **Header Key** (e.g., `Authorization`) 3. Enter **Header Value** (e.g., `Bearer abc123xyz`) 4. Add multiple headers as needed ### Step 6: Subscribe to Events Select which events you want to receive notifications for: #### Call Events * **In Queue**: Call is waiting to be processed * **Placed**: Outbound call has been initiated * **Errored**: Call encountered an error * **Canceled**: Call was canceled before completion * **Expired**: Call expired (timeout) * **Completed**: Call finished successfully #### Workflow Events * **In Queue**: Workflow is waiting to execute * **Started**: Workflow execution has begun * **Node Execution**: Individual workflow node executed * **Failed**: Workflow execution failed * **Completed**: Workflow finished successfully **Selection Tips:** * Click **Select All** to subscribe to all events in a category * Select individual events for specific use cases * You must select at least one event to create the webhook ### Step 7: Create Webhook 1. Review your configuration 2. Click **Create Webhook** 3. Your webhook will appear in the webhooks dashboard 4. Toggle the switch to enable/disable the webhook ## Event Payload Structure SubVerse sends webhook events as HTTP POST requests with JSON payloads. ### Call Events Payload ```json theme={null} { "eventType": "call.placed", "createdAt": "2025-12-08T10:30:00Z", "data": { "callId": "call_xyz789", "customerNumber": "+91xxxxxxxxxx", "callStatus": "call_placed", "botNumber": "+91xxxxxxxxxx", "agentId": "agent_123", "agentName": "Customer Support Agent", "callDuration": 185, "callDirection": "outbound", "callTime": "2025-12-08T10:27:00Z", "transcript": "Full conversation transcript...", "analysis": { "sentiment": "positive", "summary": "Customer inquiry resolved successfully", "customFields": {} }, "recordingUrl": "https://recordings.subverseai.com/call_xyz789.mp3" } } ``` ### Workflow Events Payload ```json theme={null} { "eventType": "workflow.in_queue", "createdAt": "2025-12-08T10:35:00Z", "data": { "workflowId": "wf_456", "workflowName": "Order Confirmation Campaign", "executionId": "exec_789", "status": "in_queue", "startedAt": "2025-12-08T10:30:00Z", "completedAt": "2025-12-08T10:35:00Z", "duration": 300, "nodesExecuted": 5, "results": { "callsMade": 10, "emailsSent": 10, "successRate": 0.9 } } } ``` ### Common Fields All webhook payloads include: * **eventType**: Type of event (e.g., `call.completed`, `call.placed`, `workflow.started`, `workflow.in_queue`) * **createdAt**: ISO 8601 timestamp when event occurred * **data**: Event-specific data payload with camelCase field names ## Webhook Endpoint Requirements Your webhook endpoint must meet the following requirements: ### 1. Accept POST Requests ```javascript theme={null} app.post('/webhook', (req, res) => { // Handle webhook }); ``` ### 2. Parse JSON Body ```javascript theme={null} app.use(express.json()); ``` ### 3. Return 2xx Status Code ```javascript theme={null} res.status(200).json({ received: true }); ``` ### 4. Respond Quickly * Return response within 5 seconds * Process heavy operations asynchronously * Use background jobs for time-consuming tasks ## Example Webhook Endpoint ### Node.js/Express ```javascript theme={null} const express = require('express'); const app = express(); app.use(express.json()); app.post('/subverse/webhook', async (req, res) => { const { eventType, createdAt, data } = req.body; // Acknowledge receipt immediately res.status(200).json({ received: true, eventType: eventType }); // Process asynchronously processWebhookAsync(eventType, data); }); async function processWebhookAsync(eventType, data) { try { switch(eventType) { case 'call.completed': case 'call.placed': await updateCRM(data); await sendNotification(data); break; case 'workflow.completed': case 'workflow.in_queue': await logWorkflowResults(data); break; default: console.log('Unknown event type:', eventType); } } catch (error) { console.error('Error processing webhook:', error); } } app.listen(3000); ``` ### Python/Flask ```python theme={null} from flask import Flask, request, jsonify import threading app = Flask(__name__) @app.route('/subverse/webhook', methods=['POST']) def webhook(): data = request.json event_type = data.get('eventType') created_at = data.get('createdAt') # Acknowledge receipt immediately response = jsonify({'received': True, 'eventType': event_type}) # Process asynchronously thread = threading.Thread( target=process_webhook_async, args=(event_type, data.get('data')) ) thread.start() return response, 200 def process_webhook_async(event_type, data): try: if event_type in ['call.completed', 'call.placed']: update_crm(data) send_notification(data) elif event_type in ['workflow.completed', 'workflow.in_queue']: log_workflow_results(data) except Exception as e: print(f'Error processing webhook: {e}') if __name__ == '__main__': app.run(port=3000) ``` ## Security Best Practices ### 1. Use HTTPS Always use HTTPS endpoints to encrypt data in transit. ### 2. Validate Requests Verify requests are coming from SubVerse: * Check custom headers you configured * Validate event structure * Implement request signing (if available) ### 3. Implement Idempotency Handle duplicate events gracefully: ```javascript theme={null} const processedEvents = new Set(); app.post('/webhook', (req, res) => { const { eventType, createdAt, data } = req.body; // Use callId or workflowId + createdAt as unique identifier const eventId = data.callId || data.workflowId + '_' + createdAt; if (processedEvents.has(eventId)) { return res.status(200).json({ received: true, duplicate: true }); } processedEvents.add(eventId); // Process event... }); ``` ### 4. Rate Limiting Protect your endpoint from abuse: ```javascript theme={null} const rateLimit = require('express-rate-limit'); const limiter = rateLimit({ windowMs: 1 * 60 * 1000, // 1 minute max: 100 // limit each IP to 100 requests per minute }); app.post('/webhook', limiter, (req, res) => { // Handle webhook }); ``` ## Managing Webhooks ### Enable/Disable Webhooks Toggle the switch in the webhooks dashboard to enable or disable a webhook without deleting it. ### Edit Webhooks 1. Click the edit icon next to the webhook 2. Modify URL, agents, workflows, headers, or events 3. Click **Update Webhook** ### Delete Webhooks 1. Click the delete icon next to the webhook 2. Confirm deletion 3. Webhook will stop receiving events immediately ### Test Webhooks Send a test event to verify your endpoint: 1. Click the test icon next to the webhook 2. Select an event type to test 3. Check your endpoint receives the test payload ## Monitoring Webhooks ### Webhook Logs View webhook delivery status and responses: 1. Click on a webhook in the dashboard 2. View recent deliveries 3. Check success/failure status 4. Review response codes and error messages ### Retry Logic SubVerse automatically retries failed webhook deliveries: * **Attempts**: Up to 3 retries * **Backoff**: Exponential backoff (1s, 5s, 25s) * **Status Codes**: Retries on 5xx errors and timeouts * **Success**: 2xx status codes mark delivery as successful ## Common Use Cases ### 1. CRM Integration Update customer records when calls complete: ```javascript theme={null} async function updateCRM(callData) { await crmClient.contacts.update({ phone: callData.customerNumber, lastCallDate: callData.callTime, callDuration: callData.callDuration, callNotes: callData.transcript, sentiment: callData.analysis?.sentiment }); } ``` ### 2. Team Notifications Send Slack notifications for important events: ```javascript theme={null} async function sendSlackNotification(callData) { if (callData.analysis?.sentiment === 'negative') { await slackClient.chat.postMessage({ channel: '#customer-support', text: `⚠️ Negative call detected with ${callData.customerNumber}`, attachments: [{ text: callData.analysis.summary }] }); } } ``` ### 3. Analytics Tracking Send events to analytics platforms: ```javascript theme={null} async function trackAnalytics(callData) { await analyticsClient.track({ event: 'Call Completed', properties: { agentId: callData.agentId, duration: callData.callDuration, status: callData.callStatus, sentiment: callData.analysis?.sentiment } }); } ``` ### 4. Workflow Automation Trigger follow-up actions based on call outcomes: ```javascript theme={null} async function automateFollowup(callData) { if (callData.callStatus === 'completed') { // Send follow-up email await sendEmail({ to: callData.analysis?.customFields?.email, subject: 'Thank you for your call', body: generateFollowupEmail(callData) }); } else { // Schedule retry call await scheduleCallback({ customerNumber: callData.customerNumber, scheduledTime: addHours(new Date(), 2) }); } } ``` ## Troubleshooting ### Webhook Not Receiving Events **Check:** * Webhook is enabled (toggle switch is on) * URL is publicly accessible * Correct events are selected * Agents/workflows are selected (if filtered) **Solution:** * Test URL accessibility from external service * Verify firewall rules allow incoming requests * Check webhook logs for delivery attempts * Ensure endpoint returns 2xx status code ### Timeout Errors **Check:** * Endpoint response time * Heavy processing in request handler * Database query performance **Solution:** * Return 200 response immediately * Move processing to background jobs * Use async/await properly * Optimize database queries ### Duplicate Events **Check:** * Retry logic triggering multiple deliveries * Idempotency handling in your code **Solution:** * Implement event ID tracking * Use database constraints for uniqueness * Return 200 even for duplicates ## Next Steps Use webhooks in workflows Webhook API documentation Monitor call events Build automated workflows Start with a simple webhook that logs events, then gradually add more complex processing logic as you become familiar with the event structure. # Billing Source: https://docs.subverseai.com/monitor/billing Track usage and billing info The Billing section allows you to track usage and manage your payments. Key components include: * **Available Balance**: Total funds available to cover upcoming charges. * **Credits**: Promotional or earned credits applied to billing. Credits get consumed before balance recharge. If you have high volume requirements and want to test our platform, [reach out](https://dashboard.subverseai.com/customised-plan) to us to add some credits to your account. * **Billing Preferences**: Manage tax-related information. Provide your business details such as registered name, address, email, and GSTIN for billing and invoicing. * **Billing and Payment History**: Search invoices and receipts by amount or invoice number. # Performance Dashboard Source: https://docs.subverseai.com/monitor/dashboard Analyze agent level performance The Performance Dashboard provides insights into agent-level performance, helping you track efficiency, response times, and customer satisfaction. Key metrics include: * Include total number of calls handled, total duration in hours of customer conversations, and avergae call duration in minutes. * **Top Performing Agents** section enables you to compare the performance of all your agents across multiple metrics. * Timeline view of **Call Volumes** (number of calls). Also allows filtering based on agent, call status, etc. * **Funnel view** to see how your voice agents are performing. You can compare the efficiency across timelines as % calls answered and % active discussions. Also allows filtering based on agent, call status, etc. # Session History Source: https://docs.subverseai.com/monitor/session-history Unified view of all customer sessions across voice, chat, and email Session History gives you a single, unified view of every customer interaction across all your channels — voice, chat (WhatsApp, webchat), and email — in one place. ## Session List The session list displays key details for every interaction at a glance: * **Customer**: The customer's phone number or identifier * **Time**: When the session started * **Agent**: The AI agent that handled the session * **Channel**: The communication channel (e.g., Plivo voice, WhatsApp, webchat, email) * **Messages / Duration**: Number of messages exchanged, or call duration for voice sessions * **Tags**: Custom labels applied to the session * **Status**: Session outcome (e.g., Completed, Active) The stats bar at the top shows **Total Sessions**, **Total Duration**, and **Sessions in Queue** for the selected time period. ## Search & Filter * **Search**: Look up sessions by channel name, session ID, or agent email * **Filter by Agent**: Narrow sessions to those handled by a specific agent * **Filter by Channel**: View sessions from a specific channel type * **Filter by Status**: Focus on completed, active, or other session states * **Date range**: View sessions from a specific time period * **Export**: Download session data for reporting or further analysis ## Session Details Click any session to open the full detail view, which shows the complete conversation transcript alongside session metadata and AI-generated insights. The detail view includes: * **Transcript**: Full conversation history between the customer and the AI agent * **Function Calls**: Every function (tool) the agent invoked during the session, including the exact arguments passed and the result returned — invaluable for debugging agent behavior and verifying integrations * **Session Metadata**: Channel type, channel name, channel ID, communication method, message count, retry attempts, duration, direction (inbound/outbound), and status * **AI Insight**: An AI-generated summary of the session capturing what the customer was trying to accomplish, how the agent responded, and user sentiment ## Channels Supported Session History covers all channels in a single unified view: * **Voice**: Inbound and outbound calls with duration and full transcripts * **Chat**: WhatsApp, webchat, and other messaging channels * **Email**: Email-based conversations with your agents This unified view makes it easy to audit agent performance, debug function call issues, and identify customer pain points across your entire operation.