| name | ailey-com-salesforce |
| description | Comprehensive Salesforce CRM integration with automatic edition detection, OAuth authentication, SOQL queries, Bulk API, and complete object management. Supports Developer, Professional, Enterprise, Unlimited, and Performance editions with adaptive feature sets. |
| keywords | ["salesforce","crm","oauth","rest-api","soql","bulk-api","enterprise","sales-cloud","service-cloud"] |
| tools | ["execute","read","write"] |
AI-ley Salesforce Integration
Comprehensive Salesforce CRM integration with automatic edition detection, OAuth 2.0 authentication, and full API access.
Overview
The Salesforce skill provides production-grade integration with Salesforce CRM, including automatic edition detection, OAuth authentication, SOQL queries, Bulk API operations, and comprehensive object management across all Salesforce editions.
Key Features
- Edition Detection: Automatic detection of Salesforce edition (Developer, Professional, Enterprise, Unlimited, Performance)
- OAuth 2.0 Authentication: Secure OAuth flow with Connected App integration
- SOQL Queries: Full SOQL query support with pagination
- Bulk API: High-volume data operations with Bulk API 2.0
- Object Management: CRUD operations on standard and custom objects
- Metadata API: Schema introspection and metadata management
- Streaming API: Real-time event monitoring
- REST API: Complete REST API coverage
- CSV Import/Export: Bulk data import and export with CSV support
- API Limit Tracking: Real-time API usage monitoring and alerts
When to Use
- CRM Integration: Connect applications with Salesforce CRM data
- Data Migration: Import/export large volumes of Salesforce data
- Automation: Automate Salesforce workflows and processes
- Reporting: Extract data for custom reporting and analytics
- Synchronization: Sync Salesforce data with external systems
- Batch Processing: Process large datasets with Bulk API
- Real-time Updates: Monitor Salesforce changes with Streaming API
Salesforce Edition Support
Developer Edition (Free)
- API Calls: 15,000 per 24 hours
- Users: 2
- Storage: 20 MB data + 20 MB files
- Features: Full API access, sandboxes, custom objects
- Best For: Development, testing, learning
Professional Edition
- API Calls: 5,000 per license per 24 hours
- Users: Unlimited (paid per user)
- Storage: 10 GB minimum
- Features: Sales Cloud, Service Cloud, limited customization
- Best For: Small to medium businesses
Enterprise Edition
- API Calls: 100,000 per license per 24 hours
- Users: Unlimited (paid per user)
- Storage: 20 GB minimum
- Features: Advanced customization, workflow automation, API access
- Best For: Large enterprises with complex requirements
Unlimited Edition
- API Calls: Unlimited
- Users: Unlimited (paid per user)
- Storage: Unlimited
- Features: All Enterprise features + premier support
- Best For: Mission-critical enterprise deployments
Performance Edition
- API Calls: Unlimited
- Users: Unlimited (paid per user)
- Storage: Unlimited
- Features: Highest performance, advanced features
- Best For: High-transaction environments
Installation
cd .github/skills/ailey-com-salesforce
npm install
node install.cjs
Setup Instructions
Step 1: Create Salesforce Connected App
-
Log in to Salesforce
- Navigate to Setup (gear icon)
-
Create Connected App
- Go to Apps → App Manager
- Click New Connected App
-
Basic Information
-
API (Enable OAuth Settings)
- Check Enable OAuth Settings
- Callback URL:
http://localhost:3000/oauth/callback
- Selected OAuth Scopes:
- Full access (full)
- Perform requests at any time (refresh_token, offline_access)
- Access and manage your data (api)
- Provide access to custom permissions (custom_permissions)
-
Save and Get Credentials
- Click Save
- Click Continue
- Copy Consumer Key (Client ID)
- Click Click to reveal for Consumer Secret (Client Secret)
Step 2: Configure Environment
Create .env file:
cp .env.example .env
Edit .env:
SALESFORCE_CLIENT_ID=your_consumer_key_here
SALESFORCE_CLIENT_SECRET=your_consumer_secret_here
SALESFORCE_CALLBACK_URL=http://localhost:3000/oauth/callback
SALESFORCE_LOGIN_URL=https://login.salesforce.com
AUTH_METHOD=oauth
Step 3: Authenticate
Run the setup wizard:
npm run setup
This will:
- Detect your Salesforce edition
- Open OAuth flow in browser
- Authenticate and store credentials
- Display API limits and features
Step 4: Verify Connection
npm run diagnose
AI-ley Configuration
Add to .ai-ley/config/integrations.yaml:
salesforce:
type: crm
skill: ailey-com-salesforce
auth:
method: oauth
clientId: ${SALESFORCE_CLIENT_ID}
clientSecret: ${SALESFORCE_CLIENT_SECRET}
callbackUrl: ${SALESFORCE_CALLBACK_URL}
instance:
loginUrl: ${SALESFORCE_LOGIN_URL}
apiVersion: "59.0"
features:
bulkApi: true
streamingApi: true
metadataApi: true
limits:
maxApiCallsPerDay: ${MAX_API_CALLS_PER_DAY}
bulkBatchSize: ${BULK_BATCH_SIZE}
objects:
standard: [Account, Contact, Lead, Opportunity, Case]
custom: ${CUSTOM_OBJECTS}
Quick Start
1. Query Records
npm run query -- "SELECT Id, Name, Industry FROM Account LIMIT 10"
npm run query -- "SELECT Name, Email FROM Contact WHERE Account.Name = 'Acme Corp'"
npm run query -- "SELECT * FROM Opportunity" --output opportunities.csv
2. Create Records
npm run create -- Account '{"Name":"New Account","Industry":"Technology"}'
npm run create -- Contact '{"FirstName":"John","LastName":"Doe","Email":"john@example.com"}'
3. Update Records
npm run update -- Account 001XXXXXXXXXXXXXXX '{"Phone":"555-1234"}'
npm run bulk -- update Account accounts.csv
4. Delete Records
npm run delete -- Account 001XXXXXXXXXXXXXXX
npm run bulk -- delete Lead leads-to-delete.csv
5. Export Data
npm run export -- Account --output accounts.csv
npm run export -- Account --query "Industry = 'Technology'" --output tech-accounts.csv
CLI Commands
setup
Interactive OAuth setup wizard.
npm run setup
Guides through:
- Edition detection
- OAuth authentication
- Credential storage
- Feature verification
detect
Detect Salesforce edition and features.
npm run detect
Edition: Enterprise
API Calls/Day: 100,000
Bulk API: Enabled
Streaming API: Enabled
Custom Objects: 200 limit
query
Execute SOQL queries.
npm run query -- <soql-query> [options]
Options:
-o, --output <file> Export to CSV file
-l, --limit <number> Limit results (default: 2000)
--all Query all records (including deleted)
--format <format> Output format (table, json, csv)
Examples:
npm run query -- "SELECT Id, Name FROM Account"
npm run query -- "SELECT Name, Amount FROM Opportunity WHERE StageName = 'Closed Won'"
npm run query -- "SELECT * FROM Contact" --output contacts.csv
npm run query -- "SELECT Id, Name, IsDeleted FROM Account" --all
create
Create new records.
npm run create -- <object> <json-data>
npm run create -- Account '{"Name":"Acme Corp","Industry":"Technology"}'
npm run create -- Contact --file contacts.json
update
Update existing records.
npm run update -- <object> <record-id> <json-data>
npm run update -- Account 001XXXXXX '{"Phone":"555-1234","Website":"example.com"}'
npm run update -- Contact --file contacts-updates.csv
delete
Delete records.
npm run delete -- <object> <record-id>
npm run delete -- Lead 00QXXXXXX
npm run delete -- Opportunity --file opp-ids.txt
bulk
Bulk operations with Bulk API 2.0.
npm run bulk -- <operation> <object> <csv-file> [options]
Operations: insert, update, upsert, delete
Options:
--batch-size <size> Records per batch (default: 10000)
--external-id <field> External ID field for upsert
--wait Wait for completion
Examples:
npm run bulk -- insert Account accounts.csv
npm run bulk -- upsert Contact contacts.csv --external-id Email__c
npm run bulk -- delete Lead leads.csv --wait
export
Export Salesforce data to CSV.
npm run export -- <object> [options]
Options:
-o, --output <file> Output file (default: <object>.csv)
-q, --query <soql> Custom SOQL WHERE clause
-f, --fields <fields> Comma-separated field list
--all Include all fields
Examples:
npm run export -- Account --output accounts.csv
npm run export -- Opportunity --query "StageName = 'Prospecting'" --output prospects.csv
npm run export -- Contact --fields "FirstName,LastName,Email,Phone"
diagnose
System diagnostics and connection test.
npm run diagnose
npm run diagnose -- --check-auth
npm run diagnose -- --check-limits
npm run diagnose -- --check-features
TypeScript API
Basic Usage
import { SalesforceClient } from './src/index';
const client = new SalesforceClient({
clientId: process.env.SALESFORCE_CLIENT_ID!,
clientSecret: process.env.SALESFORCE_CLIENT_SECRET!,
loginUrl: 'https://login.salesforce.com',
apiVersion: '59.0'
});
await client.authenticate();
const accounts = await client.query('SELECT Id, Name FROM Account LIMIT 10');
console.log(accounts.records);
CRUD Operations
const newAccount = await client.create('Account', {
Name: 'Acme Corp',
Industry: 'Technology',
Phone: '555-1234'
});
const account = await client.retrieve('Account', newAccount.id);
await client.update('Account', newAccount.id, {
Phone: '555-5678',
Website: 'https://acme.com'
});
await client.delete('Account', newAccount.id);
SOQL Queries
const result = await client.query(
'SELECT Id, Name, Email FROM Contact WHERE Account.Name = \'Acme Corp\''
);
const allRecords = await client.queryAll(
'SELECT Id, Name FROM Opportunity WHERE Amount > 10000'
);
const count = await client.query('SELECT COUNT() FROM Lead');
console.log(`Total leads: ${count.totalSize}`);
const summary = await client.query(
'SELECT SUM(Amount), AVG(Amount) FROM Opportunity WHERE StageName = \'Closed Won\''
);
Bulk API Operations
const insertJob = await client.bulk.insert('Account', accounts, {
batchSize: 10000,
wait: true
});
const upsertJob = await client.bulk.upsert('Contact', contacts, {
externalIdField: 'Email__c',
wait: true
});
const deleteJob = await client.bulk.delete('Lead', leadIds);
const jobInfo = await client.bulk.getJobInfo(insertJob.id);
console.log(`Status: ${jobInfo.state}, Processed: ${jobInfo.numberRecordsProcessed}`);
Edition Detection
const edition = await client.detectEdition();
console.log(`Edition: ${edition.edition}`);
console.log(`API Calls/Day: ${edition.apiCallsPerDay}`);
console.log(`Bulk API: ${edition.features.bulkApi ? 'Enabled' : 'Disabled'}`);
const limits = await client.getApiLimits();
console.log(`Daily API Calls Used: ${limits.DailyApiRequests.Used}/${limits.DailyApiRequests.Max}`);
Streaming API
const stream = await client.streaming.subscribe('/data/ChangeEvents', (event) => {
console.log('Change detected:', event);
});
await client.streaming.subscribe('/event/CustomEvent__e', (event) => {
console.log('Custom event received:', event);
});
await stream.unsubscribe();
Metadata API
const metadata = await client.metadata.describe('Account');
console.log(`Fields: ${metadata.fields.length}`);
const objects = await client.metadata.listObjects();
const picklistValues = await client.metadata.getPicklistValues('Account', 'Industry');
Workflows
Workflow 1: Data Migration
Migrate data from external system to Salesforce:
import { SalesforceClient } from './src/index';
import * as fs from 'fs';
import * as csv from 'fast-csv';
const client = new SalesforceClient(config);
await client.authenticate();
const records: any[] = [];
fs.createReadStream('accounts.csv')
.pipe(csv.parse({ headers: true }))
.on('data', (row) => records.push(row))
.on('end', async () => {
const job = await client.bulk.insert('Account', records, {
batchSize: 10000,
wait: true
});
console.log(`Inserted ${job.numberRecordsProcessed} accounts`);
console.log(`Failed: ${job.numberRecordsFailed}`);
});
Workflow 2: Custom Reporting
Extract data for custom reports:
const client = new SalesforceClient(config);
await client.authenticate();
const opps = await client.queryAll(`
SELECT
Id, Name, Amount, StageName, CloseDate,
Account.Name, Account.Industry, Account.AnnualRevenue
FROM Opportunity
WHERE CloseDate = THIS_YEAR
AND StageName IN ('Prospecting', 'Qualification', 'Proposal')
`);
await client.exportToCsv(opps.records, 'opportunities-report.csv');
Workflow 3: Real-time Synchronization
Sync Salesforce changes to external system:
const client = new SalesforceClient(config);
await client.authenticate();
await client.streaming.subscribe('/data/AccountChangeEvent', async (event) => {
if (event.payload.ChangeEventHeader.changeType === 'CREATE') {
await externalSystem.createAccount(event.payload);
} else if (event.payload.ChangeEventHeader.changeType === 'UPDATE') {
await externalSystem.updateAccount(event.payload);
}
});
Workflow 4: Batch Processing
Process records in batches:
const client = new SalesforceClient(config);
await client.authenticate();
const batchSize = 2000;
let offset = 0;
let hasMore = true;
while (hasMore) {
const result = await client.query(
`SELECT Id, Name, Status FROM Lead LIMIT ${batchSize} OFFSET ${offset}`
);
for (const lead of result.records) {
await processLead(lead);
}
offset += batchSize;
hasMore = result.records.length === batchSize;
}
Workflow 5: Data Validation
Validate and clean data:
const client = new SalesforceClient(config);
await client.authenticate();
const contacts = await client.queryAll(
'SELECT Id, Name, Email FROM Contact WHERE Email = null'
);
const updates = [];
for (const contact of contacts.records) {
const validEmail = await validateEmail(contact.Name);
if (validEmail) {
updates.push({ Id: contact.Id, Email: validEmail });
}
}
if (updates.length > 0) {
await client.bulk.update('Contact', updates);
}
Authentication Methods
OAuth 2.0 (Recommended)
Most secure for user-facing applications:
const client = new SalesforceClient({
clientId: process.env.SALESFORCE_CLIENT_ID!,
clientSecret: process.env.SALESFORCE_CLIENT_SECRET!,
callbackUrl: 'http://localhost:3000/oauth/callback',
authMethod: 'oauth'
});
await client.authenticate();
Username-Password (Legacy)
For backward compatibility:
const client = new SalesforceClient({
username: process.env.SALESFORCE_USERNAME!,
password: process.env.SALESFORCE_PASSWORD! + process.env.SALESFORCE_SECURITY_TOKEN!,
authMethod: 'username-password'
});
await client.authenticate();
JWT Bearer Flow (Server-to-Server)
For automation and CI/CD:
const client = new SalesforceClient({
clientId: process.env.SALESFORCE_CLIENT_ID!,
username: process.env.SALESFORCE_USERNAME_JWT!,
privateKeyPath: './certs/server.key',
authMethod: 'jwt'
});
await client.authenticate();
Edition-Specific Features
Developer Edition
const features = {
apiCalls: 15000,
bulkApi: true,
streamingApi: true,
customObjects: 200,
customFields: 500,
sandboxes: false
};
Professional Edition
const features = {
apiCalls: '5000 per license',
bulkApi: false,
streamingApi: false,
customObjects: 10,
customFields: 100,
sandboxes: false
};
Enterprise Edition
const features = {
apiCalls: 100000,
bulkApi: true,
streamingApi: true,
customObjects: 2000,
customFields: 500,
sandboxes: true
};
API Limit Management
Monitor Usage
const limits = await client.getApiLimits();
console.log(`Daily API Calls: ${limits.DailyApiRequests.Used}/${limits.DailyApiRequests.Max}`);
console.log(`Bulk API Jobs: ${limits.DailyBulkApiRequests.Used}/${limits.DailyBulkApiRequests.Max}`);
if (limits.DailyApiRequests.Used > limits.DailyApiRequests.Max * 0.8) {
console.warn('Warning: Approaching API limit!');
}
Automatic Throttling
const client = new SalesforceClient({
...config,
autoThrottle: true,
maxApiCallsPerSecond: 10
});
Error Handling
Common Errors
try {
await client.create('Account', invalidData);
} catch (error) {
if (error.errorCode === 'REQUIRED_FIELD_MISSING') {
console.error('Required field missing:', error.fields);
} else if (error.errorCode === 'DUPLICATE_VALUE') {
console.error('Duplicate record found');
} else if (error.errorCode === 'INVALID_SESSION_ID') {
await client.authenticate();
}
}
Bulk API Errors
const job = await client.bulk.insert('Account', records);
const failures = await client.bulk.getFailedResults(job.id);
for (const failure of failures) {
console.error(`Record failed: ${failure.sf__Id}, Error: ${failure.sf__Error}`);
}
Performance Tips
1. Use Bulk API for Large Operations
for (const record of records) {
await client.create('Account', record);
}
await client.bulk.insert('Account', records);
2. Query Only Needed Fields
await client.query('SELECT * FROM Account');
await client.query('SELECT Id, Name, Industry FROM Account');
3. Use Query Locator for Large Results
const allRecords = await client.queryAll('SELECT Id FROM Account');
4. Batch Operations
const batch = [];
for (const record of records) {
batch.push(record);
if (batch.length === 200) {
await client.createBatch('Account', batch);
batch.length = 0;
}
}
Troubleshooting
| Issue | Cause | Solution |
|---|
| Invalid OAuth credentials | Wrong Client ID/Secret | Verify Connected App credentials |
| Session expired | Token timeout | Re-authenticate with client.authenticate() |
| API limit exceeded | Too many calls | Wait 24 hours or use Bulk API |
| INVALID_FIELD error | Field doesn't exist | Check object metadata |
| REQUIRED_FIELD_MISSING | Missing required field | Add required fields to data |
| UNABLE_TO_LOCK_ROW | Record locked | Retry after delay |
| REQUEST_LIMIT_EXCEEDED | Governor limits | Optimize queries, use Bulk API |
Resources
version: 1.0.0
updated: 2026-02-01
reviewed: 2026-02-01
score: 4.8