---
title: "Salesforce Connector"
description: "Complete Salesforce CRM integration guide for syncing leads, contacts, accounts, opportunities, and custom objects with Brevo via Tajo."
url: https://tajo.io/docs/connectors/crm/salesforce/
markdown: https://tajo.io/docs/connectors/crm/salesforce.md
lang: en-US
robots: noindex
---

# Salesforce Connector

Connector status: Planned Not built yet. Tajo does not run this connector today.

| Source field | Destination field | Sample value |
| --- | --- | --- |
| `record.id` | `source_id` | `record_1042` |
| `record.updated_at` | `updated_at` | `2026-10-18T08:00:00Z` |
| `record.value` | `value` | `sample_value` |

Connect your Salesforce CRM to Brevo via Tajo for enterprise-grade contact synchronization, lead management, opportunity tracking, and marketing automation powered by your CRM data.

## Overview

| Property | Value |
| --- | --- |
| **Platform** | Salesforce |
| **Category** | CRM |
| **Setup Complexity** | Advanced |
| **Official Integration** | No |
| **Data Synced** | Contacts, Leads, Accounts, Opportunities, Events |
| **API Base URL** | `https://yourInstance.salesforce.com/services/data/vXX.0` |

## Features

- **Bidirectional contact/lead sync** - Sync Salesforce contacts and leads with Brevo contact lists
- **Opportunity tracking** - Map deal stages and amounts for revenue-based segmentation
- **Account hierarchy** - Sync company accounts for account-based marketing in Brevo
- **Custom object mapping** - Map Salesforce custom objects to Brevo attributes and events
- **Campaign member sync** - Sync Salesforce campaign members with Brevo lists
- **Activity tracking** - Sync tasks, events, and email activities for engagement scoring
- **Real-time streaming** - Use Salesforce Streaming API for instant data updates
- **SOQL query support** - Filter synced data with custom SOQL queries

## Prerequisites

Before you begin, ensure you have:

1. A Salesforce org (any edition with API access)
2. A Connected App configured in Salesforce Setup
3. API access enabled for your Salesforce user profile
4. A Brevo account with API access
5. A Tajo account

## Authentication

### OAuth 2.0 Web Server Flow (Recommended)

Best for production integrations with user authorization.

```bash
# Step 1: Authorize
https://login.salesforce.com/services/oauth2/authorize?
  response_type=code&
  client_id={consumer_key}&
  redirect_uri={callback_url}

# Step 2: Exchange code for tokens
curl -X POST https://login.salesforce.com/services/oauth2/token \
  -d "grant_type=authorization_code" \
  -d "code={auth_code}" \
  -d "client_id={consumer_key}" \
  -d "client_secret={consumer_secret}" \
  -d "redirect_uri={callback_url}"
```

### Username-Password Flow

For server-to-server integrations without user interaction.

```bash
curl -X POST https://login.salesforce.com/services/oauth2/token \
  -d "grant_type=password" \
  -d "client_id={consumer_key}" \
  -d "client_secret={consumer_secret}" \
  -d "username={username}" \
  -d "password={password}{security_token}"
```

Security Token

Salesforce requires appending your security token to your password for the username-password flow. Reset your token from Setup > My Personal Information > Reset My Security Token.

## Configuration

### Basic Setup

```yaml
connectors:
  salesforce:
    enabled: true
    instance_url: "https://yourorg.my.salesforce.com"
    api_version: "v59.0"
    auth:
      type: oauth2
      consumer_key: "${SF_CONSUMER_KEY}"
      consumer_secret: "${SF_CONSUMER_SECRET}"
      refresh_token: "${SF_REFRESH_TOKEN}"

    # Data sync options
    sync:
      contacts: true
      leads: true
      accounts: true
      opportunities: true
      campaigns: true

    # Sync direction
    direction: salesforce_to_brevo

    # Brevo list assignment
    lists:
      all_leads: 15
      qualified_leads: 16
      customers: 17
```

### Field Mapping

Map Salesforce fields to Brevo contact attributes:

#### Default Mappings

| Parameter | Type | Description |
| --- | --- | --- |
| `Email` required | string | Contact/Lead email (unique identifier for Brevo) |
| `FirstName` optional | string | Maps to FIRSTNAME attribute in Brevo |
| `LastName` optional | string | Maps to LASTNAME attribute in Brevo |
| `Phone` optional | string | Maps to SMS attribute for WhatsApp/SMS messaging |
| `Account.Name` optional | string | Associated account/company name |
| `LeadSource` optional | string | Lead acquisition source |
| `StageName` optional | string | Opportunity stage for deal tracking |
| `OwnerId` optional | string | Assigned sales rep for routing |

#### Custom Field Mapping

```yaml
field_mapping:
  # Standard fields
  Email: email
  FirstName: FIRSTNAME
  LastName: LASTNAME
  Phone: SMS

  # CRM fields
  LeadSource: LEAD_SOURCE
  Lead_Score__c: LEAD_SCORE
  Account.Name: COMPANY_NAME
  Account.Industry: INDUSTRY

  # Opportunity fields
  Amount: DEAL_VALUE
  StageName: DEAL_STAGE
  CloseDate: EXPECTED_CLOSE_DATE

  # Custom fields
  Preferred_Channel__c: PREFERRED_CHANNEL
  Customer_Tier__c: VIP_TIER
```

## API Endpoints

### REST API Resources

| Method | Endpoint | Description |
| --- | --- | --- |
| `GET` | `/services/data/vXX.0/sobjects/Contact` | Query contacts |
| `POST` | `/services/data/vXX.0/sobjects/Contact` | Create a contact |
| `PATCH` | `/services/data/vXX.0/sobjects/Contact/{id}` | Update a contact |
| `GET` | `/services/data/vXX.0/sobjects/Lead` | Query leads |
| `GET` | `/services/data/vXX.0/sobjects/Account` | Query accounts |
| `GET` | `/services/data/vXX.0/sobjects/Opportunity` | Query opportunities |
| `GET` | `/services/data/vXX.0/query?q={SOQL}` | Execute SOQL query |
| `POST` | `/services/data/vXX.0/composite/sobjects` | Batch create/update |

### Bulk API

| Method | Endpoint | Description |
| --- | --- | --- |
| `POST` | `/services/data/vXX.0/jobs/ingest` | Create bulk ingest job |
| `PUT` | `/services/data/vXX.0/jobs/ingest/{jobId}/batches` | Upload batch data |
| `GET` | `/services/data/vXX.0/jobs/ingest/{jobId}` | Check job status |

### Streaming API

| Endpoint | Description |
| --- | --- |
| `/cometd/XX.0` | CometD long-polling for real-time events |
| PushTopic | Subscribe to record changes via SOQL-based topics |
| Change Data Capture | Stream fine-grained field-level changes |
| Platform Events | Custom event-driven architecture |

## Events

### Record Events (Change Data Capture)

| Event | Trigger | Use Case |
| --- | --- | --- |
| `ContactChangeEvent` | Contact created/updated/deleted | Real-time contact sync |
| `LeadChangeEvent` | Lead created/updated/converted | Lead lifecycle tracking |
| `OpportunityChangeEvent` | Opportunity stage changed | Deal pipeline automation |
| `AccountChangeEvent` | Account record modified | Company data sync |

### Platform Events

| Event | Trigger | Use Case |
| --- | --- | --- |
| `Lead_Converted__e` | Lead converted to contact | Post-conversion nurture |
| `Deal_Won__e` | Opportunity closed-won | Customer onboarding flow |
| `Deal_Lost__e` | Opportunity closed-lost | Win-back campaigns |

## Code Examples

### Initialize Connector

```javascript
import { TajoClient } from '@tajo/sdk';

const tajo = new TajoClient({
  apiKey: process.env.TAJO_API_KEY,
  brevoApiKey: process.env.BREVO_API_KEY
});

// Connect Salesforce
await tajo.connectors.connect('salesforce', {
  instanceUrl: 'https://yourorg.my.salesforce.com',
  consumerKey: process.env.SF_CONSUMER_KEY,
  consumerSecret: process.env.SF_CONSUMER_SECRET,
  refreshToken: process.env.SF_REFRESH_TOKEN
});
```

### Sync Contacts with SOQL Filter

```javascript
// Sync only qualified leads from Salesforce
await tajo.connectors.sync('salesforce', {
  type: 'filtered',
  resources: ['leads'],
  filter: "SELECT Id, Email, FirstName, LastName, LeadScore__c FROM Lead WHERE Status = 'Qualified' AND Email != null",
  brevoListId: 16
});

// Check sync status
const status = await tajo.connectors.status('salesforce');
console.log(status);
// {
//   connected: true,
//   lastSync: '2024-01-15T10:30:00Z',
//   contactsSynced: 18400,
//   leadsSynced: 7200,
//   opportunitiesSynced: 3100
// }
```

### Real-Time Streaming

```javascript
// Subscribe to Salesforce Change Data Capture
await tajo.connectors.stream('salesforce', {
  channels: [
    '/data/ContactChangeEvent',
    '/data/LeadChangeEvent',
    '/data/OpportunityChangeEvent'
  ],
  handler: async (event) => {
    console.log(`Change detected: ${event.entity} ${event.changeType}`);
    // Automatically synced to Brevo by Tajo
  }
});
```

## Rate Limits

Salesforce REST API limits depend on your edition and license count:

| Edition | API Requests per 24 hours |
| --- | --- |
| Developer | 15,000 |
| Enterprise | 1,000 per user license (min 15,000) |
| Unlimited | 5,000 per user license (min 15,000) |
| Performance | 5,000 per user license (min 15,000) |

Additional limits:

- **Concurrent API limit**: 25 long-running requests
- **Bulk API**: 15,000 batches per 24 hours
- **Streaming API**: 2,000 events per day (can be increased)
- **Composite API**: 25 subrequests per composite request

API Usage Monitoring

Monitor your API usage in Salesforce Setup > System Overview. Tajo uses bulk API for large syncs to conserve your API limits.

## Troubleshooting

### Common Issues

| Issue | Cause | Solution |
| --- | --- | --- |
| INVALID\_SESSION\_ID | Token expired | Refresh OAuth token automatically |
| REQUEST\_LIMIT\_EXCEEDED | Daily API limit hit | Use Bulk API or reduce sync frequency |
| FIELD\_INTEGRITY\_EXCEPTION | Required field missing | Map all required fields in configuration |
| DUPLICATES\_DETECTED | Duplicate rules active | Configure duplicate handling preferences |
| INSUFFICIENT\_ACCESS | Missing object permissions | Grant API access in Salesforce profile |

### Debug Mode

Enable verbose logging:

```yaml
connectors:
  salesforce:
    debug: true
    log_level: verbose
    log_api_calls: true
```

### Test Connection

```bash
tajo connectors test salesforce
# ✓ OAuth token valid
# ✓ Contacts accessible
# ✓ Leads accessible
# ✓ Accounts accessible
# ✓ Opportunities accessible
# ✓ Bulk API enabled
```

## Best Practices

1. **Use Bulk API for large syncs** - Switch to Bulk API 2.0 for datasets over 2,000 records
2. **Implement Change Data Capture** - Use CDC for real-time sync instead of polling
3. **Map only needed fields** - Reduce API usage by syncing only required fields
4. **Handle token refresh** - Implement automatic OAuth token refresh logic
5. **Use composite requests** - Combine related API calls to reduce request count
6. **Test in sandbox first** - Use a Salesforce sandbox org before production deployment

## Security

- **OAuth 2.0** - Industry-standard authorization with multiple grant types
- **IP restrictions** - Salesforce supports login IP ranges and trusted IP settings
- **TLS 1.2+** - All API communication encrypted with TLS 1.2 minimum
- **Field-level security** - Granular field access control per profile
- **Session management** - Configurable session timeout and concurrent session limits

## Related Resources

- [Salesforce REST API Documentation](https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/intro_rest.htm)
- [Salesforce Bulk API 2.0 Guide](https://developer.salesforce.com/docs/atlas.en-us.api_asynch.meta/api_asynch/asynch_api_intro.htm)
- [HubSpot Connector](https://tajo.io/docs/connectors/crm/hubspot)
- [Customer Sync Skill](https://tajo.io/docs/skills/data-sync/customer-sync)
- [Brevo Contacts API](https://tajo.io/docs/contact-management)

## Open-Source Implementation Map

No official open-source repository was found in the current Tajo connector catalog for Salesforce. Keep this page focused on the verified public API contract and vendor documentation until an official schema, SDK, MCP server, or public integration repository is available.

### Tajo Revamp Checklist

- Verify authentication and scope requirements against the vendor documentation before each connector release.
- Document primary sync objects, external IDs, pagination strategy, and rate limits explicitly.
- Add smoke tests from public API examples rather than undocumented behavior.
- Capture webhook signature verification and replay protection when the vendor supports webhooks.
- Record gaps where no official public repository or schema exists so future maintainers know what still needs source-backed validation.
