Salesforce Integration for ChatGPT SaaS Apps
Integrating Salesforce with ChatGPT unlocks enterprise CRM data for 800 million ChatGPT users, enabling businesses to automate workflows, query customer data, and create conversational experiences without leaving the chat interface. This guide shows you how to build a production-ready Salesforce ChatGPT integration using Connected Apps, SOQL queries, and the Salesforce REST API.
Whether you're building a sales assistant that pulls opportunity data, a customer service bot that queries case histories, or a marketing automation app that syncs leads, this tutorial covers everything you need to know about Salesforce ChatGPT integration.
This article is part of our comprehensive guide on Building ChatGPT Applications.
Salesforce Platform Overview
Salesforce is the world's #1 CRM platform, powering customer data for 150,000+ companies. For ChatGPT app developers, Salesforce offers three primary APIs for accessing CRM data: REST API, SOAP API, and Bulk API.
REST API vs SOAP API vs Bulk API
Understanding which Salesforce API to use for your ChatGPT integration is critical for performance and scalability:
REST API (Recommended for ChatGPT Apps)
- Modern HTTP/JSON interface
- Perfect for real-time queries (contacts, accounts, opportunities)
- Rate limit: 15,000 API calls per 24 hours (adjustable by license)
- Best for: User-initiated queries in ChatGPT conversations
SOAP API
- XML-based legacy interface
- More verbose than REST but supports complex transactions
- Same rate limits as REST API
- Best for: Enterprise integrations requiring ACID transactions
Bulk API
- Designed for large data operations (10,000+ records)
- Asynchronous processing
- Separate rate limits (10,000 batches per 24 hours)
- Best for: Batch sync operations, data migration, reporting
For most ChatGPT apps, the REST API is your best choice. It provides low-latency responses (critical for chat UX), uses familiar JSON syntax, and integrates seamlessly with Node.js and Python MCP servers.
Common Salesforce Objects
Salesforce organizes CRM data into objects (similar to database tables). Here are the most commonly used objects for ChatGPT integrations:
Account - Companies and organizations
- Fields:
Name,Industry,AnnualRevenue,NumberOfEmployees - Use case: "Show me all accounts in the healthcare industry with revenue over $10M"
Contact - Individual people associated with accounts
- Fields:
FirstName,LastName,Email,Phone,AccountId - Use case: "Find the primary contact for Acme Corporation"
Opportunity - Sales deals and pipeline
- Fields:
Name,Amount,StageName,CloseDate,Probability - Use case: "What's our total pipeline value for Q1 2026?"
Lead - Potential customers not yet qualified
- Fields:
FirstName,LastName,Company,Email,Status - Use case: "Show me all leads from last week's webinar"
Case - Customer support tickets
- Fields:
Subject,Status,Priority,Description,ContactId - Use case: "How many open high-priority cases do we have?"
These objects form the foundation of most Salesforce ChatGPT integrations. Understanding their relationships (e.g., Contact.AccountId links to Account.Id) is essential for writing effective SOQL queries.
Connected App Setup
To integrate Salesforce with ChatGPT, you must create a Connected App in Salesforce. This establishes OAuth 2.0 credentials that allow your ChatGPT app to authenticate users and access their CRM data securely.
Creating a Connected App
Follow these steps to create a Salesforce Connected App for your ChatGPT integration:
Step 1: Navigate to Setup
- Log into Salesforce as an administrator
- Click the gear icon (⚙️) in the top-right corner
- Select Setup from the dropdown
Step 2: Create Connected App
- In Quick Find, search for "App Manager"
- Click App Manager in the sidebar
- Click New Connected App button
Step 3: Configure Basic Information
Connected App Name: ChatGPT Integration
API Name: ChatGPT_Integration (auto-generated)
Contact Email: your-email@company.com
Step 4: Enable OAuth Settings
- Check Enable OAuth Settings
- Set Callback URL:
https://yourdomain.com/oauth/callback - Add Selected OAuth Scopes:
api(Access and manage your data)refresh_token(Perform requests on your behalf at any time)offline_access(Perform requests at any time)
- Check Require Secret for Web Server Flow (recommended)
Step 5: Save and Retrieve Credentials
- Click Save (takes 2-10 minutes to activate)
- Navigate to App Manager > Find your app > Click View
- Copy Consumer Key (Client ID)
- Click Click to reveal for Consumer Secret (Client Secret)
Step 6: Configure Connected App Policies
- Edit the Connected App
- Under OAuth Policies, set:
- Permitted Users: Admin approved users are pre-authorized
- IP Relaxation: Relax IP restrictions (for development)
- Refresh Token Policy: Refresh token is valid until revoked
Security Note: Store your Consumer Key and Consumer Secret in environment variables. NEVER commit them to version control.
OAuth 2.0 JWT Bearer Flow
For server-to-server integrations (most ChatGPT apps), use the OAuth 2.0 JWT Bearer flow. This allows your MCP server to authenticate without requiring user login for every request.
Prerequisites:
- Generate RSA key pair:
# Generate private key
openssl genrsa -out server.key 2048
# Generate public key
openssl req -new -x509 -key server.key -out server.crt -days 365
- Upload
server.crtto Salesforce Connected App:- Setup > App Manager > Your App > Edit
- Check Use digital signatures
- Upload
server.crtfile
Node.js Implementation:
// salesforce-auth.js
const jwt = require('jsonwebtoken');
const axios = require('axios');
const fs = require('fs');
class SalesforceAuth {
constructor() {
this.clientId = process.env.SALESFORCE_CLIENT_ID;
this.username = process.env.SALESFORCE_USERNAME;
this.loginUrl = process.env.SALESFORCE_LOGIN_URL || 'https://login.salesforce.com';
this.privateKey = fs.readFileSync('./certs/server.key', 'utf8');
}
// Generate JWT token
generateJWT() {
const payload = {
iss: this.clientId, // Consumer Key
sub: this.username, // Salesforce username
aud: this.loginUrl, // https://login.salesforce.com or https://test.salesforce.com
exp: Math.floor(Date.now() / 1000) + 300 // 5 minutes expiration
};
return jwt.sign(payload, this.privateKey, { algorithm: 'RS256' });
}
// Exchange JWT for access token
async getAccessToken() {
const jwtToken = this.generateJWT();
try {
const response = await axios.post(`${this.loginUrl}/services/oauth2/token`,
new URLSearchParams({
grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
assertion: jwtToken
}),
{
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
}
);
return {
accessToken: response.data.access_token,
instanceUrl: response.data.instance_url // e.g., https://yourinstance.salesforce.com
};
} catch (error) {
throw new Error(`Salesforce OAuth failed: ${error.response?.data?.error_description || error.message}`);
}
}
}
module.exports = SalesforceAuth;
Usage in MCP Server:
const SalesforceAuth = require('./salesforce-auth');
const sfAuth = new SalesforceAuth();
const { accessToken, instanceUrl } = await sfAuth.getAccessToken();
// Use accessToken for Salesforce API calls
Rate Limits:
- JWT Bearer flow is exempt from login rate limits
- Standard API call limits still apply (15,000 per 24 hours)
- Recommendation: Cache access tokens for their lifetime (~2 hours)
SOQL Queries
SOQL (Salesforce Object Query Language) is SQL-like syntax for querying Salesforce data. Mastering SOQL is essential for building effective Salesforce ChatGPT integrations.
Basic SOQL Query Structure
The basic SOQL syntax follows this pattern:
SELECT field1, field2, field3
FROM ObjectName
WHERE condition
ORDER BY field
LIMIT number
Example: Query All Contacts
SELECT Id, FirstName, LastName, Email, Phone
FROM Contact
WHERE AccountId = '001...'
ORDER BY CreatedDate DESC
LIMIT 100
Node.js Implementation:
const axios = require('axios');
async function queryContacts(accessToken, instanceUrl, accountId) {
const query = `
SELECT Id, FirstName, LastName, Email, Phone
FROM Contact
WHERE AccountId = '${accountId}'
ORDER BY CreatedDate DESC
LIMIT 100
`;
const response = await axios.get(`${instanceUrl}/services/data/v59.0/query`, {
params: { q: query },
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json'
}
});
return response.data.records; // Array of Contact objects
}
SOQL Query Patterns for ChatGPT Apps
Here are common query patterns for ChatGPT integrations:
1. Search by Name (Case-Insensitive)
SELECT Id, Name, Industry, AnnualRevenue
FROM Account
WHERE Name LIKE '%Acme%'
ORDER BY Name
LIMIT 10
2. Filter by Date Range
SELECT Id, Name, Amount, CloseDate, StageName
FROM Opportunity
WHERE CloseDate >= 2026-01-01 AND CloseDate <= 2026-03-31
ORDER BY Amount DESC
3. Aggregate Functions (COUNT, SUM, AVG)
SELECT StageName, SUM(Amount) total, COUNT(Id) count
FROM Opportunity
WHERE CloseDate = THIS_QUARTER
GROUP BY StageName
4. Relationship Queries (Parent-to-Child)
SELECT Id, Name,
(SELECT FirstName, LastName, Email FROM Contacts)
FROM Account
WHERE Industry = 'Technology'
LIMIT 5
5. Relationship Queries (Child-to-Parent)
SELECT Id, FirstName, LastName, Account.Name, Account.Industry
FROM Contact
WHERE Account.Industry = 'Healthcare'
LIMIT 20
Query Optimization Best Practices
SOQL queries count against your API rate limits. Optimize for performance:
1. Use Selective Filters
- Filter on indexed fields when possible:
Id,Name,OwnerId,CreatedDate,SystemModstamp - Avoid:
WHERE Description LIKE '%keyword%'(full table scan) - Prefer:
WHERE Name LIKE 'Acme%'(index-friendly prefix match)
2. Limit Result Sets
- Always use
LIMITclause (max 2,000 records per query) - For large datasets, implement pagination with
OFFSETorqueryMoreAPI
// Pagination example
async function queryAllOpportunities(accessToken, instanceUrl) {
let allRecords = [];
let nextRecordsUrl = null;
const query = `
SELECT Id, Name, Amount, StageName
FROM Opportunity
WHERE StageName = 'Closed Won'
ORDER BY CloseDate DESC
`;
let response = await axios.get(`${instanceUrl}/services/data/v59.0/query`, {
params: { q: query },
headers: { 'Authorization': `Bearer ${accessToken}` }
});
allRecords = response.data.records;
nextRecordsUrl = response.data.nextRecordsUrl;
// Fetch additional pages if needed
while (nextRecordsUrl) {
response = await axios.get(`${instanceUrl}${nextRecordsUrl}`, {
headers: { 'Authorization': `Bearer ${accessToken}` }
});
allRecords.push(...response.data.records);
nextRecordsUrl = response.data.nextRecordsUrl;
}
return allRecords;
}
3. Select Only Required Fields
- Avoid:
SELECT Id, Name, ... (50 fields) - Prefer:
SELECT Id, Name, Amount, CloseDate(only what you need) - Smaller payloads = faster responses = better chat UX
4. Use Query Plan Analysis Test query performance with the Query Plan tool:
EXPLAIN SELECT Id, Name FROM Account WHERE Name LIKE 'Acme%'
Salesforce returns execution plan showing index usage and estimated cost.
Error Handling for SOQL Queries
Always handle SOQL errors gracefully in ChatGPT apps:
async function safeSoqlQuery(accessToken, instanceUrl, query) {
try {
const response = await axios.get(`${instanceUrl}/services/data/v59.0/query`, {
params: { q: query },
headers: { 'Authorization': `Bearer ${accessToken}` }
});
return response.data.records;
} catch (error) {
if (error.response?.status === 401) {
throw new Error('Salesforce session expired. Please re-authenticate.');
} else if (error.response?.data?.[0]?.errorCode === 'INVALID_FIELD') {
throw new Error(`Invalid field in SOQL query: ${error.response.data[0].message}`);
} else if (error.response?.data?.[0]?.errorCode === 'MALFORMED_QUERY') {
throw new Error(`Malformed SOQL query: ${error.response.data[0].message}`);
} else {
throw new Error(`Salesforce query failed: ${error.message}`);
}
}
}
Object Management
Beyond querying data, Salesforce ChatGPT integrations often need to create, update, and delete CRM objects. The Salesforce REST API provides simple endpoints for these operations.
Creating Records
Use the sobjects endpoint to create new records:
Create Contact Example:
async function createContact(accessToken, instanceUrl, contactData) {
const response = await axios.post(
`${instanceUrl}/services/data/v59.0/sobjects/Contact`,
{
FirstName: contactData.firstName,
LastName: contactData.lastName,
Email: contactData.email,
Phone: contactData.phone,
AccountId: contactData.accountId // Link to parent Account
},
{
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json'
}
}
);
return response.data.id; // Returns new Contact ID
}
Create Opportunity with Products:
async function createOpportunity(accessToken, instanceUrl, oppData) {
const response = await axios.post(
`${instanceUrl}/services/data/v59.0/sobjects/Opportunity`,
{
Name: oppData.name,
AccountId: oppData.accountId,
StageName: 'Prospecting',
CloseDate: oppData.closeDate, // Format: YYYY-MM-DD
Amount: oppData.amount,
Probability: 10,
OwnerId: oppData.ownerId
},
{
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json'
}
}
);
return response.data.id;
}
Updating Records
Use the PATCH method to update existing records:
async function updateOpportunityStage(accessToken, instanceUrl, oppId, newStage) {
await axios.patch(
`${instanceUrl}/services/data/v59.0/sobjects/Opportunity/${oppId}`,
{
StageName: newStage,
Probability: getStageProbability(newStage) // Helper function
},
{
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json'
}
}
);
}
function getStageProbability(stage) {
const stageMap = {
'Prospecting': 10,
'Qualification': 25,
'Proposal': 50,
'Negotiation': 75,
'Closed Won': 100,
'Closed Lost': 0
};
return stageMap[stage] || 0;
}
Deleting Records
Use the DELETE method to remove records:
async function deleteContact(accessToken, instanceUrl, contactId) {
await axios.delete(
`${instanceUrl}/services/data/v59.0/sobjects/Contact/${contactId}`,
{
headers: { 'Authorization': `Bearer ${accessToken}` }
}
);
}
Warning: Deleting records is permanent (unless Recycle Bin recovery is enabled). Always confirm with users before deleting CRM data.
Bulk Operations with Composite API
For creating/updating multiple records efficiently, use the Composite API:
async function bulkCreateContacts(accessToken, instanceUrl, contacts) {
const compositeRequest = {
allOrNone: false, // Continue on errors
compositeRequest: contacts.map((contact, index) => ({
method: 'POST',
url: `/services/data/v59.0/sobjects/Contact`,
referenceId: `contact${index}`,
body: contact
}))
};
const response = await axios.post(
`${instanceUrl}/services/data/v59.0/composite`,
compositeRequest,
{
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json'
}
}
);
return response.data.compositeResponse; // Array of results
}
Benefits of Composite API:
- Reduced API calls (up to 25 sub-requests per composite call)
- Better performance (single round-trip vs multiple sequential calls)
- Atomic transactions (with
allOrNone: true)
Apex Integration
For advanced use cases, Salesforce ChatGPT integrations can leverage Apex (Salesforce's proprietary Java-like language) to implement custom business logic.
When to Use Apex
Use Apex for:
- Complex validations not possible with standard API calls
- Triggers that fire automatically on record changes
- Batch processing of large datasets (10,000+ records)
- Custom REST endpoints exposing proprietary logic
Exposing Apex as REST Endpoint
@RestResource(urlMapping='/chatgpt/opportunities/*')
global with sharing class ChatGPTOpportunityAPI {
@HttpGet
global static List<Opportunity> getTopOpportunities() {
return [
SELECT Id, Name, Amount, StageName, CloseDate, Account.Name
FROM Opportunity
WHERE StageName IN ('Proposal', 'Negotiation')
AND Amount > 50000
ORDER BY Amount DESC
LIMIT 10
];
}
@HttpPost
global static String createOpportunityWithProducts(
String accountId,
String oppName,
Decimal amount,
Date closeDate,
List<String> productIds
) {
// Complex logic: create Opportunity + OpportunityLineItems in single transaction
Savepoint sp = Database.setSavepoint();
try {
Opportunity opp = new Opportunity(
Name = oppName,
AccountId = accountId,
Amount = amount,
CloseDate = closeDate,
StageName = 'Prospecting'
);
insert opp;
// Add products (simplified example)
List<OpportunityLineItem> lineItems = new List<OpportunityLineItem>();
for (String productId : productIds) {
lineItems.add(new OpportunityLineItem(
OpportunityId = opp.Id,
Product2Id = productId,
Quantity = 1,
UnitPrice = amount / productIds.size()
));
}
insert lineItems;
return opp.Id;
} catch (Exception e) {
Database.rollback(sp);
throw new CustomException('Failed to create opportunity: ' + e.getMessage());
}
}
}
Calling Apex REST from Node.js:
async function callApexEndpoint(accessToken, instanceUrl) {
const response = await axios.get(
`${instanceUrl}/services/apexrest/chatgpt/opportunities`,
{
headers: { 'Authorization': `Bearer ${accessToken}` }
}
);
return response.data;
}
Note: Apex REST endpoints require
@RestResourceannotation and governor limit awareness (max 10,000 SOQL queries, 150 DML statements per transaction).
Real-World ChatGPT Integration Example
Here's a complete example of a ChatGPT MCP server tool for querying Salesforce opportunities:
// mcp-server.js
const { MCPServer } = require('@modelcontextprotocol/sdk');
const SalesforceAuth = require('./salesforce-auth');
const axios = require('axios');
const server = new MCPServer({
name: 'salesforce-integration',
version: '1.0.0'
});
// Tool: Get Pipeline Summary
server.addTool({
name: 'get_pipeline_summary',
description: 'Get a summary of sales pipeline by stage',
parameters: {
type: 'object',
properties: {
quarter: {
type: 'string',
description: 'Quarter to analyze (e.g., Q1 2026)',
enum: ['Q1 2026', 'Q2 2026', 'Q3 2026', 'Q4 2026']
}
},
required: ['quarter']
},
handler: async ({ quarter }) => {
const sfAuth = new SalesforceAuth();
const { accessToken, instanceUrl } = await sfAuth.getAccessToken();
const query = `
SELECT StageName, SUM(Amount) totalValue, COUNT(Id) count
FROM Opportunity
WHERE CloseDate >= ${getQuarterStart(quarter)}
AND CloseDate <= ${getQuarterEnd(quarter)}
GROUP BY StageName
ORDER BY totalValue DESC
`;
const response = await axios.get(`${instanceUrl}/services/data/v59.0/query`, {
params: { q: query },
headers: { 'Authorization': `Bearer ${accessToken}` }
});
return {
structuredContent: {
type: 'inline',
cards: response.data.records.map(record => ({
title: record.StageName,
metadata: [
{ label: 'Total Value', value: `$${(record.totalValue / 1000000).toFixed(1)}M` },
{ label: 'Opportunities', value: record.count.toString() }
]
}))
}
};
}
});
function getQuarterStart(quarter) {
const [q, year] = quarter.split(' ');
const month = (parseInt(q.substring(1)) - 1) * 3 + 1;
return `${year}-${month.toString().padStart(2, '0')}-01`;
}
function getQuarterEnd(quarter) {
const [q, year] = quarter.split(' ');
const month = parseInt(q.substring(1)) * 3;
const lastDay = new Date(year, month, 0).getDate();
return `${year}-${month.toString().padStart(2, '0')}-${lastDay}`;
}
server.start();
This MCP server enables ChatGPT users to ask: "What's our Q1 2026 pipeline?" and receive structured data cards showing opportunities by stage.
Related Articles
- window.openai API Reference — Technical API patterns for ChatGPT app development
- Legal Document Automation via ChatGPT — Another advanced integration pattern for professional services
- Healthcare ChatGPT Apps — EHR/EMR integration strategies for medical practices
Conclusion
Integrating Salesforce with ChatGPT transforms enterprise CRM into a conversational interface accessible to 800 million users. By following this guide, you've learned how to:
- ✅ Set up Salesforce Connected Apps with OAuth 2.0
- ✅ Authenticate using JWT Bearer flow for server-to-server integrations
- ✅ Query CRM data with optimized SOQL queries
- ✅ Create, update, and delete Salesforce objects via REST API
- ✅ Leverage Apex for advanced custom logic
Key Takeaways:
- Use REST API for real-time ChatGPT queries (best performance)
- Implement JWT Bearer flow for seamless authentication
- Optimize SOQL queries with selective filters and indexed fields
- Handle errors gracefully to maintain chat UX quality
- Cache access tokens to reduce authentication overhead
Next Steps:
- Create your Salesforce Connected App
- Generate RSA key pair for JWT authentication
- Build your first MCP server tool (start with a simple SOQL query)
- Test in ChatGPT developer mode
- Deploy to production and submit to ChatGPT App Store
Want to build Salesforce ChatGPT integrations without writing code? Try MakeAIHQ's no-code app builder - from zero to ChatGPT App Store in 48 hours. No OAuth configuration, no SOQL syntax, no deployment headaches. Just describe your integration in plain English, and our AI builds it for you.
Start your free trial: https://makeaihq.com/signup