> For the complete documentation index, see [llms.txt](https://docs.dapta.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.dapta.ai/ai-text-agents/setting-up-your-text-agent/crm-pipeline-sync.md).

# CRM Pipeline Sync

Automatically move contacts to the right stage in your CRM pipeline after every conversation. Connect GoHighLevel or HubSpot, choose eligible stages, and let the agent handle the rest.

**CRM Pipeline Sync** lets your Text Agent move contacts through a GoHighLevel or HubSpot pipeline automatically — no manual updates needed. After each conversation closes and the post-conversation analysis runs, an AI judge reads the analysis and moves the matching contact to the appropriate stage.

{% hint style="info" %}
To configure CRM Pipeline Sync, you need permission to edit the Text Agent and a connected HubSpot or GoHighLevel credential. You do not need to request limited-rollout access.
{% endhint %}

***

**📘 What you'll learn in this document:**

* **Step 1:** Connect a CRM credential in **Settings → OAuth**.
* **Step 2:** Enable and configure CRM Pipeline Sync for a specific Text Agent.
* **How it works:** what happens at runtime when a conversation closes.

***

#### 🔐 Step 1: Connect a CRM credential

Before configuring your agent, add your CRM credential in **Settings → OAuth**. You can add multiple credentials per provider.

{% tabs %}
{% tab title="GoHighLevel" %}
You will need a **Private Integration Token** and your **Location ID**.

1. In your GoHighLevel account, go to **Settings → Integrations → Private Integrations** and create a new integration.
2. Copy the generated **Private Integration Token**.
3. Find your **Location ID** in **Settings → Business Info**.
4. In Dapta, go to **Settings → OAuth** and click **Add credential**.
5. Select **GoHighLevel**, paste your token and Location ID, give the credential a name, and click **Save**.

{% hint style="info" %}
Opportunities in GoHighLevel are the cards that move across pipeline stages.
{% endhint %}
{% endtab %}

{% tab title="HubSpot" %}
You will need a **Private App Token** with the right CRM scopes.

1. In HubSpot, go to **Settings → Integrations → Private Apps** and create a new app.
2. On the **Scopes** tab, enable at minimum:
   * `crm.objects.contacts.read` / `write`
   * `crm.objects.deals.read` / `write`
   * `crm.schemas.deals.read` / `write`
3. Click **Create app** and copy the generated token.
4. In Dapta, go to **Settings → OAuth** and click **Add credential**.
5. Select **HubSpot**, paste your token, give it a name, and click **Save**.

{% hint style="info" %}
Deals in HubSpot are the cards that move across pipeline stages.
{% endhint %}

{% content-ref url="/pages/GzstVCm8nuQpBuZ9BScN" %}
[HubSpot Private App Setup](/integrations/hubspot-private-app-setup.md)
{% endcontent-ref %}
{% endtab %}
{% endtabs %}

***

#### ⚙️ Step 2: Enable CRM Pipeline Sync for your Text Agent

Once a credential is connected, open the agent you want to configure.

1. Open your **Text Agent** and go to the **Conversation Analysis** tab.
2. Expand the **CRM Pipeline Sync** section.
3. Toggle **Enable CRM pipeline sync for this agent** to on.

***

#### 🔌 Select a credential and pipeline

4. Click the **Credential** selector. Each option shows the provider icon (HubSpot or GoHighLevel). If you haven't added a credential yet, select **Add credential** — this takes you to **Settings → OAuth**.
5. Once a credential is selected, choose a **Pipeline** from the dropdown. The list is pulled live from your CRM.

***

#### 🎯 Choose stages and set move conditions

6. Click **Choose stages** to open the stage selector. Check every stage the agent is allowed to move contacts into.
7. Click **Confirm**. Each selected stage appears as a card. Use its **pencil icon** to optionally write a **move condition** — a short description of when a contact belongs in that stage.

> Dapta generates a hidden AI fallback condition from the stage name. The editable field contains your own condition, not that fallback. Your condition takes priority; leaving the field empty uses the fallback when one is available.

***

#### ➕ "Add contact to pipeline if not already in it" toggle

This toggle controls what happens when an existing CRM contact has no deal/opportunity yet in the chosen pipeline:

| Toggle state | Behavior                                                                                                                                              |
| ------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| **ON**       | If the contact exists in the CRM but has no deal in this pipeline, a new deal/opportunity is created at the matched stage so they enter the pipeline. |
| **OFF**      | Only contacts who already have a deal/opportunity in this pipeline are moved.                                                                         |

{% hint style="warning" %}
**CRM Pipeline Sync never creates contacts.** It only acts on people who already exist in your CRM. If a contact cannot be found by phone number or email, nothing happens — no error, no data is created.
{% endhint %}

8. Set the toggle based on your workflow, then click **Save Agent** to save the draft. Review your changes, then click **Publish** to make them live.

***

## How it works at runtime

When a conversation session closes (either by the agent calling the **Close Conversation** action or after the inactivity timeout), the post-conversation analysis runs. As part of that analysis:

1. Dapta looks up the contact in your CRM by **phone number** or **email** captured during the conversation.
2. An LLM judge reads the analysis results and compares them against each eligible stage's condition: your own condition takes priority over its AI-generated fallback.
3. The judge selects the best matching eligible stage and moves the contact's deal/opportunity to that stage.

> The stage move is **best-effort** — it runs after the conversation closes and never blocks or delays the conversation itself. If the contact is not found in the CRM, the move is skipped silently.

***

## Requirements and limitations

| Requirement               | Detail                                                                                                                |
| ------------------------- | --------------------------------------------------------------------------------------------------------------------- |
| **Agent version**         | V2 Text Agents (temporal/durable runtime) only.                                                                       |
| **Contact matching**      | The contact must already exist in the CRM. Matching is by phone number (E.164 format recommended) or email.           |
| **Phone format**          | Phone numbers should match the format stored in your CRM. Use E.164 (e.g. `+15551234567`) where possible.             |
| **HubSpot object**        | Moves **Deals** across pipeline stages.                                                                               |
| **GoHighLevel object**    | Moves **Opportunities** across pipeline stages.                                                                       |
| **Multiple credentials**  | You can add multiple credentials per provider in **Settings → OAuth**. Each agent uses one credential + one pipeline. |
| **Conversation Analysis** | Post-Conversation Analysis must be enabled on the agent for CRM sync to run.                                          |

***

## Related pages

{% content-ref url="/pages/fvInwnJ2sqlPC09BrHef" %}
[Post-Conversation Analysis](/ai-text-agents/setting-up-your-text-agent/post-conversation-analysis.md)
{% endcontent-ref %}

{% content-ref url="/pages/GzstVCm8nuQpBuZ9BScN" %}
[HubSpot Private App Setup](/integrations/hubspot-private-app-setup.md)
{% endcontent-ref %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.dapta.ai/ai-text-agents/setting-up-your-text-agent/crm-pipeline-sync.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
