# Salesforce

Salesforce is a leading Customer Relationship Management (CRM) platform. The Sling Salesforce connector extracts data from the Salesforce REST API, supporting standard objects like accounts, contacts, leads, opportunities, cases, campaigns, and custom objects.

{% hint style="success" %}
**CLI Pro Required**: APIs require a [CLI Pro token](https://docs.slingdata.io/sling-cli/cli-pro) or [Platform Plan](https://docs.slingdata.io/sling-platform/platform).
{% endhint %}

## Setup

The following credentials and inputs are accepted:

**Secrets:**

* `client_id` **(required)** -> Your Salesforce Connected App Client ID
* `client_secret` **(required)** -> Your Salesforce Connected App Client Secret
* `instance` **(required)** -> Your Salesforce instance URL (e.g., `mycompany.my.salesforce.com`)

**Inputs:**

* `anchor_date` (optional) -> The starting date for historical data extraction (default: 1 year ago). Format: `YYYY-MM-DDTHH:MM:SSZ`

### Getting Your Credentials

1. Log in to your [Salesforce organization](https://login.salesforce.com/)
2. Go to **Setup** > **Apps** > **App Manager**
3. Create a new **Connected App** with OAuth 2.0 enabled
4. Set OAuth Scopes:
   * `api` (Access and manage your data)
   * `refresh_token` (Offline access)
5. Copy your **Client ID** and **Client Secret**
6. Your instance URL is your Salesforce domain (e.g., `mycompany.my.salesforce.com`)

{% hint style="warning" %}
**Important:** Keep your Client Secret secure. Never commit it to version control.
{% endhint %}

### Using `sling conns`

Here are examples of setting a connection named `SALESFORCE`. We must provide the `type=api` property:

{% code overflow="wrap" %}

```bash
sling conns set SALESFORCE type=api spec=salesforce secrets='{ client_id: xxxxxxxx, client_secret: xxxxxxxx, instance: mycompany.my.salesforce.com }'
```

{% endcode %}

### Environment Variable

See [here](https://docs.slingdata.io/sling-cli/environment#dot-env-file-.env.sling) to learn more about the `.env.sling` file.

{% code overflow="wrap" %}

```bash
export SALESFORCE='{ type: api, spec: salesforce, secrets: { client_id: "xxxxxxxx", client_secret: "xxxxxxxx", instance: "mycompany.my.salesforce.com" } }'
```

{% endcode %}

### Sling Env File YAML

See [here](https://docs.slingdata.io/sling-cli/environment#sling-env-file-env.yaml) to learn more about the sling `env.yaml` file.

```yaml
connections:
  SALESFORCE:
    type: api
    spec: salesforce
    secrets:
      client_id: "xxxxxxxx"
      client_secret: "xxxxxxxx"
      instance: "mycompany.my.salesforce.com"
```

**With anchor date for historical data:**

```yaml
connections:
  SALESFORCE:
    type: api
    spec: salesforce
    secrets:
      client_id: "xxxxxxxx"
      client_secret: "xxxxxxxx"
      instance: "mycompany.my.salesforce.com"
    inputs:
      anchor_date: "2020-01-01T00:00:00Z"
```

## Replication

Here's an example replication configuration to sync Salesforce data to a PostgreSQL database:

```yaml
source: SALESFORCE
target: MY_POSTGRES

defaults:
  mode: incremental
  object: salesforce.{stream_name}

streams:
  # Sync core CRM objects
  accounts:
  contacts:
  leads:
  opportunities:
  cases:
  
  # Sync additional objects as needed
  campaigns:
  products:
  orders:
```

**Selective sync example:**

```yaml
source: SALESFORCE
target: MY_POSTGRES

defaults:
  mode: incremental
  object: crm.{stream_name}

streams:
  accounts:
  contacts:
  opportunities:
  opportunity_line_items:
```

**Full refresh example for metadata:**

```yaml
source: SALESFORCE
target: MY_POSTGRES

defaults:
  mode: full-refresh
  object: salesforce.{stream_name}

streams:
  # Metadata endpoints (no incremental support)
  organizations:
  users:
  profiles:
  record_types:
```

## Endpoints

### Core CRM Objects

| Endpoint        | Description         | Incremental |
| --------------- | ------------------- | ----------- |
| `accounts`      | Account records     | Yes         |
| `contacts`      | Contact records     | Yes         |
| `leads`         | Lead records        | Yes         |
| `opportunities` | Opportunity records | Yes         |
| `cases`         | Case/ticket records | Yes         |

### Activity & Campaign Objects

| Endpoint           | Description                  | Incremental |
| ------------------ | ---------------------------- | ----------- |
| `campaigns`        | Campaign records             | Yes         |
| `campaign_members` | Campaign member associations | Yes         |
| `events`           | Calendar events              | Yes         |
| `tasks`            | Task records                 | Yes         |

### Products & Pricing

| Endpoint     | Description       | Incremental |
| ------------ | ----------------- | ----------- |
| `products`   | Product2 records  | Yes         |
| `pricebooks` | Pricebook records | Yes         |

### Orders & Contracts

| Endpoint      | Description      | Incremental |
| ------------- | ---------------- | ----------- |
| `orders`      | Order records    | Yes         |
| `order_items` | Order line items | Yes         |
| `contracts`   | Contract records | Yes         |

### Opportunity Details

| Endpoint                    | Description                      | Incremental |
| --------------------------- | -------------------------------- | ----------- |
| `opportunity_line_items`    | Opportunity line items           | Yes         |
| `opportunity_contact_roles` | Contact roles on opportunities   | Yes         |
| `opportunity_history`       | Opportunity field change history | Yes         |

### Users & Org Structure

| Endpoint     | Description              | Incremental |
| ------------ | ------------------------ | ----------- |
| `users`      | User records             | Yes         |
| `user_roles` | User role hierarchy      | Yes         |
| `groups`     | Public groups and queues | Yes         |

### Metadata & Configuration

| Endpoint        | Description              | Incremental |
| --------------- | ------------------------ | ----------- |
| `organizations` | Organization metadata    | No          |
| `profiles`      | User profile definitions | Yes         |
| `record_types`  | Record type definitions  | Yes         |

### File & Content Objects

| Endpoint            | Description          | Incremental |
| ------------------- | -------------------- | ----------- |
| `assets`            | Asset records        | Yes         |
| `content_documents` | File metadata        | Yes         |
| `content_versions`  | File version history | Yes         |

### Discovery

| Endpoint    | Description                           | Incremental |
| ----------- | ------------------------------------- | ----------- |
| `_sobjects` | Available Salesforce objects metadata | No          |

### Custom Objects

The connector automatically discovers and syncs custom objects in your Salesforce organization. Custom objects are dynamically extracted and named based on their Salesforce API names (e.g., `Project__c` becomes `projects`).

To discover available endpoints:

```bash
sling conns discover SALESFORCE
```

## Incremental Sync

The Salesforce connector uses time-based incremental sync with the `SystemModstamp` timestamp:

* **First run:** Fetches all records from `anchor_date` (default: 1 year ago) to present
* **Subsequent runs:** Only fetches records modified after the last sync
* **Update tracking:** Uses `SystemModstamp` to detect changed records

The `SystemModstamp` field represents when a record was last modified in Salesforce, including:

* Direct record changes
* Child record changes
* Formula field recalculations

This ensures you capture both new records and updates to existing records.

## Date Fields

All Unix timestamp fields are automatically converted to proper datetime columns. Standard timestamp fields like `CreatedDate`, `LastModifiedDate`, and `SystemModstamp` are handled appropriately.

## Rate Limiting

Salesforce API has rate limits based on your license type:

* **Standard:** 1,000 API calls per 24 hours per user
* **Unlimited/Performance:** 4,000-10,000 API calls per 24 hours per user

The connector automatically:

* Uses conservative rate limiting (5 requests/second by default)
* Retries with exponential backoff on 429 (rate limit) responses
* Batches SOQL queries to minimize API calls

{% hint style="info" %}
The connector uses SOQL (Salesforce Object Query Language) with pagination to efficiently extract large datasets while respecting rate limits.
{% endhint %}

## Limitations & Disabled Endpoints

Some endpoints may be disabled by default due to Salesforce edition limitations (e.g., unavailable in Developer Edition):

* `opportunity_team_members` - Not available in all editions
* `account_team_members` - Not available in all editions
* `quotes` - Not available in all editions

These can be re-enabled if your Salesforce edition supports them.

## Common Use Cases

### Sync Core Sales Data

```yaml
source: SALESFORCE
target: MY_POSTGRES

defaults:
  mode: incremental
  object: sales.{stream_name}

streams:
  accounts:
  contacts:
  leads:
  opportunities:
  opportunity_line_items:
```

### Sync Customer Service Data

```yaml
source: SALESFORCE
target: MY_POSTGRES

defaults:
  mode: incremental
  object: service.{stream_name}

streams:
  cases:
  assets:
  contacts:
  accounts:
```

### Sync Marketing & Campaign Data

```yaml
source: SALESFORCE
target: MY_POSTGRES

defaults:
  mode: incremental
  object: marketing.{stream_name}

streams:
  campaigns:
  campaign_members:
  leads:
  contacts:
```

### Sync Orders & Contracts

```yaml
source: SALESFORCE
target: MY_POSTGRES

defaults:
  mode: incremental
  object: orders.{stream_name}

streams:
  orders:
  order_items:
  contracts:
```

### Sync Organizational Metadata

```yaml
source: SALESFORCE
target: MY_POSTGRES

defaults:
  mode: full-refresh
  object: org.{stream_name}

streams:
  organizations:
  users:
  user_roles:
  groups:
  profiles:
  record_types:
```

### Sync All Endpoints

```yaml
source: SALESFORCE
target: MY_POSTGRES

defaults:
  mode: incremental
  object: salesforce.{stream_name}

streams:
  # Sync all available endpoints
  '*':
```

## Troubleshooting

### Authentication Issues

* Verify your instance URL is correct (e.g., `mycompany.my.salesforce.com`, not `https://mycompany.my.salesforce.com`)
* Ensure your Connected App is approved by your Salesforce administrator
* Check that your Client ID and Client Secret are correct

### No Records Returned

* Verify the endpoint exists in your Salesforce edition (some are limited to specific editions)
* Check that your user has access to the objects you're trying to sync
* Verify your Salesforce API is enabled

### Custom Objects Not Appearing

* Custom objects must be marked as "Queryable" in Salesforce
* Only custom objects are automatically discovered; ensure you're using the `_sobjects` endpoint to see available objects

If you are facing issues connecting, please reach out to us at <support@slingdata.io>, on [discord](https://discord.gg/q5xtaSNDvp) or open a Github Issue [here](https://github.com/slingdata-io/sling-cli/issues).


---

# Agent Instructions: 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:

```
GET https://docs.slingdata.io/connections/api-connections/salesforce.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
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.
