# Connecting Salesforce

> Source: https://docs.trailspark.ai/crm-integration/connecting-salesforce

## Before You Connect

Salesforce requires a Connected App in your Salesforce org. This is a one-time setup that takes about five minutes. You'll need:

- **System Administrator** access in Salesforce (to create the Connected App)
- **Admin** or **Owner** role in Trailspark

Unlike HubSpot, the Salesforce connection uses a **per-workspace Client ID** — you enter your Connected App's Consumer Key directly in Trailspark. The connection uses secure OAuth, so no Client Secret is needed.

## Create a Connected App in Salesforce

1. In Salesforce Setup, search for **App Manager** and click **New Connected App**
2. Fill in the basic fields:

| Field | Value |
| - | - |
| Connected App Name | Trailspark Integration |
| API Name | Auto-fills |
| Contact Email | Your admin email |

3. Check **Enable OAuth Settings**
4. Set the **Callback URL** to:

```
https://[your-subdomain].trailspark.ai/api/oauth/callback/salesforce
```

5. Add these **OAuth Scopes**:
   - `Access and manage your data (api)`
   - `Perform requests on your behalf at any time (refresh_token, offline_access)`

6. Check **Require Proof Key for Code Exchange (PKCE)**

7. Click **Save**, then click **Manage Consumer Details**

8. Copy the **Consumer Key** — this is your Client ID

> [!TIP]
> With PKCE enabled, only the Consumer Key is required. No Client Secret is needed.

## Connect in Trailspark

1. Go to **Settings** > **CRM Integration**
2. Click **Connect Salesforce** on the Salesforce card
3. On the **Salesforce Configuration** page:
   - Toggle **Sandbox Environment** if connecting to a Salesforce sandbox (leave off for production)
   - Paste your **Client ID** (the Consumer Key from your Connected App)
4. Click **Connect to Salesforce**
5. Complete the Salesforce OAuth login and approve the requested permissions

Once authorized, the **Connect** tab shows a **Salesforce Connected** status. Click **Test Connection** to verify the integration is live.

> [!WARNING]
> The **Sandbox Environment** toggle must match your Salesforce org. Production credentials will not work against a sandbox, and vice versa.

## After Connecting

Trailspark fetches your Salesforce field schema automatically on connect. Open the **Field Mapping** tab to map Account and Lead fields to Trailspark's scoring fields.

If your Salesforce schema changes (new custom fields, renamed properties), click **Refresh Fields** on the **Connect** tab to pull the updated schema.

## Syncing opportunities

Once Salesforce is your active CRM, an **Opportunities** card appears on this page for configuring how Trailspark syncs your opportunities onto accounts — the same card as the **Deals** card on the HubSpot integration page, under Salesforce's own vocabulary:

- A toggle in the card header turns syncing on or off — **on by default** once Salesforce is connected. Turning it off stops syncing new opportunity activity from Salesforce; opportunities Trailspark already has keep informing scoring until they age out of the history window it can see.
- The status line shows when opportunities last synced, how many were synced, how many Trailspark couldn't match to an account, and how many Salesforce API calls have been used today.
- **Sync now** runs a sync immediately, without waiting for the next scheduled one.
- **Record types to include** and **Types to include** limit the sync to specific Salesforce record types and opportunity types — leave either empty to include everything.
- **Deal type comes from** decides where Trailspark reads each opportunity's type: its **Deal type property**, its **Pipeline**, or a **Custom property** you name. Below it, a mapping table lets you assign each observed value to **New business**, **Renewal**, **Expansion**, or **Other** — anything left unmapped counts as Other.
- **Reporting currency** sets which currency to total your open pipeline in, when your open opportunities span more than one currency.
- **Workspace ID deal property** (optional) names a field on the Opportunity object that holds your product workspace ID — for example `product_workspace_id` — if your product writes that ID onto opportunities when they're created or updated. When it's set, Trailspark matches an opportunity to an account by that workspace ID first, before falling back to its linked account. This is usually a more complete match than the account link alone, especially if not every account is linked to a Salesforce Account record yet.
- Click **Save** to apply changes to record types, opportunity types, deal types, reporting currency, or the workspace ID property — the enable toggle itself applies immediately. Changing any of these **recalculates your accounts' deal facts right away, with no additional Salesforce calls**. Setting or changing the workspace ID property re-checks your existing opportunities against it — for smaller deal volumes this happens right away and the card shows a message when it's done; for larger volumes it happens during the next scheduled sync instead, and the card tells you that too.

Trailspark syncs opportunities automatically once a day (around 7 PM Pacific), with a full repair pass once a week on Saturday evening (Pacific). Every sync reads your whole Salesforce opportunity pipeline, not just opportunities for one account, and matches each one to an account on its own — first by workspace ID if you've configured one, then through its linked account, then falling back to its contacts when they unambiguously point to one account. An opportunity Trailspark can't confidently match doesn't disappear; it's counted in the status line above.

See [Account detail](https://docs.trailspark.ai/accounts-dashboard/account-detail#opportunities) for where synced opportunities show up, and [Field Mapping](https://docs.trailspark.ai/crm-integration/field-mapping#deal-fields) for mapping extra opportunity properties onto them.

## Switching Environments

To move from sandbox to production (or vice versa):

1. Click **Disconnect** on the **Connect** tab
2. Navigate to **Settings** > **CRM Integration** and click **Connect Salesforce** (or go directly to **Settings** > **Integrations** > **Salesforce**) — both paths open the Salesforce Configuration page
3. Toggle **Sandbox Environment** to the correct position
4. Enter your Client ID and click **Connect to Salesforce**

## Troubleshooting

### "Invalid Client ID" error

- Confirm the Consumer Key was copied in full — it is a long string
- New Connected Apps may take a few minutes to propagate in Salesforce
- Verify the callback URL in your Connected App matches exactly: `https://[your-subdomain].trailspark.ai/api/oauth/callback/salesforce`

### Authorization fails

- Confirm you are logging into the correct Salesforce org (production vs. sandbox)
- Verify your Salesforce user has API access enabled
- Check that the Connected App is active in Salesforce App Manager

### Persistent token errors

OAuth tokens refresh automatically. If you see repeated token errors, the refresh token may have been revoked in Salesforce. Disconnect and reconnect to issue a new token.

## Next Steps

- [Field Mapping](https://docs.trailspark.ai/crm-integration/field-mapping) — map Salesforce Account and Lead fields to Trailspark
- [Buying Groups Overview](https://docs.trailspark.ai/buying-groups/buying-groups-overview) — how Trailspark uses Salesforce contact data for role detection
- [Salesforce integration overview](https://www.trailspark.ai/integrations/salesforce) — what the Salesforce integration does, the fields Trailspark writes, and how scoring uses your CRM data
