Requirement
Need to perform a Salesforce upsert via SOAP API using External IDs on standard objects.e.g. you want to specify the record Owner or RecordType without using Salesforce IDs.
Getting set up
Don't bother trying to prototype using Data Loader. All the standard object external IDs are unavailable. AFAICT Workbench doesn't support them either.
- Generate the WSDL and strip out any comments and script
- Install SoapUI if you haven't already
- Create a new SOAP project using your WSDL
- Find the login method and set it up as below. Get rid of any question marks
- Press play. The response appears on the right hand side.
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:enterprise.soap.sforce.com">
<soapenv:Header>
<urn:LoginScopeHeader>
<urn:organizationId></urn:organizationId>
<!--Optional:-->
<urn:portalId></urn:portalId>
</urn:LoginScopeHeader>
</soapenv:Header>
<soapenv:Body>
<urn:login>
<urn:username>me@myorg.org.sandbox</urn:username>
<urn:password>reallybadpassword</urn:password>
</urn:login>
</soapenv:Body>
</soapenv:Envelope>
Upsert time
Find the Upsert method, set it up as below and press play. Copy the session ID from the login response to it.- The server URL returned in the login response is the target for this request. Put it up in the url box at the top of the request window
- Account doesn't have any standard external ID fields so a field called ExternalID__c has been created. You could use the ID field instead, but yeuch
- The Account has a record type with Name "Record Type 1"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:urn="urn:enterprise.soap.sforce.com"
xmlns:urn1="urn:sobject.enterprise.soap.sforce.com"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Header>
<urn:SessionHeader>
<sessionId>00Dm00000001xVa!ARQAQCyXrqpRsPctsGUj4AAHIKJJlBeOjxM9M.GOGMCjsYrNNAHJ6OTRIYxZLwbjXb.5bEZh66q09rhYecRDl4YNUc0_7ruO</sessionId>
</urn:SessionHeader>
</soapenv:Header>
<soapenv:Body>
<urn:upsert>
<urn:externalIDFieldName>ExternalId__c</urn:externalIDFieldName>
<urn:sObjects xsi:type="urn1:Account">
<urn1:ExternalId__c>abcd1234</urn1:ExternalId__c>
<urn1:Owner xsi:type="urn1:User">
<urn1:Email>me@myorg.org</urn1:Email>
</urn1:Owner>
<urn1:RecordType xsi:type="urn1:RecordType">
<urn1:Email>Record Type 1</urn1:Email>
</urn1:RecordType>
</urn:sObjects>
</urn:upsert>
</soapenv:Body>
</soapenv:Envelope>
Other things to note
To find out which standard object fields are available as external IDs, use the Workbench and look for idlookup:true" on a field.If you're a freetard using the dead-ended version of SoapUI (5.2.1) then you'll need to enable TLS 1.2 as per instructions at the following link...(or so I've heard)
https://community.smartbear.com/t5/SoapUI-Open-Source/How-to-enable-TLS-1-2-in-SoapUI/td-p/96239/page/2
The correct instruction in this topic for Windows:
Place this in your SoapUI-X.Y.Z.vmoptionsf file (where X.Y.Z is the version number of SOAPUI you have)
-Dsoapui.https.protocols=TLSv1.2,SSLv3
The User object doesn't have any fields where both idlookup and unique are true. As a result, to do an upsert involving Users, the session user requires the incredibly broad View All Data rights, otherwise they will get this error: "INSUFFICIENT_ACCESS: Upsert requires view all data on a non-unique custom index". This despite UserNames being unique across the entire platform!
The RecordType Name field can be used as an external ID, but the DeveloperName field can't, which is odd given that the DeveloperName is recommended as the invariant reference for apex code.