Salesforce Gotchas and Undocumented ‘Features’

Salesforce Gotchas and Undocumented

– Objects (such as individual leads or contacts) have either a 15-character or an 18-character case-sensitive ID (e.g. 00Q6000000OaR87). You should not count on one format or the other being returned. The two formats can normally be used interchangeably (you can pass either version to an API call), but one notable exception to this rule is the Excel Connector, which integrates Salesforce and Excel. CORRECTION: This is wrong. The lesson here is that when your motivation for writing a blog is your horrible experience with your Salesforce integrators, you shouldn’t take what they say as gospel. David Schach pointed out that the 15-character version is simply case-sensitive. There is no metadata whatsoever. I apologize again for failing to fact-check this.

– Object IDs have a three-character prefix, which will be consistent for standard objects and will differ between instances for custom objects. This is not very well documented, and in fact, a Google search for “salesforce id prefix” returns no results (except this entry, after it gets indexed). If you don’t yet have any objects of a particular type, but need the ID, you can get it from the URL after clicking on the tab (or the ‘>’ to the right of the tabs if you don’t see the object you’re looking for). The URL will be something like ‘’, and the prefix is between the slashes (here, ‘00Q,’ for leads). Prefixes for common standard objects include:

  • 00Q (Leads)
  • 003 (Contacts)
  • 001 (Accounts)
  • 006 (Opportunities)
  • 701 (Campaigns)
  • 500 (Cases)

– Salesforce API logins (including logins from other third-party applications, like the Outlook tool) have the concept of a security token, which can be reset by going to Setup > My Personal Information > Reset My Security Token.

– Security tokens are appended to passwords when logging in via the API, so you might login with the username ‘joe’ and the password ‘mypasswordmytoken’.

– Security tokens change automatically when a password changes – watch out for this!

– There are no default administrator profiles whose passwords do not expire. This means that your API user’s password may expire, and your entire API integration will suddenly fail. I highly recommend making a new administrator profile called something like ‘Admins – Passwords Do Not Expire’ and adding your API and other back-end users to it. The original profile will not (currently) let you check the ‘Passwords do not expire’ checkbox.

– Avoid using the logout() call. As discussed before, all logins for a single user share a session id. Calling logout() will log out all concurrent connections for that Salesforce user via the API. Note also that this behavior is undocumented. Not to worry, the PHP Toolkit gracefully cleans up the SOAP connection for you.

– Deleted and merged data (e.g. deleted leads) can wreak havoc if your application relies on valid Salesforce IDs. Just because a lead exists today doesn’t mean Sales isn’t going to mass-delete those 10,000 ‘junk’ leads tomorrow.

– Salesforce objects are always referred to in the API in the singular form, so ‘Lead’ rather than ‘Leads.’

– Custom fields append __c to the field name, e.g. My_Custom_Field__c.

– There are a couple of Salesforce expressions that I’ll use here to be consistent, including ‘picklist’ to mean an HTML select element, ‘dependent picklist’ to mean a picklist whose appearance or values depend on another picklist, ‘auto number’ to mean an auto-increment field, and ‘upsert’ to mean a call that will update if a record with the specified ID exists, or else insert a new record.

Lastly, a quick aside about languages and operating systems. The code examples presented here assume a POSIX-compliant OS, such as Linux, but Windows-specific considerations should pretty much non-existent. PHP is fairly OS-agnostic for what we’re going to be doing, but inevitably there will be an OS-specific issue that will creep in. As far as portable paths go, PHP lets you use ‘/’ as a path separator in scripts on all OSes, but you could certainly instead use the native (and portable) DIRECTORY_SEPARATOR constant or ‘\\’ in the paths if you prefer. Lastly, in this blog, ‘native’ is taken to mean ‘native to PHP, written in C’ – an example of this is the native SOAP client (versus the much slower NuSOAP client written in PHP).