See Also:
4. Optionally, the client application saves the request timestamp for future reference
A client application likely performs other tasks associated with data replication operations. For example, if an opportunity were to become closed, a client application might run a new revenue report. Similarly, if a task were completed, the process might log this somehow in another system.
Sample Code—Java
private void getUpdatedSample() { try {
// You can use the server timestamp as known point in time
Calendar serverTime = binding.getServerTimestamp().getTimestamp();
// Create a start time value for the call
GregorianCalendar startTime = (GregorianCalendar) serverTime.clone();
// Create an end time value for the call
GregorianCalendar endTime = (GregorianCalendar) serverTime;
// subtract 5 mins from the server time so
// that we have a valid time frame, you can use just // about any timespan you want, 5 minutes is arbitrary startTime.add(GregorianCalendar.MINUTE, -5);
System.out.println("Checking updates at: " + startTime.getTime().toString());
GetUpdatedResult ur = binding.getUpdated("Account", startTime, endTime);
// Check the length of the returned array of IDs // to detect if you got any hits
if (ur.getIds() != null && ur.getIds().length > 0) { for (int i=0;i<ur.getIds().length;i++) {
System.out.println(ur.getIds(i) + " was updated between "
+ startTime.getTime().toString() + " and "
+ endTime.getTime().toString());
} } else {
System.out.println("No updates to accounts in the last 5 minutes.");
}
} catch (Exception ex) {
System.out.println("\nException caught, error message was: \n" + ex.getMessage());
} }
getUpdated
Sample Code—C#
private void getUpdatedSample() {
DateTime endTime = binding.getServerTimestamp().timestamp;
DateTime startTime = endTime.Subtract(new System.TimeSpan(0, 0, 5, 0, 0));
sforce.GetUpdatedResult gur = binding.getUpdated("Account", startTime, endTime);
if (gur.ids.Length> 0) {
for (int i=0;i<gur.ids.Length;i++) {
Console.WriteLine(gur.ids[i] + " was updated between " + startTime.ToString() + " and " + endTime.ToString());
} }
else {
Console.WriteLine("No updates to accounts between " + startTime.ToString() + " and " + endTime.ToString() );
} }
Arguments
Description Type
Name
Object type. The specified value must be a valid object for your organization.
For a list of standard objects, see Standard Object Reference.
string sObjectTypeEntityType
Starting date/time (Greenwich Mean Time (GMT) or Coordinated Universal Time (UTC) time zone—not local— timezone) of the timespan for which to dateTime
startDate
retrieve the data. The Apex Web service ignores the seconds portion of the specified dateTime value (for example, 12:30:15 is interpreted as 12:30:00 GMT).
Ending date/time (Greenwich Mean Time (GMT) or Coordinated Universal Time (UTC) time zone—not local— timezone) of the timespan for which to dateTime
endDate
retrieve the data. The Apex Web service ignores the seconds portion of the specified dateTime value (for example, 12:35:15 is interpreted as 12:35:00 GMT).
Important: There is a 200 KB limit on the result GetUpdatedResult[]. If your getUpdated call returns more than 200 KB, an exception EXCEEDED_ID_LIMIT is returned. You can correct the error by choosing start and end dates that are closer together.
Response
GetUpdatedResult[]
Faults
InvalidSObjectFault
getUpdated
UnexpectedErrorFault
See Also:
Data Replication Understanding API Calls
http://www.sforce.com/us/resources/soap/sforce60/sforce_API_messages_getUpdated.html
GetUpdatedResult
The getUpdated call returns an array of GetUpdatedResult objects. Each element in the GetUpdatedResult array corresponds to an object that was inserted or updated within the given timespan. A GetUpdatedResult object has the following properties:
Description Type
Name
ID of an sObject that has been updated.
ID id
The timestamp (Greenwich Mean Time (GMT) or Coordinated Universal Time (UTC) time zone—not local— timezone) of the earliest process within the range dateTime
latestDateCovered
of startDate and endDate that did not complete. A value here indicates that for safety, you should use this value for your next startDate in order to capture the changes that started after startDate but did not complete before endDate and were therefore not returned in this call.
login
Logs in to the login server and starts a client session.
Syntax
LoginResult = sfdc.login(string username, string password);
Usage
Use the login call to log in to the login server and start a client session. A client application must log in and obtain a session ID and server URL before making any other API calls.
When a client application invokes the login call, it passes in a username and password as user credentials. Upon invocation, the Apex Web service authenticates the crendentials and returns the session ID for the session, the user ID associated with the logged-in username, and an URL that points to the Apex Web service to use in all subsequent API calls.
After logging in, a client application needs to perform these tasks:
• Set the session ID in the SOAP header so that the Apex Web service can validate subsequent requests for this session.
• Specify the server URL as the target for subsequent service requests. You must change to the server URL, the login server only supports login calls.
Development tools differ in the way you specify session headers and server URLs. For more information, see the documentation for your particular development tool.
Client applications do not need to explicitly log out to end the session. Sessions expire automatically after a predetermined length of time, which can be configured at Setup ➤ Security Controls. The default is 120 minutes (two hours).
login
If you will be repeatedly logging in and your organization’s password policy forces users to change their passwords every certain number of days, you should enable the “Password Never Expires” option on your profile.
To authenticate active Self-Service users, use the LoginScopeHeader to specify the Organization ID against which Self-Service users are authenticated. A Self-Service user must exist and be active before being authenticated (see SelfServiceUser).
Sample Code—Java
private boolean login() {
LoginResult loginResult = null;
SoapBindingStub sfdc = null;
try {
// Create binding object
sfdc = (SoapBindingStub) new SforceServiceLocator().getSoap();
// login
loginResult = sfdc.login("username", "password");
} catch (Exception ex) {
System.out.println("An unexpected error has occurred." + ex.getMessage());
return false;
}
System.out.println("Login was successful.");
// Reset the SOAP endpoint to the returned server URL
sfdc._setProperty(SoapBindingStub.ENDPOINT_ADDRESS_PROPERTY, loginResult.getServerUrl());
// Create a new session header object
// add the session ID returned from the login SessionHeader sh = new SessionHeader();
sh.setSessionId(loginResult.getSessionId());
// Set the session header for subsequent call authentication
sfdc.setHeader(new SforceServiceLocator().getServiceName().getNamespaceURI(), "SessionHeader", sh);
// get user info try {
GetUserInfoResult userInfo = sfdc.getUserInfo();
} catch (Exception ex) {
System.out.println("An unexpected error has occurred." + ex.getMessage());
return false;
}
return true;
}
Sample Code—C#
private void login() {
// Create service object
SforceService sfdc = new SforceService();
// Invoke the login call and save results in LoginResult LoginResult lr = sfdc.login("username","password");
// Reset the SOAP endpoint to the returned server URL sfdc.Url = lr.serverUrl;
// Create a new session header object
// Add the session ID returned from the login sfdc.SessionHeaderValue = new SessionHeader();
sfdc.SessionHeaderValue.sessionId = lr.sessionId;
GetUserInfoResult userInfo = lr.userInfo;
}
login
Arguments
Description Type
Name
Login username. string
username
Login password associated with the specified username. string
password
Response LoginResult
Faults LoginFault
UnexpectedErrorFault
See Also:
Understanding API Calls
http://www.sforce.com/us/resources/soap/sforce60/sforce_API_messages_login.html
LoginResult
The login call returns a LoginResult object, which has the following properties:
Description Type
Name
Indicates whether the password used during the login attempt is expired (true) or not (false). If the password has expired, then the Web boolean
passwordExpired
service returns a valid sessionId, but the only allowable operation is the setPassword call.
URL of the Web service that will process subsequent API calls. Your client application needs to set the end point.
string serverUrl
Unique ID associated with this session. Your client application needs to set this value in the session header.
string sessionID
ID of the user associated with the specified username and password.
ID userID
User information fields. For a list of these fields, see GetUserInfoResult.
GetUserInfoResult userInfo
merge
Merge up to three records into one.
Syntax
mergeResult on page 144[]= sfdc.merge(mergeRequest[] mergeRequests);
merge
Usage
Use this call to merge records of the same object type into one of the records, deleting the others, and re-parenting any related records. Each merge operation is within one transaction. A batch merge has multiple transactions, one for each element in the batch.
The only supported object types are Lead,Contact and Account.
The masterRecord field indicates which of the records is the master record that the others are merged into. You can use queryAll to view records that have been deleted during a merge.
This call requires that you decide prior to the merge call if there are any field values from the non-master record(s) that should supersede the values in the master record. If so, the field names and their new values should be provided in the masterRecord of the MergeRequest, similar to a call to update.
The following limits apply to any merge request:
• Up to 200 merge requests can be made in a single SOAP call.
• Up to three records can be merged in a single request, including the master record. This is the same limit as the Salesforce user interface. If you have more than three records to merge, use the same master record in each request to avoid errors.
To find all records that have been merged since a given point in time, you can use queryAll with a SELECT statement similar to the following:
SELECT Id, FROM Contact WHERE isDeleted=true and masterRecordId != null AND SystemModstamp > 2006-01-01T23:01:01+01:00
It is a recommended best practice to narrow your result set to the most relevant records by filtering on SystemModstamp. Sample Code—Java
Account masterAccount = new Account();
masterAccount.setName("MasterAccount");
SaveResult masterAccountSaveResult = binding.create(new SObject[] {masterAccount})[0];
masterAccount.setId(masterAccountSaveResult.getId());
masterAccount.setDescription("Old description");
Account accountToMerge = new Account();
accountToMerge.setName("AccountToMerge");
accountToMerge.setDescription("Duplicate account");
SaveResult accountToMergeSaveResult = binding.create(new SObject[] {accountToMerge})[0];
// Attach a note, which will get re-parented Note note = new Note();
note.setParentId(accountToMergeSaveResult.getId());
note.setBody("This note will be moved to the MasterAccount during merge");
binding.create(new SObject[] {note});
MergeRequest mr = new MergeRequest();
// Perform an update on the master record as part of the merge:
masterAccount.setDescription("Was merged");
mr.setMasterRecord(masterAccount);
mr.setRecordToMergeIds(new ID[] {accountToMergeSaveResult.getId()});
MergeResult result = binding.merge(new MergeRequest[] {mr})[0];
System.out.println("Merged " + result.isSuccess() + " got " + result.getUpdatedRelatedIds().length + " updated child records");
merge
Sample Code—C#
private void mergeSample() {
try {
Account masterAccount = new Account();
masterAccount.Name = "MasterAccount";
SaveResult sr = binding.create(new sObject[] { masterAccount })[0];
masterAccount.Id = sr.id;
masterAccount.Description = "Old description";
Account accountToMerge = new Account();
accountToMerge.Name = "AccountToMerge";
accountToMerge.Description = "Duplicte account";
SaveResult accountToMergeSaveResult = binding.create(new sObject[]
{ accountToMerge })[0];
// Attach a note, which will get re-parented Note note = new Note();
note.ParentId = accountToMergeSaveResult.id;
note.Body = "This note will be moved ot the MasterAccount during merge";
binding.create(new sObject[] { note });
MergeRequest mr = new MergeRequest();
// Perform an update on the master record as part of the merge:
masterAccount.Description = "Was merged";
mr.masterRecord = masterAccount;
mr.recordToMergeIds = new String[] { accountToMergeSaveResult.id };
MergeResult result = binding.merge(new MergeRequest[] { mr })[0];
Console.WriteLine("Merged " + result.success + " got " + result.ToString() + " updated child records");
}
catch (Exception ex) {
Console.WriteLine(ex.ToString());
} } Arguments
Description Type
Name
Required. Must provide the ID of the object that other records will be merged into. Optionally, provide the fields to be updated and their values.
sObject masterRecord
Required. Minimum of one, maximum of two. The other record or records to be merged into the master record.
ID[]
recordToMergeIds
Response mergeResult[]
Faults
InvalidSObjectFault UnexpectedErrorFault InvalidIdFault
merge
mergeResult
The merge call returns a mergeResult object, which has the following properties:
Description Type
Name
ID of the master record, the record into which the other records were merged.
ID Id
ID of the records that were merged into the master record. If successful, the values will match mergeRequest.recordToMergeIds.
ID[]
mergedRecordIds
Indicates whether the merge was successful (true) or not (false).
boolean success
ID of all related records that were moved (re-parented) as a result of the merge, and that are viewable by the user sending the merge call.
ID[]
updatedRelatedIds
If an error occurred during the merge call, an array of one or more Error objects providing the error code and description.
Error[]
errors
process
Submits an array of approval process instances for approval, or processes an array of approval process instances to be approved, rejected, or removed. For more information, see "Getting Started with Approval Processes" in the Salesforce online help.
Syntax
ProcessResult = sfdc.process( processType processRequest[])
processType can be either ProcessSubmitRequest or ProcessWorkitemRequest Usage
Use the process call to perform either of the following two tasks:
• Submit an array of objects to the approval process. Objects cannot already be in an approval process when submitted. Use the ProcessSubmitRequest signature.
• Process an object that has been submitted to the approval process by performing an approval action (Approve or Reject).
Use the ProcessWorkitemRequest signature.
Requests are processed and a ProcessResult is returned with the same process instances as sent in the request.
The failure of a particular record will not cause failure of the entire request.
Sample Code—Java
public ProcessResult[] doProcessSample(String comments, String id, String[] approverIds) throws ApiFault {
ProcessResult[] processResults;
ProcessSubmitRequest request = new ProcessSubmitRequest();
request.setComments(comments);
request.setNextApproverIds(approverIds);
request.setObjectId(id);
try {
PartnerConnection connection = Connector.newConnection(xconfig);
//calling process on the approval submission
processResults = connection.process(new ProcessSubmitRequest[]{request});
for (ProcessResult processResult : processResults) {
process
if(processResult.getSuccess()){
private void doProcessSample(String id, String[] approverIds) {
ProcessResult[] processResults;
ProcessSubmitRequest request = new ProcessSubmitRequest();
request.objectId = id;
try {
processResults = binding.process(new ProcessSubmitRequest[] { request });
for (int i = 0; i < processResults.Length; i++)
The object to submit for approval, for example, an Account,Contact, or custom object.
ID objectId
If the process requires specification of the next approval, the ID of the user to be assigned the next request.
ID[]
nextOwnerId
The comment to add to the history step associated with this request.
string comment
process
ProcessWorkitemRequest Arguments
Description Type
Name
For processing an item after being submitted for approval, a string representing the kind of action to take: Approve, Reject, or Remove. Only system
administrators can specify Remove.
string action
If the process requires specification of the next approval, the ID of the user to be assigned the next request.
ID[]
nextOwnerId
The comment to add to the history step associated with this request.
string comment
The ID of the ProcessInstanceWorkitem that is being approved, rejected, or removed.
ID workitemId
Response ProcessResult[]
Faults
ALREADY_IN_PROCESS NO_APPLICABLE_PROCESS
See Also:
Understanding API Calls
ProcessResult
The process call returns a ProcessResult object, which has the following properties, depending on the type of call (submit for approval or process object already submitted to for approval):
Description Type
Name
The object being processed.
ID entityId
The set of errors returned if the request failed.
Error[]
errors
The ID of the ProcessInstance associated with the object submitted for processing.
ID instanceId
The status of the current process instance (not an individual object but the entire process instance: “Approved,” “Rejected,” “Removed,” or “Pending.”
string instanceStatus
Case-insensitive Ids that point to ProcessInstanceWorkitem objects (the set of new workflow items created). There can be 0 or 1 items.
ID[]
newWorkItemIds
true if processing or approval completed successfully.
boolean success
query
Executes a query against the specified object and returns data that matches the specified criteria.
query
Syntax
QueryResult = sfdc.query(string queryString);
Usage
Use the query call to retrieve data from an object. When a client application invokes the query call, it passes in a query expression that specifies the object to query, the fields to retrieve, and any conditions that determine whether a given object qualifies. For an extensive discussion about the syntax and rules used for queries, see Sforce Object Query Language (SOQL).
Upon invocation, the Web service executes the query against the specified object, caches the results of the query on the Web service, and returns a query response object to the client application. The client application can then use methods on the query response object to iterate through rows in the query response and retrieve information.
Your client application must be logged in with sufficient access rights to query individual objects within the specified object and to query the fields in the specified field list. For more information, see Factors that Affect Data Access.
Certain objects cannot be queried via the API. To query an object via the query call, its object must be configured as queryable.
To determine whether an object can be queried, your client application can invoke the describeSObjects call on the object and inspect its queryable property.
Tip: If you use the Enterprise WSDL, you should not use describe to populate a select list. For example, if a system administrator adds a field to the SObject after you consume it, the describe call will pull down the field but your toolkit won’t know how to serialize it, and your integration may fail.
You can use queryAll to query on all Task and Event records, archived or not. You can also filter on the isArchived field to find only the archived objects. You cannot use query, it automatically filters out all records where isArchived is set to true. You can insert, update, or delete archived records.
The query response object contains up to 500 rows of data by default. If the query results exceed 500 rows, then the client application uses the queryMore call and a server-side cursor to retrieve additional rows in 500-row chunks. You can increase the default size up to 2,000 in the QueryOptions header, as described in Changing the Batch Size in Queries.
Queries that take longer than two minutes to process will be timed out. For timed out queries, the Apex Web service returns an ExceptionCode of QUERY_TIMEOUT. If a timeout occurs, refactor your query to return or scan a smaller amount of data.
When querying for fields of type Base64 (see base64Binary), the query response object returns only one record at a time. You cannot alter this by changing the batch size of the query call.
Note: For multi-currency organizations, special handling is required when querying currency fields containing values in different currencies. For example, if a client application is querying PricebookEntry objects based on values in the UnitPrice field, and if the UnitPrice amounts are expressed in different currencies, then the query logic must handle this case correctly. For example, if the query is trying to retrieve the product codes of all products with a unit price greater than or equal to $10 USD, the query expression might look something like this:
SELECT Product2Id,ProductCode,UnitPrice FROM PricebookEntry WHERE (UnitPrice >= 10 and CurrencyIsoCode="USD")
OR (UnitPrice >= 5.47 and CurrencyIsoCode="GBP") OR (UnitPrice >= 8.19 and CurrencyIsoCode="EUR")
Sample Code—Java
private void querySample() { QueryResult qr = null;
QueryOptions qo = new QueryOptions();
qo.setBatchSize(new Integer(250));
binding.setHeader(new SforceServiceLocator().getServiceName().getNamespaceURI(),
query
try {
qr = binding.query("select FirstName, LastName from Contact");
boolean done = false;
if (qr.getSize() > 0){
System.out.println("Logged-in user can see " + qr.getRecords().length + " contact records.");
System.out.println("No records found.");
}
System.out.println("\nQuery succesfully executed.");
}
catch (RemoteException ex) {
System.out.println("\nFailed to execute query succesfully, error message was: \n" + ex.getMessage());
//Set the query options (Optional; default batch size is 2000) binding.QueryOptionsValue = new QueryOptions();
binding.QueryOptionsValue.batchSize = 500;
binding.QueryOptionsValue.batchSizeSpecified = true;
// Invoke the query call and save the result in a QueryResult
QueryResult qr = binding.query("select FirstName, LastName from contact where MailingPostalCode = '94062'");
// Get the returned records sObject[] records = qr.records;
// Determine whether some records where returned if (records.Length > 0)
System.Diagnostics.Trace.WriteLine(contact.FirstName + " " + contact.LastName);
}
qr = binding.queryMore(qr.queryLocator);
records = qr.records;
} else {
done = qr.done;
} else {
System.Diagnostics.Trace.WriteLine("no records matched criteria");
} }
Arguments
Description Type
Name
Query string that specifies the object to query, the fields to return, and any conditions for including a specific object in the query. For more information, see Sforce Object Query Language (SOQL).
string queryString
Response QueryResult
Faults
MalformedQueryFault InvalidSObjectFault InvalidFieldFault UnexpectedErrorFault
See Also:
queryAll queryMore
Sforce Object Query Language (SOQL) Understanding API Calls
Changing the Batch Size in Queries
http://www.sforce.com/us/resources/soap/sforce60/sforce_API_messages_query.html
QueryResult
The query call returns a QueryResult object, which has the following properties:
Description Type
Name
String. Used in queryMore for retrieving subsequent sets of objects from the query results, if applicable.Represents a server-side cursor. Note that a Salesforce account can have up to five (5) query cursors open at a time, per user.
QueryLocator queryLocator
Indicates whether additional rows need to be retrieved from the query results (false) using queryMore, or not (true). Your client application can use this value as a loop boolean
done
query
Description Type
Name
Array of sObjects representing individual objects of the specified object and containing data defined in the field list specified in the queryString.
sObject[]
records
Your client application can use this value to determine whether the query retrieved any rows (size > 0) or not (size = 0). Total number of rows retrieved in the query.
Your client application can use this value to determine whether the query retrieved any rows (size > 0) or not (size = 0). Total number of rows retrieved in the query.