# Salesforce

> Bring accounts, contacts, leads, opportunities and other Salesforce objects, custom ones included, into your warehouse.

## Before you start

Salesforce signs sanda in through OAuth. That means an app registered in Salesforce, and a refresh token that lets sanda keep signing in without you. The form asks for the app's client ID and secret, and the refresh token.

- **A Salesforce edition with API access.** Some editions include it only as an add-on, so ask your Salesforce admin if you are unsure.
- **A user for sanda.** Use a dedicated integration user rather than a person's login, with the **API Enabled** permission and read access to the objects you want in sanda. sanda only ever reads. Whatever this user cannot see, sanda cannot sync.
- **An app that allows OAuth.** In Salesforce Setup, create the app that sanda will sign in as. Salesforce calls it a connected app, or an external client app in newer orgs. Turn on OAuth for it, with a callback URL you control and the scopes **Manage user data via APIs (api)** and **Perform requests at any time (refresh_token, offline_access)**.
- **The client ID and secret.** Salesforce calls them the consumer key and the consumer secret. You find both in the app's details in Setup.
- **A refresh token.** Authorise the app once as the integration user, using Salesforce's OAuth authorisation code flow. Salesforce sends an authorisation code to your callback URL. Exchange that code for tokens, and keep the `refresh_token` from the reply. If the app requires PKCE, add a code challenge to the authorisation request and the matching code verifier to the token request.

If your Salesforce is a sandbox, do the authorisation against the sandbox login address, and turn on **Sandbox** in the form.

## Connect Salesforce

:::steps
1. **Choose Salesforce.** Go to **Data · Connections**, press **New connection** and pick **Salesforce**.
2. **Enter the app's keys.** Put the consumer key in **Client ID** and the consumer secret in **Client Secret**.
3. **Enter the refresh token.** Paste it into **Refresh Token**.
4. **Say if it is a sandbox.** **Sandbox** sits under **Advanced settings** and opens off. Turn it on for a sandbox org.
5. **Choose how far back to load.** **Start Date** is under **Advanced settings**. Enter a date as `YYYY-MM-DD`, or a date and time as `YYYY-MM-DDTHH:mm:ssZ`. When it is empty, sanda loads the last two years.
6. **Continue.** Press **Continue**, name the connection, and press **Read schema**. sanda signs in and lists the objects the integration user can read. If it fails, the message says why. See [Troubleshoot connections](https://docs.sanda-os.com.au/connections/troubleshooting).
:::

The rest of the flow, naming the connection, setting a frequency and choosing tables, is the same for every source. See [Add a connection](https://docs.sanda-os.com.au/connections/add-a-connection).

## What syncs

Each Salesforce object lands in your warehouse as its own table. The usual starting points are `Account`, `Contact`, `Lead`, `Opportunity`, `Task` and `User`. The list also holds the other objects the integration user can read, custom objects included.

An org with a very large number of objects makes a long list. **Filter Salesforce Objects** under **Advanced settings** narrows it by object name.

## Tips

- **Choose a start date.** Leaving **Start Date** empty loads the last two years, but a fixed date makes the first load predictable. **End Date** stops loading at a chosen point, and is rarely needed.
- **Read the large objects incrementally.** The first run reads every object you choose in full. Switch big ones such as `Opportunity` and `Task` to an incremental mode afterwards. See [sync modes](https://docs.sanda-os.com.au/connections/sync-modes).
- **Leave Force to use BULK API off.** It is under **Advanced settings**. Turning it on can leave some fields empty on some tables.
- **Watch for NA turning into null.** Strings such as `NA`, `N/A`, `NULL`, `None` and `NaN` returned by the Salesforce Bulk API are treated as missing and arrive as null. Turn on **Preserve "NA" and similar string values** if `NA` is real data, for example North America.
- **Mind your API allowance.** Salesforce caps how many API requests an org can make in a day, and syncs use some of them. If your org is close to its limit, sync less often. See [sync schedules](https://docs.sanda-os.com.au/connections/schedules).

## Configuration fields

What the connection form asks for. Required fields are marked; the rest are optional.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| **Sandbox** | boolean | No | Toggle if you're using a Salesforce Sandbox. Default `false`. |
| **Client ID** | string | Yes | Enter your Salesforce developer application's Client ID. |
| **Client Secret** | string, secret | Yes | Enter your Salesforce developer application's Client secret. |
| **Refresh Token** | string, secret | Yes | Enter your application's Salesforce Refresh Token used for becca to access your Salesforce account. |
| **Start Date** | string | No | Enter the date (or date-time) in the YYYY-MM-DD or YYYY-MM-DDTHH:mm:ssZ format. becca will replicate the data updated on and after this date. If this field is blank, becca will replicate the data for last two years. |
| **End Date** | string | No | Enter the date (or date-time) in the YYYY-MM-DD or YYYY-MM-DDTHH:mm:ssZ format. For streams synced incrementally, becca will replicate data updated before this date; the bound is exclusive, so a date-only value means midnight UTC and the named day itself is not included. Streams synced in full refresh mode ignore this field and replicate all data. If this field is blank, becca will replicate data up to the current time. |
| **Force to use BULK API** | boolean | No | Toggle to use Bulk API (this might cause empty fields for some streams). Default `false`. |
| **Stream Slice Step for Incremental sync** | string | No | The size of the time window (ISO8601 duration) to slice requests. Default `P30D`. |
| **Lookback Window for Incremental sync** | string | No | The duration (ISO8601 duration) to re-read data from the source when running incremental syncs. This compensates for records that may not be immediately available when querying the Salesforce API due to eventual consistency delays. The connector will re-query this amount of time before the last cursor position on each sync. Increase this value if you observe missing records in your destination. Default `PT10M`. |
| **Filter Salesforce Objects** | array | No | Add filters to select only required stream based on `SObject` name. Use this field to filter which tables are displayed by this connector. This is useful if your Salesforce account has a large number of tables (>1000), in which case you may find it easier to choose tables and speed up the connector's performance if you restrict the tables displayed by this connector. |
| **Preserve "NA" and similar string values** | boolean | No | By default, string values such as "NA", "N/A", "NULL", "None" and "NaN" returned by the Salesforce Bulk API are treated as missing and synced as null. Enable this option to keep these values as literal strings (for example, "NA" meaning "North America"). Empty fields are still synced as null. Leaving this disabled preserves the connector's historical behavior. Default `false`. |

## Related

:::links
- [Sync modes](https://docs.sanda-os.com.au/connections/sync-modes): How sanda reads each table on every run.
- [Sync schedules](https://docs.sanda-os.com.au/connections/schedules): How often a connection runs.
- [Allowlist sanda’s address](https://docs.sanda-os.com.au/connections/allowlist): For a system behind a firewall.
- [Troubleshoot connections](https://docs.sanda-os.com.au/connections/troubleshooting): What an error means and how to fix it.
:::
