Salesforce Gotchas and Undocumented ‘Features’
Today we’re going to go through some things that I hope you find interesting and informative, things that hopefully will make your development process a lot easier. With many of the following issues, I’ve found the documentation either sparse, obscured, or non-existent.
- 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. The 18-character version has some extra non-essential metadata about the object that’s not present in the earlier 15-character version. 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 ‘https://cs1.salesforce.com/00Q/o’, 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).

Good post, but I should clear up some things:
The 15-character ID is case-SENSITIVE, and the 18-char is case-INSENSITIVE. There is no additional information in the ID other than to make it case-insensitive.
Excel Connector will return the 18-char ID when querying data, and so will every other API-using tool such as Apex Data Loader. There is no “metadata” in the ID, and neither is newer or previous – they are interchangable. In fact, there is a FIXID() formula installed by the Office Toolkit into Excel that will let you switch between the two.
The reason there’s nothing returned for “salesforce id prefix” is that the three characters are not an ID prefix! They are called “object codes” and there are great posts about them at http://salesforce.phollaio.com/2007/01/11/salesforces_url_structure/, among other places.
Security tokens change automatically, but once you set a security token, Salesforce will email you a replacement token every time you change your password.
Welcome to the Salesforce world. Though Sites will render PHP-integration obsolete, eventually, customers with existing PHP implementations that they do not wish to migrate completely to Sites/Visualforce will still need to know this. Thanks for writing.
First, thank you. The 15-character vs. 18-character issue is now corrected above.
The gotcha I was referring to in the Excel Connector is when using the case-insensitive format, I was only talking about being able to use the two formats interchangeably. The issue, as illustrated here, is that VLOOKUP is case-insensitive. Excel issues are generally out-of-scope for this blog, I happened to be aware of this particular issue and mentioned it. There certainly are work-arounds.
According to David Claiborne, you can indeed refer to it as a prefix. See this post. I think we all understand what I’m talking about here.
As discussed before, Sites is geared toward form management, it is never going to replace web applications.
-p
I can’t resist responding to this:
1. Just because someone calls it a prefix on a discussion board does not mean that it is a prefix. It really is an object identifier.
2. I’m sorry to see you say that Sites is geared towards form management and will never replace web applications. That is just false. To see the amazing things that have been done with Sites, visit the Sites Gallery at http://developer.force.com/sitesgallery. You’ll see that entire web applications are created on Sites. There is even an AppExchange CMS package that was just released. Sites CAN replace entire websites, so let’s watch the word “never.”
Remember: It was once said that humans would never fly, that Einstein would never amount to anything, and that the American people would never be interested in movies with sound.
1. This is ’someone on a discussion board’: http://www.salesforce.com/platform/innovators/claiborne.jsp. You get the point already.
2. I went to the URL, and saw several examples of forms implemented using Sites. I guess I’m just refuting your comment ‘Though Sites will render PHP-integration obsolete…’. Honestly, I really only care about a specific layer on the server side. I hereby suggest that anyone who wants to know anything about Apex, VisualForce, or Sites check out http://www.x2od.com/.
Until Salesforce improves their uptime, it’s a moot point. It’s not even worth discussing, IMHO. I get exception messages from Salesforce in my mailbox every single day, sometimes many per day. That doesn’t even include scheduled maintenance. If I want to retrieve my license keys from Salesforce during an outage, how do I do that with Sites? Perhaps there’s an answer to that question, but if there’s not, maybe you should try to develop a CRM framework that builds in redundancy and handles keeping your second datastore (memcached/bdb/SQL/flat files) in sync while users are making changes in the UI. I’ll be discussing ways to do this soon.
Thanks for the tip on the administrator profile!!
I can’t resist responding to *this*:
Just because something *can* be done in one framework doesn’t mean it should *always* be done in that framework. Sites is cool but doesn’t fit every purpose. Some of us are working with more than just Salesforce integration in our applications, and I highly doubt that PHP integration with Salesforce will become obsolete just because Sites exists (although it’s also nice to have Sites as an option).
And I’ve also heard of the 3-character “prefix” but no one I’ve ever discussed it with has ever called it an “object code”… if we’re going to be purist about nomenclature let’s see it referenced in the docs and not just some other guy’s blog.
Actually, it is both a prefix and an object code. It is a prefix in the context of the whole ID and an object code when considered independently.