go-salesforce
A REST API wrapper for interacting with Salesforce using the Go programming language.

Table of Contents
Installation
go get github.com/k-capehart/go-salesforce/v3
Types
type Salesforce struct {
auth *authentication
config configuration
}
type configuration struct {
compressionHeaders bool
apiVersion string
batchSizeMax int
bulkBatchSizeMax int
httpClient *http.Client
roundTripper http.RoundTripper
shouldValidateAuthentication bool
httpTimeout time.Duration
}
type Creds struct {
Domain string
Username string
Password string
SecurityToken string
ConsumerKey string
ConsumerSecret string
ConsumerRSAPem string
AccessToken string
}
type SalesforceResults struct {
Results []SalesforceResult
HasSalesforceErrors bool
}
type SalesforceResult struct {
Id string
Errors []SalesforceErrorMessage
Success bool
}
type SalesforceErrorMessage struct {
Message string
StatusCode string
Fields []string
}
type BulkJobResults struct {
Id string
State string
NumberRecordsFailed int
ErrorMessage string
SuccessfulRecords []map[string]any
FailedRecords []map[string]any
}
Salesforce tag
- tag struct fields with the
salesforce tag to decode them into their Salesforce API field names
type Account struct {
ExternalID string `salesforce:"ExternalId__c"`
Name string
}
Authentication
Init
func Init(creds Creds, options ...Option) *Salesforce
Returns a new Salesforce instance given a user's credentials.
creds: a struct containing the necessary credentials to authenticate into a Salesforce org
options: optional configuration - see Configuration
- If an operation fails with the Error Code
INVALID_SESSION_ID, go-salesforce will attempt to refresh the session by resubmitting the same credentials used during initialization
- Configuration values are set to the defaults if not specified
Client Credentials Flow
sf, err := salesforce.Init(salesforce.Creds{
Domain: DOMAIN, // ex: https://myslug.my.salesforce.com
ConsumerKey: CONSUMER_KEY,
ConsumerSecret: CONSUMER_SECRET,
})
Username-Password Flow
sf, err := salesforce.Init(salesforce.Creds{
Domain: DOMAIN,
Username: USERNAME,
Password: PASSWORD,
SecurityToken: SECURITY_TOKEN,
ConsumerKey: CONSUMER_KEY,
ConsumerSecret: CONSUMER_SECRET,
})
JWT Bearer Flow
sf, err := salesforce.Init(salesforce.Creds{
Domain: DOMAIN,
Username: USERNAME,
ConsumerKey: CONSUMER_KEY,
ConsumerRSAPem: CONSUMER_RSA_PEM,
})
Authenticate with an Access Token
- Implement your own OAuth flow and use the resulting
access_token from the response to initialize go-salesforce
sf, err := salesforce.Init(salesforce.Creds{
Domain: DOMAIN,
AccessToken: ACCESS_TOKEN,
})
GetAccessToken
func (sf *Salesforce) GetAccessToken() string
Returns the current session's Access Token as a string.
token := sf.GetAccessToken()
GetInstanceUrl
func (sf *Salesforce) GetInstanceUrl() string
Returns the current session's Instance URL as a string.
url := sf.GetInstanceUrl()
GetAuthFlow
func (sf *Salesforce) GetAuthFlow() AuthFlowType
Returns the auth flow used for authentication.
authType := sf.GetAuthFlow()
Configuration
Configure optional parameters for your Salesforce instance
Optional configuration:
func WithCompressionHeaders(compression bool) Option - see docs
func WithAPIVersion(version string) Option - set API version manually instead of using default
func WithBatchSizeMax(size int) - for collections API
func WithBulkBatchSizeMax(size int) Option - for Bulk API
func WithBulkPollTimeout(timeout time.Duration) Option - set max wait when polling bulk results with waitForResults=true
func WithRoundTripper(rt http.RoundTripper) Option - for http requests
func WithHTTPTimeout(timeout time.Duration) Option - set custom timeout
func WithValidateAuthentication(validate bool) Option - optionally skip validation during certain auth flows
Get configuration:
func (sf *Salesforce) GetAPIVersion() string
func (sf *Salesforce) GetBatchSizeMax() int
func (sf *Salesforce) GetBulkBatchSizeMax() int
func (sf *Salesforce) GetCompressionHeaders() bool
func (sf *Salesforce) GetHTTPClient() *http.Client
See HTTP_CLIENT_CONFIG for additional documentation on round trippers
See examples/functional-config and examples/http-config for usage
See WithHeader for custom header options
SOQL
Query Salesforce records
Query
func (sf *Salesforce) Query(query string, sObject any) error
Performs a SOQL query given a query string and decodes the response into the given struct
query: a SOQL query
sObject: a slice of a custom struct type representing a Salesforce Object
type Contact struct {
Id string
LastName string
}
contacts := []Contact{}
err := sf.Query("SELECT Id, LastName FROM Contact WHERE LastName = 'Lee'", &contacts)
QueryStruct
func (sf *Salesforce) QueryStruct(soqlStruct any, sObject any) error
Performs a SOQL query given a go-soql struct and decodes the response into the given struct
soqlStruct: a custom struct using soql tags
sObject: a slice of a custom struct type representing a Salesforce Object
- Review forcedotcom/go-soql
- Eliminates need to separately maintain query string and struct
- Helps prevent SOQL injection
type Contact struct {
Id string `soql:"selectColumn,fieldName=Id" json:"Id"`
LastName string `soql:"selectColumn,fieldName=LastName" json:"LastName"`
}
type ContactQueryCriteria struct {
LastName string `soql:"equalsOperator,fieldName=LastName"`
}
type ContactSoqlQuery struct {
SelectClause Contact `soql:"selectClause,tableName=Contact"`
WhereClause ContactQueryCriteria `soql:"whereClause"`
}
soqlStruct := ContactSoqlQuery{
SelectClause: Contact{},
WhereClause: ContactQueryCriteria{
LastName: "Lee",
},
}
contacts := []Contact{}
err := sf.QueryStruct(soqlStruct, &contacts)
Handling Relationship Queries
When querying Salesforce objects, it's common to access fields that are related through parent-child or lookup relationships. For instance, querying Account.Name with related Contact might look like this:
type Account struct {
Name string
}
type Contact struct {
Id string
Account Account
}
contacts := []Contact{}
sf.Query("SELECT Id, Account.Name FROM Contact", &contacts)
DML
Note that any DML operation that includes an uninitialized struct field, or 0 or null value, will effectively be treated as passing a null value to Salesforce.
type Contact struct {
Id string
LastName string
FirstName string
}
contact := Contact{
Id: "003Dn00000pEYQSIA4",
LastName: "Banner",
}
err = sf.UpdateOne("Contact", contact) // will update the FirstName of the contact to an empty string ""
SObject Single Record Operations
Insert, Update, Upsert, or Delete one record at a time
InsertOne
func (sf *Salesforce) InsertOne(sObjectName string, record any) (SalesforceResult, error)
InsertOne inserts one salesforce record of the given type
sObjectName: API name of Salesforce object
record: a Salesforce object record
type Contact struct {
LastName string
}
contact := Contact{
LastName: "Stark",
}
result, err := sf.InsertOne("Contact", contact)
UpdateOne
func (sf *Salesforce) UpdateOne(sObjectName string, record any) error
Updates one salesforce record of the given type
sObjectName: API name of Salesforce object
record: a Salesforce object record
type Contact struct {
Id string
LastName string
}
contact := Contact{
Id: "003Dn00000pEYQSIA4",
LastName: "Banner",
}
err := sf.UpdateOne("Contact", contact)
UpsertOne
func (sf *Salesforce) UpsertOne(sObjectName string, externalIdFieldName string, record any) (SalesforceResult, error)
Updates (or inserts) one salesforce record using the given external Id
sObjectName: API name of Salesforce object
externalIdFieldName: field API name for an external Id that exists on the given object
record: a Salesforce object record
- A value for the External Id is required
type Contact struct {
ContactExternalId__c string
LastName string
}
contact := Contact{
ContactExternalId__c: "Avng0",
LastName: "Rogers",
}
result, err := sf.UpsertOne("Contact", "ContactExternalId__c", contact)
DeleteOne
func (sf *Salesforce) DeleteOne(sObjectName string, record any) error
Deletes a Salesforce record
sObjectName: API name of Salesforce object
record: a Salesforce object record
- Should only contain an Id
type Contact struct {
Id string
}
contact := Contact{
Id: "003Dn00000pEYQSIA4",
}
err := sf.DeleteOne("Contact", contact)
SObject Collections
Insert, Update, Upsert, or Delete collections of records
- Review Salesforce REST API resources for working with collections
- Perform operations in batches of up to 200 records at a time
- Consider making a Bulk request for very large operations
- Partial successes are enabled
- If a record fails then successes are still committed to the database
- Will return an instance of
SalesforceResults which contains information on each affected record and whether DML errors were encountered
InsertCollection
func (sf *Salesforce) InsertCollection(sObjectName string, records any, batchSize int) (SalesforceResults, error)
Inserts a list of salesforce records of the given type
sObjectName: API name of Salesforce object
records: a slice of salesforce records
batchSize: 1 <= batchSize <= 200
type Contact struct {
LastName string
}
contacts := []Contact{
{
LastName: "Barton",
},
{
LastName: "Romanoff",
},
}
results, err := sf.InsertCollection("Contact", contacts, 200)
UpdateCollection
func (sf *Salesforce) UpdateCollection(sObjectName string, records any, batchSize int) (SalesforceResults, error)
Updates a list of salesforce records of the given type
sObjectName: API name of Salesforce object
records: a slice of salesforce records
batchSize: 1 <= batchSize <= 200
type Contact struct {
Id string
LastName string
}
contacts := []Contact{
{
Id: "003Dn00000pEfyAIAS",
LastName: "Fury",
},
{
Id: "003Dn00000pEfy9IAC",
LastName: "Odinson",
},
}
results, err := sf.UpdateCollection("Contact", contacts, 200)
UpsertCollection
func (sf *Salesforce) UpsertCollection(sObjectName string, externalIdFieldName string, records any, batchSize int) (SalesforceResults, error)
Updates (or inserts) a list of salesforce records using the given ExternalId
sObjectName: API name of Salesforce object
externalIdFieldName: field API name for an external Id that exists on the given object
records: a slice of salesforce records
- A value for the External Id is required
batchSize: 1 <= batchSize <= 200
type Contact struct {
ContactExternalId__c string
LastName string
}
contacts := []Contact{
{
ContactExternalId__c: "Avng1",
LastName: "Danvers",
},
{
ContactExternalId__c: "Avng2",
LastName: "Pym",
},
}
results, err := sf.UpsertCollection("Contact", "ContactExternalId__c", contacts, 200)
DeleteCollection
func (sf *Salesforce) DeleteCollection(sObjectName string, records any, batchSize int) (SalesforceResults, error)
Deletes a list of salesforce records
sObjectName: API name of Salesforce object
records: a slice of salesforce records
batchSize: 1 <= batchSize <= 200
type Contact struct {
Id string
}
contacts := []Contact{
{
Id: "003Dn00000pEfyAIAS",
},
{
Id: "003Dn00000pEfy9IAC",
},
}
results, err := sf.DeleteCollection("Contact", contacts, 200)
Composite Requests
Make numerous 'subrequests' contained within a single 'composite request', reducing the overall number of calls to Salesforce
- Review Salesforce REST API resources for making composite requests
- Up to 25 subrequests may be included in a single composite request
- For DML operations, max number of records to be processed is determined by batch size (
25 * (batch size))
- So if batch size is 1, then max number of records to be included in request is 25
- If batch size is 200, then max is 5000
- If allOrNone is true, then records are only committed to database if everything succeeds
- Will return an instance of SalesforceResults which contains information on each affected record and whether DML errors were encountered
InsertComposite
func (sf *Salesforce) InsertComposite(sObjectName string, records any, batchSize int, allOrNone bool) (SalesforceResults, error)
Inserts a list of salesforce records in a single request
sObjectName: API name of Salesforce object
records: a slice of salesforce records
batchSize: 1 <= batchSize <= 200
allOrNone: denotes whether to roll back entire operation if a record fails
type Contact struct {
LastName string
}
contacts := []Contact{
{
LastName: "Parker",
},
{
LastName: "Murdock",
},
}
results, err := sf.InsertComposite("Contact", contacts, 200, true)
UpdateComposite
func (sf *Salesforce) UpdateComposite(sObjectName string, records any, batchSize int, allOrNone bool) (SalesforceResults, error)
Updates a list of salesforce records in a single request
sObjectName: API name of Salesforce object
records: a slice of salesforce records
batchSize: 1 <= batchSize <= 200
allOrNone: denotes whether to roll back entire operation if a record fails
type Contact struct {
Id string
LastName string
}
contacts := []Contact{
{
Id: "003Dn00000pEi32IAC",
LastName: "Richards",
},
{
Id: "003Dn00000pEi31IAC",
LastName: "Storm",
},
}
results, err := sf.UpdateComposite("Contact", contacts, 200, true)
UpsertComposite
func (sf *Salesforce) UpsertComposite(sObjectName string, externalIdFieldName string, records any, batchSize int, allOrNone bool) (SalesforceResults, error)
Updates (or inserts) a list of salesforce records using the given ExternalId in a single request
sObjectName: API name of Salesforce object
externalIdFieldName: field API name for an external Id that exists on the given object
records: a slice of salesforce records
- A value for the External Id is required
batchSize: 1 <= batchSize <= 200
allOrNone: denotes whether to roll back entire operation if a record fails
type Contact struct {
ContactExternalId__c string
LastName string
}
contacts := []Contact{
{
ContactExternalId__c: "Avng3",
LastName: "Maximoff",
},
{
ContactExternalId__c: "Avng4",
LastName: "Wilson",
},
}
results, err := sf.UpsertComposite("Contact", "ContactExternalId__c", contacts, 200, true)
DeleteComposite
func (sf *Salesforce) DeleteComposite(sObjectName string, records any, batchSize int, allOrNone bool) (SalesforceResults, error)
Deletes a list of salesforce records in a single request
sObjectName: API name of Salesforce object
records: a slice of salesforce records
batchSize: 1 <= batchSize <= 200
allOrNone: denotes whether to roll back entire operation if a record fails
type Contact struct {
Id string
}
contacts := []Contact{
{
Id: "003Dn00000pEi0OIAS",
},
{
Id: "003Dn00000pEi0NIAS",
},
}
results, err := sf.DeleteComposite("Contact", contacts, 200, true)
Bulk v2
Create Bulk API Jobs to query, insert, update, upsert, and delete large collections of records
QueryBulkExport
func (sf *Salesforce) QueryBulkExport(query string, filePath string) error
Performs a query and exports the data to a csv file
filePath: name and path of a csv file to be created
query: a SOQL query
err := sf.QueryBulkExport("SELECT Id, FirstName, LastName FROM Contact", "data/export.csv")
QueryStructBulkExport
func (sf *Salesforce) QueryStructBulkExport(soqlStruct any, filePath string) error
Performs a SOQL query given a go-soql struct and decodes the response into the given struct
filePath: name and path of a csv file to be created
soqlStruct: a custom struct using soql tags
- Review forcedotcom/go-soql
- Eliminates need to separately maintain query string and struct
- Helps prevent SOQL injection
type ContactSoql struct {
Id string `soql:"selectColumn,fieldName=Id" json:"Id"`
FirstName string `soql:"selectColumn,fieldName=FirstName" json:"FirstName"`
LastName string `soql:"selectColumn,fieldName=LastName" json:"LastName"`
}
type ContactSoqlQuery struct {
SelectClause ContactSoql `soql:"selectClause,tableName=Contact"`
}
soqlStruct := ContactSoqlQuery{
SelectClause: ContactSoql{},
}
err := sf.QueryStructBulkExport(soqlStruct, "data/export2.csv")
QueryBulkIterator
func (sf *Salesforce) QueryBulkIterator(query string) (IteratorJob, error)
Performs a query and return a IteratorJob to decode data
type Contact struct {
Id string `json:"Id" csv:"Id"`
FirstName string `json:"FirstName" csv:"FirstName"`
LastName string `json:"LastName" csv:"LastName"`
}
it, err := sf.QueryBulkIterator("SELECT Id, FirstName, LastName FROM Contact")
if err != nil {
panic(err)
}
for it.Next() {
var data []Contact
if err := it.Decode(&data); err != nil {
panic(err)
}
fmt.Println(data)
}
if err := it.Error(); err != nil {
panic(err)
}
Bulk with nested objects
- Nested objects are supported using the
csv tag
- The
csv tag should be formatted as csv:"APIFieldName.,inline"
type ContactWithAltOwner struct {
Id string
AlternateOwnerName User `csv:"Alternate_Owner__r.,inline"`
}
it, err = sf.QueryBulkIterator("SELECT Id, Alternate_Owner__r.Name FROM Contact")
if err != nil {
panic(err)
}
for it.Next() {
var data []Contact
if err := it.Decode(&data); err != nil {
panic(err)
}
fmt.Println(data)
}
if err := it.Error(); err != nil {
panic(err)
}
InsertBulk
func (sf *Salesforce) InsertBulk(sObjectName string, records any, batchSize int, waitForResults bool) ([]string, error)
Inserts a list of salesforce records using Bulk API v2, returning a list of Job IDs
sObjectName: API name of Salesforce object
records: a slice of salesforce records
batchSize: 1 <= batchSize <= 10000
waitForResults: denotes whether to wait for jobs to finish
type Contact struct {
LastName string
}
contacts := []Contact{
{
LastName: "Lang",
},
{
LastName: "Van Dyne",
},
}
jobIds, err := sf.InsertBulk("Contact", contacts, 1000, false)
InsertBulkFile
func (sf *Salesforce) InsertBulkFile(sObjectName string, filePath string, batchSize int, waitForResults bool) ([]string, error)
Inserts a collection of salesforce records from a csv file using Bulk API v2, returning a list of Job IDs
sObjectName: API name of Salesforce object
filePath: path to a csv file containing salesforce data
batchSize: 1 <= batchSize <= 10000
waitForResults: denotes whether to wait for jobs to finish
data/avengers.csv
FirstName,LastName
Tony,Stark
Steve,Rogers
Bruce,Banner
jobIds, err := sf.InsertBulkFile("Contact", "data/avengers.csv", 1000, false)
InsertBulkAssign
func (sf *Salesforce) InsertBulkAssign(sObjectName string, records any, batchSize int, waitForResults bool, assignmentRuleId string) ([]string, error)
Inserts a list of Lead or Case records to be assigned via an Assignment rule, using Bulk API v2, returning a list of Job IDs
sObjectName: API name of Salesforce object (must be Lead or Case)
records: a slice of Lead or Case records
batchSize: 1 <= batchSize <= 10000
waitForResults: denotes whether to wait for jobs to finish
assignmentRuleId: the Salesforce Id of a Lead or Case Assignment Rule
type Lead struct {
LastName string
Company string
}
leads := []Lead{
{
LastName: "Spector",
Company: "The Avengers",
},
}
jobIds, err := sf.InsertBulkAssign("Lead", leads, 100, true, "01QDn00000112FHMAY")
InsertBulkFileAssign
func (sf *Salesforce) InsertBulkFileAssign(sObjectName string, filePath string, batchSize int, waitForResults bool, assignmentRuleId string) ([]string, error)
Inserts a list of Lead or Case records to be assigned via an Assignment rule, from a csv file using Bulk API v2, returning a list of Job IDs
sObjectName: API name of Salesforce object (must be Lead or Case)
filePath: path to a csv file containing Lead or Case data
batchSize: 1 <= batchSize <= 10000
waitForResults: denotes whether to wait for jobs to finish
assignmentRuleId: the Salesforce Id of a Lead or Case Assignment Rule
data/avengers.csv
FirstName,LastName,Company
Tony,Stark,The Avengers
Steve,Rogers,The Avengers
Bruce,Banner,The Avengers
jobIds, err := sf.InsertBulkFileAssign("Lead", "data/avengers.csv", 1000, false, "01QDn00000112FHMAY")
UpdateBulk
func (sf *Salesforce) UpdateBulk(sObjectName string, records any, batchSize int, waitForResults bool) ([]string, error)
Updates a list of salesforce records using Bulk API v2, returning a list of Job IDs
sObjectName: API name of Salesforce object
records: a slice of salesforce records
batchSize: 1 <= batchSize <= 10000
waitForResults: denotes whether to wait for jobs to finish
type Contact struct {
Id string
LastName string
}
contacts := []Contact{
{
Id: "003Dn00000pEsoRIAS",
LastName: "Strange",
},
{
Id: "003Dn00000pEsoSIAS",
LastName: "T'Challa",
},
}
jobIds, err := sf.UpdateBulk("Contact", contacts, 1000, false)
UpdateBulkFile
func (sf *Salesforce) UpdateBulkFile(sObjectName string, filePath string, batchSize int, waitForResults bool) ([]string, error)
Updates a collection of salesforce records from a csv file using Bulk API v2, returning a list of Job IDs
sObjectName: API name of Salesforce object
filePath: path to a csv file containing salesforce data
- An Id is required within csv data
batchSize: 1 <= batchSize <= 10000
waitForResults: denotes whether to wait for jobs to finish
data/update_avengers.csv
Id,FirstName,LastName
003Dn00000pEwRuIAK,Rocket,Raccoon
003Dn00000pEwQxIAK,Drax,The Destroyer
003Dn00000pEwQyIAK,Peter,Quill
003Dn00000pEwQzIAK,I Am,Groot
003Dn00000pEwR0IAK,Gamora,Zen Whoberi Ben Titan
003Dn00000pEwR1IAK,Mantis,Mantis
jobIds, err := sf.UpdateBulkFile("Contact", "data/update_avengers.csv", 1000, false)
UpdateBulkAssign
func (sf *Salesforce) UpdateBulkAssign(sObjectName string, records any, batchSize int, waitForResults bool, assignmentRuleId string) ([]string, error)
Updates a list of Lead or Case records to be assigned via an Assignment rule, using Bulk API v2, returning a list of Job IDs
sObjectName: API name of Salesforce object (must be Lead or Case)
records: a slice of Lead or Case records
batchSize: 1 <= batchSize <= 10000
waitForResults: denotes whether to wait for jobs to finish
assignmentRuleId: the Salesforce Id of a Lead or Case Assignment Rule
type Lead struct {
Id string
LastName string
Company string
}
leads := []Lead{
{
Id: "00QDn0000024r6FMAQ",
LastName: "Grant",
Company: "The Avengers",
},
}
jobIds, err := sf.UpdateBulkAssign("Lead", leads, 100, true, "01QDn00000112FHMAY")
UpdateBulkFileAssign
func (sf *Salesforce) UpdateBulkFileAssign(sObjectName string, filePath string, batchSize int, waitForResults bool, assignmentRuleId string) ([]string, error)
Updates a list of Lead or Case records to be assigned via an Assignment rule, from a csv file using Bulk API v2, returning a list of Job IDs
sObjectName: API name of Salesforce object (must be Lead or Case)
filePath: path to a csv file containing Lead or Case data
batchSize: 1 <= batchSize <= 10000
waitForResults: denotes whether to wait for jobs to finish
assignmentRuleId: the Salesforce Id of a Lead or Case Assignment Rule
data/update_avengers.csv
Id,FirstName,LastName,Company
00QDn0000024r6WMAQ,Clint,Barton,The Avengers
00QDn0000024r6VMAQ,Natasha,Romanoff,The Avengers
00QDn0000024r6UMAQ,Hank,Pym,The Avengers
jobIds, err := sf.UpdateBulkFileAssign("Lead", "data/update_avengers.csv", 100, true, "01QDn00000112FHMAY")
UpsertBulk
func (sf *Salesforce) UpsertBulk(sObjectName string, externalIdFieldName string, records any, batchSize int, waitForResults bool) ([]string, error)
Updates (or inserts) a list of salesforce records using Bulk API v2, returning a list of Job IDs
sObjectName: API name of Salesforce object
externalIdFieldName: field API name for an external Id that exists on the given object
records: a slice of salesforce records
- A value for the External Id is required
batchSize: 1 <= batchSize <= 10000
waitForResults: denotes whether to wait for jobs to finish
type Contact struct {
ContactExternalId__c string
LastName string
}
contacts := []Contact{
{
ContactExternalId__c: "Avng5",
LastName: "Rhodes",
},
{
ContactExternalId__c: "Avng6",
LastName: "Quill",
},
}
jobIds, err := sf.UpsertBulk("Contact", "ContactExternalId__c", contacts, 1000, false)
UpsertBulkFile
func (sf *Salesforce) UpsertBulkFile(sObjectName string, externalIdFieldName string, filePath string, batchSize int, waitForResults bool) ([]string, error)
Updates (or inserts) a collection of salesforce records from a csv file using Bulk API v2, returning a list of Job IDs
sObjectName: API name of Salesforce object
externalIdFieldName: field API name for an external Id that exists on the given object
filePath: path to a csv file containing salesforce data
- A value for the External Id is required within csv data
batchSize: 1 <= batchSize <= 10000
waitForResults: denotes whether to wait for jobs to finish
data/upsert_avengers.csv
ContactExternalId__c,FirstName,LastName
Avng7,Matt,Murdock
Avng8,Luke,Cage
Avng9,Jessica,Jones
Avng10,Danny,Rand
jobIds, err := sf.UpsertBulkFile("Contact", "ContactExternalId__c", "data/upsert_avengers.csv", 1000, false)
UpsertBulkAssign
func (sf *Salesforce) UpsertBulkAssign(sObjectName string, externalIdFieldName string, records any, batchSize int, waitForResults bool, assignmentRuleId string) ([]string, error)
Updates (or inserts) a list of Lead or Case records to be assigned via an Assignment rule, using Bulk API v2, returning a list of Job IDs
sObjectName: API name of Salesforce object (must be Lead or Case)
externalIdFieldName: field API name for an external Id that exists on the given object
records: a slice of Lead or Case records
batchSize: 1 <= batchSize <= 10000
waitForResults: denotes whether to wait for jobs to finish
assignmentRuleId: the Salesforce Id of a Lead or Case Assignment Rule
type Lead struct {
LeadExternalId__c string
LastName string
Company string
}
leads := []Lead{
{
LeadExternalId__c: "MK3",
LastName: "Lockley",
Company: "The Avengers",
},
}
jobIds, err := sf.UpsertBulkAssign("Lead", "LeadExternalId__c", leads, 100, true, "00QDn0000024r6FMAQ")
UpsertBulkFileAssign
func (sf *Salesforce) UpsertBulkFileAssign(sObjectName string, externalIdFieldName string, filePath string, batchSize int, waitForResults bool, assignmentRuleId string) ([]string, error)
Updates (or inserts) a list of Lead or Case records to be assigned via an Assignment rule, from a csv file using Bulk API v2, returning a list of Job IDs
sObjectName: API name of Salesforce object (must be Lead or Case)
externalIdFieldName: field API name for an external Id that exists on the given object
filePath: path to a csv file containing salesforce data
- A value for the External Id is required within csv data
batchSize: 1 <= batchSize <= 10000
waitForResults: denotes whether to wait for jobs to finish
assignmentRuleId: the Salesforce Id of a Lead or Case Assignment Rule
data/upsert_avengers
LeadExternalId__c,FirstName,LastName,Company
Avng11,Nick,Fury,The Avengers
Avng12,Maria,Hill,The Avengers
Avng13,Howard,Stark,The Avengers
jobIds, err := sf.UpsertBulkFileAssign("Lead", "LeadExternalId__c", "data/upsert_avengers.csv", 100, true, "01QDn00000112FHMAY")
DeleteBulk
func (sf *Salesforce) DeleteBulk(sObjectName string, records any, batchSize int, waitForResults bool) ([]string, error)
Deletes a list of salesforce records using Bulk API v2, returning a list of Job IDs
sObjectName: API name of Salesforce object
records: a slice of salesforce records
batchSize: 1 <= batchSize <= 10000
waitForResults: denotes whether to wait for jobs to finish
type Contact struct {
Id string
}
contacts := []ContactIds{
{
Id: "003Dn00000pEsoRIAS",
},
{
Id: "003Dn00000pEsoSIAS",
},
}
jobIds, err := sf.DeleteBulk("Contact", contacts, 1000, false)
DeleteBulkFile
func (sf *Salesforce) DeleteBulkFile(sObjectName string, filePath string, batchSize int, waitForResults bool) ([]string, error)
Deletes a collection of salesforce records from a csv file using Bulk API v2, returning a list of Job IDs
sObjectName: API name of Salesforce object
filePath: path to a csv file containing salesforce data
batchSize: 1 <= batchSize <= 10000
waitForResults: denotes whether to wait for jobs to finish
data/delete_avengers.csv
Id
003Dn00000pEwRuIAK
003Dn00000pEwQxIAK
003Dn00000pEwQyIAK
003Dn00000pEwQzIAK
003Dn00000pEwR0IAK
003Dn00000pEwR1IAK
jobIds, err := sf.DeleteBulkFile("Contact", "data/delete_avengers.csv", 1000, false)
GetJobResults
func (sf *Salesforce) GetJobResults(bulkJobId string) (BulkJobResults, error)
Returns an instance of BulkJobResults given a Job Id
bulkJobId: the Id for a bulk API job
- Use to check results of Bulk Job, including successful and failed records
type Contact struct {
LastName string
}
contacts := []Contact{
{
LastName: "Grimm",
},
}
jobIds, err := sf.InsertBulk("Contact", contacts, 1000, true)
if err != nil {
panic(err)
}
for _, id := range jobIds {
results, err := sf.GetJobResults(id) // returns an instance of BulkJobResults
if err != nil {
panic(err)
}
fmt.Println(results)
}
Other
DoRequest
func (sf *Salesforce) DoRequest(method string, uri string, body []byte, opts ...RequestOption) (*http.Response, error)
Make a http call to Salesforce, returning a response to be parsed by the client
method: request method ("GET", "POST", "PUT", "PATCH", "DELETE")
uri: uniform resource identifier (include everything after /services/data/apiVersion)
body: json encoded body to be included in request
opts: optional request options (currently supports custom headers via WithHeader)
Example to call the /limits endpoint
resp, err := sf.DoRequest(http.MethodGet, "/limits", nil)
if err != nil {
panic(err)
}
respBody, err := io.ReadAll(resp.Body)
if err != nil {
panic(err)
}
fmt.Println(string(respBody))
func WithHeader(key, value string) RequestOption
Creates a request option that sets a custom header on the HTTP request
key: the header name
value: the header value
// Use If-Modified-Since for efficient caching
resp, err := sf.DoRequest("GET", "/sobjects/Account/describe", nil,
salesforce.WithHeader("If-Modified-Since", "Wed, 21 Oct 2015 07:28:00 GMT"))
if err != nil {
panic(err)
}
if resp.StatusCode == 304 {
fmt.Println("Data not modified, using cached version")
}
// Multiple custom headers
resp, err := sf.DoRequest("GET", "/sobjects", nil,
salesforce.WithHeader("If-Modified-Since", "Wed, 21 Oct 2015 07:28:00 GMT"),
salesforce.WithHeader("Accept-Language", "en-US"))