# Salesforce

<figure><img src="https://3697023207-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFSlso1Kjob5CLDrh0dVn%2Fuploads%2FjHDHVzm922WsDs8Y4vxf%2Fimage.png?alt=media&#x26;token=e120d7e9-820e-4055-a5b0-ca78c9ff0f30" alt=""><figcaption></figcaption></figure>

The **Salesforce** **Node** allows you to connect directly to your Salesforce CRM account and query structured sales and customer data. It supports SQL queries to retrieve contact, lead, opportunity, and account information, making it easier to automate workflows, analyze performance, or power downstream nodes like LLMs or VectorDBs.

Once connected, Stack AI can use this data to enhance sales processes, generate insights, and improve decision-making.

### Setting Up A Credentials Connection

1. **Obtain your login credentials**:
   * **Username**: your Salesforce login name.
   * **Password**: your Salesforce account password.

<figure><img src="https://3697023207-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFSlso1Kjob5CLDrh0dVn%2Fuploads%2Fua4wnzW7EMR4QXbnWDg0%2Fimage.png?alt=media&#x26;token=e9c6d268-f5d2-4f57-a332-1591a2e36307" alt=""><figcaption></figcaption></figure>

2. After logging in, click on your profile picture on the upper right.

<figure><img src="https://3697023207-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFSlso1Kjob5CLDrh0dVn%2Fuploads%2FCBoNkhcvyQPrlu8Udklf%2Fimage.png?alt=media&#x26;token=1dcfcbf5-95b1-47eb-811f-ae3954674881" alt=""><figcaption></figcaption></figure>

3. A dropdown menu will appear, click on **Settings**.

<figure><img src="https://3697023207-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFSlso1Kjob5CLDrh0dVn%2Fuploads%2F2XLuRr9KtV4zsWCsAUxc%2Fimage.png?alt=media&#x26;token=ffbc126e-d863-4269-9ace-8244467b0921" alt=""><figcaption></figcaption></figure>

4. On the **Settings** page, on the left navigation, select **Reset My Security Token**.

<figure><img src="https://3697023207-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFSlso1Kjob5CLDrh0dVn%2Fuploads%2F5mAW6asDcyM3jw2u8VGu%2Fimage.png?alt=media&#x26;token=a81367d9-3ff1-419f-a277-e858c92aafee" alt=""><figcaption></figcaption></figure>

5. Click on **Reset Security Token**.

<figure><img src="https://3697023207-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFSlso1Kjob5CLDrh0dVn%2Fuploads%2FBzi4ozRmdntkWPBfwRob%2Fimage.png?alt=media&#x26;token=d5f5662d-7163-40ed-a23a-17ab9234efda" alt=""><figcaption></figcaption></figure>

6. On click, the new Security token will be sent to the email associated to your Salesforce account.

<figure><img src="https://3697023207-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFSlso1Kjob5CLDrh0dVn%2Fuploads%2FimNpAvOkdeMSPwCSPlTF%2Fimage.png?alt=media&#x26;token=9508fc0b-87f3-41b8-9668-890b73ec1622" alt=""><figcaption></figcaption></figure>

7. Finally, in the email, this will be the **Security token** that will be used for the connection.

<figure><img src="https://3697023207-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFSlso1Kjob5CLDrh0dVn%2Fuploads%2FxHU7FN1KLW9EFobowJlW%2Fimage.png?alt=media&#x26;token=a2811203-663f-4a00-abf0-e12e868b9a6b" alt=""><figcaption></figcaption></figure>

#### Steps to connect:

1. Add the **Salesforce node** from the Apps section into your Stack AI project.

<figure><img src="https://3697023207-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFSlso1Kjob5CLDrh0dVn%2Fuploads%2FSkoPVbVuMR4Eqw6xId3g%2Fimage.png?alt=media&#x26;token=86e84f10-e59a-4455-9e64-7ffd17c9be3a" alt=""><figcaption></figcaption></figure>

2. Select **"Query Salesforce"** as the Action.

<figure><img src="https://3697023207-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFSlso1Kjob5CLDrh0dVn%2Fuploads%2FASy3z38bfItuyS90IsOV%2Fimage.png?alt=media&#x26;token=c4407633-50dc-43e9-995e-17eb09839e73" alt=""><figcaption></figcaption></figure>

3. Click on **"Select a connection"** or create a new connection with your credentials.

<figure><img src="https://3697023207-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFSlso1Kjob5CLDrh0dVn%2Fuploads%2Fi584XfU0BO9BegjCouzC%2Fimage.png?alt=media&#x26;token=e982a690-75b3-4ccd-848b-820114d50cef" alt=""><figcaption></figcaption></figure>

4. Choose the appropriate domain for your Salesforce environment:

   | Domain                | Use When                                                    |
   | --------------------- | ----------------------------------------------------------- |
   | "login" or left blank | Connecting to production or developer orgs                  |
   | "test"                | Connecting to a sandbox instance                            |
   | mycustomdomain        | Using a custom domain (recommended for SSO or OAuth setups) |

<figure><img src="https://3697023207-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFSlso1Kjob5CLDrh0dVn%2Fuploads%2FZKeilLrPrvBrdgNrTxS6%2Fimage.png?alt=media&#x26;token=f9bc7132-c4ed-4f31-be69-6ce3eb8c4b4f" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
Note that the Username for your API is different from the email address you used to sign up for Salesforce.
{% endhint %}

* **Enabling the "sandbox" toggle** tells Stack AI to connect to your Salesforce **sandbox environment** instead of your main (production) Salesforce account.
* **Disabling the "sandbox" toggle** means Stack AI will connect to your **production** Salesforce environment.

5. **Add your Salesforce Schema** in the configurations of the node to define which table you want to extract.
   * For example: TABLE Contact (Id TEXT, Name TEXT, Industry TEXT);

     <figure><img src="https://3697023207-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFSlso1Kjob5CLDrh0dVn%2Fuploads%2FEAqkL6xOOdmAdsLgVYVz%2Fimage.png?alt=media&#x26;token=b4f5be1c-61c2-4053-b52a-9f9007ae445e" alt=""><figcaption></figcaption></figure>
   * To list tables from your Salesforce account, you can run the included Python script below on your local machine.

<details>

<summary>Show Python Script</summary>

{% code title="list\_salesforce\_schema\_with\_filter.py" lineNumbers="true" fullWidth="true" %}

```python
from simple_salesforce import Salesforce

# Salesforce credentials (replace with environment variables in production)
username = ""
password = ""
security_token = ""

# 🔍 Specify object names to include (DANGER leaving the list empty will include ALL)
included_objects = ["Contact", "Account", "Opportunity"]  # Case-sensitive

# Connect to Salesforce
sf = Salesforce(username=username, password=password, security_token=security_token)

# Mapping Salesforce field types to SQL types
def map_salesforce_type(sf_type):
    mapping = {
        "string": "TEXT",
        "textarea": "TEXT",
        "picklist": "TEXT",
        "id": "VARCHAR(18)",
        "boolean": "BOOLEAN",
        "int": "INTEGER",
        "double": "FLOAT",
        "currency": "DECIMAL(18,2)",
        "percent": "DECIMAL(5,2)",
        "date": "DATE",
        "datetime": "TIMESTAMP",
        "email": "TEXT",
        "phone": "TEXT",
        "url": "TEXT",
        "reference": "VARCHAR(18)",
        "base64": "BYTEA",
        "location": "TEXT",
    }
    return mapping.get(sf_type, "TEXT")


# Get all object descriptions
objects = sf.describe()["sobjects"]

# Open file for writing schema output
with open("salesforce_schema.txt", "w") as file:
    for obj in objects:
        obj_name = obj["name"]
        
        # Apply filter if specified
        if included_objects and obj_name not in included_objects:
            continue
        
        try:
            obj_details = sf.__getattr__(obj_name).describe()
            field_defs = []

            for field in obj_details["fields"]:
                field_name = field["name"]
                field_type = map_salesforce_type(field["type"])
                field_defs.append(f"{field_name} {field_type}")

            field_list = ", ".join(field_defs)
            table_def = f"TABLE {obj_name} ({field_list});"
            print(table_def)
            file.write(table_def + "\n")

        except Exception as e:
            error_msg = f"-- Could not process {obj_name}: {e}"
            print(error_msg)
            file.write(error_msg + "\n")

print("\nFiltered schema has been saved to 'salesforce_schema.txt'")

```

{% endcode %}

</details>

## **Setting Up An OAuth2 Connector + Connection:**

1. Navigate to **Setup** (the gear in the top right corner), enter `App Manager` in the Quick Find box, and click **New External Client App** in the top right corner.&#x20;

<figure><img src="https://3697023207-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFSlso1Kjob5CLDrh0dVn%2Fuploads%2FYCwiCO7ACkQA5xqwdUQO%2Fsalesforce_client.png?alt=media&#x26;token=2dc1238d-05f0-4052-9904-a066d759da44" alt=""><figcaption></figcaption></figure>

2. Name the app and fill out the required information.
3. Ensure you select **Enable OAuth** under Enable OAuth Settings.
4. Type in your callback url. It should be the base web URL followed by `/auth`. For our Cloud offering, the URL is `https://www.stackai.com/auth`
5. Add the permissions your client needs. At minimum, usually `Access and manage your data (api)` and `Perform requests on your behalf at any time (refresh_token, offline_access)` are required.
6. Under **Flow Enablement**, toggle on at least **Enable Authorization Code Flow**
7. Under Security, select **Enable Refresh Token Rotation**, this will allow us to keep your connection alive.
8. Click **Create**
9. Go to Settings of your created app. Under OAuth settings, go to **Consumer Key and Secret.**
10. Save the key and secret you see here.

#### Salesforce OAuth2 Connector

In StackAI, go to **Connectors** in Settings. Search for Salesforce, and create a new **OAuth2 Connector**. Enter the key and secret you got from Salesforce here and click **Create.**

<figure><img src="https://3697023207-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFSlso1Kjob5CLDrh0dVn%2Fuploads%2FEVH1JjH0tOqFaHvQiB0X%2Fsalesforce_connector.png?alt=media&#x26;token=171cab47-56e0-4d17-99a7-60feb6508f3e" alt=""><figcaption></figcaption></figure>

To establish a connection, select the new Connector you created in any connection dialog window, you will be automatically redirected to sign in to Salesforce, or logged in automatically if you are signed in already.

### Visual overview

<figure><img src="https://3697023207-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFSlso1Kjob5CLDrh0dVn%2Fuploads%2F6WHsfO4dYVuI3btm7ahW%2Fimage.png?alt=media&#x26;token=0fa38678-3b47-42a8-904a-49d5cd213d3a" alt=""><figcaption></figcaption></figure>

Below are some examples of valid SQL queries for your Salesforce database, provided that it has been included in the **Schema**:

```sql
SELECT Name, Email FROM Contact
```

```sql
SELECT Id, Email FROM Contact WHERE Income > USD10000
```

```sql
SELECT Id, Email FROM Contact WHERE LastName = 'Aceituno'
```

```sql
SELECT Id, Email, Name, ParentAccount.Name FROM Contact
```

### Available Actions

#### 1. Salesforce Query

* **Purpose:** Query Salesforce using plain English or SOQL.
* **Inputs:**
  * **sql\_schema** (required): The database schema (tables, columns, types, etc.).
  * **query** (required): Your question in plain English or a SOQL query.

***

#### 2. Create Case

* **Purpose:** Create a new case in Salesforce.
* **Inputs:**
  * **subject** (required): The subject/title of the case.
  * **status** (optional): Status of the case (e.g., New, Working, Closed).
  * **priority** (optional): Priority level (e.g., High, Medium, Low).
  * **origin** (optional): Source of the case (e.g., Web, Phone, Email).
  * **description** (optional): Detailed description.
  * **account\_id** (optional): Salesforce Account ID to associate.
  * **contact\_id** (optional): Salesforce Contact ID to associate.

***

#### 3. Update Case

* **Purpose:** Update an existing case.
* **Inputs:**
  * **case\_id** (required): Salesforce Case ID to update.
  * **subject** (optional): New subject/title.
  * **status** (optional): New status.
  * **priority** (optional): New priority.
  * **origin** (optional): New origin/source.
  * **description** (optional): New description.
  * **account\_id** (optional): New Account ID.
  * **contact\_id** (optional): New Contact ID.

***

#### 4. Delete Case

* **Purpose:** Delete a case.
* **Inputs:**
  * **case\_id** (required): Salesforce Case ID to delete.

***

#### 5. Create Opportunity

* **Purpose:** Create a new opportunity.
* **Inputs:**
  * **name** (required): Name of the opportunity.
  * **stage\_name** (required): Sales stage (e.g., Prospecting, Closed Won).
  * **close\_date** (required): Expected close date (YYYY-MM-DD).
  * **amount** (optional): Opportunity amount.
  * **account\_id** (optional): Account ID to associate.
  * **description** (optional): Description.

***

#### 6. Update Opportunity

* **Purpose:** Update an existing opportunity.
* **Inputs:**
  * **opportunity\_id** (required): Salesforce Opportunity ID to update.
  * **name** (optional): New name.
  * **stage\_name** (optional): New stage.
  * **close\_date** (optional): New close date.
  * **amount** (optional): New amount.
  * **description** (optional): New description.

***

#### 7. Delete Opportunity

* **Purpose:** Delete an opportunity.
* **Inputs:**
  * **opportunity\_id** (required): Salesforce Opportunity ID to delete.

***

#### 8. Create Contact

* **Purpose:** Create a new contact.
* **Inputs:**
  * **last\_name** (required): Last name of the contact.
  * **first\_name** (optional): First name.
  * **email** (optional): Email address.
  * **phone** (optional): Phone number.
  * **account\_id** (optional): Account ID to associate.
  * **title** (optional): Job title.

***

#### 9. Update Contact

* **Purpose:** Update an existing contact.
* **Inputs:**
  * **contact\_id** (required): Salesforce Contact ID to update.
  * **last\_name** (optional): New last name.
  * **first\_name** (optional): New first name.
  * **email** (optional): New email.
  * **phone** (optional): New phone.
  * **title** (optional): New job title.

***

#### 10. Delete Contact

* **Purpose:** Delete a contact.
* **Inputs:**
  * **contact\_id** (required): Salesforce Contact ID to delete.

Here are the details for the Salesforce actions you requested, in your specified format:

***

#### **11. Create Comment**

* **Purpose:** Add a new comment to a Salesforce record (such as a Case, Opportunity, etc.).
* **Inputs:**
  * **parent\_id** (required): The Salesforce ID of the parent record to associate the comment with (e.g., Case ID, Opportunity ID).
  * **comment\_body** (required): The text content of the comment.
  * **is\_published** (optional): Boolean indicating if the comment should be published and visible to customers (default: true).

***

#### 12. Update Comment

* **Purpose:** Update the content or visibility of an existing Salesforce comment.
* **Inputs:**
  * **comment\_id** (required): The Salesforce ID of the comment to update.
  * **comment\_body** (optional): The updated text content of the comment.
  * **is\_published** (optional): Boolean indicating if the comment should be published and visible to customers.

***

#### 13. Delete Comment

* **Purpose:** Remove a comment from Salesforce.
* **Inputs:**
  * **comment\_id** (required): The Salesforce ID of the comment to delete.
