When is Thread_Id value generated?

I tried accessing it through SOQL and Apex and SFDC complains and throws error.

How do I access Thread_Id in apex?

  • I don't see such field on case. Where did you see this field? – Kiran Machhewar Dec 22 '15 at 18:09
  • Hi Kiren, when you go to Email Templates for the Merge Field it allows to access {!Case.Thread_Id} but when tried to access it through SOQL and Apex it does not. – Nilam Patel Dec 22 '15 at 18:28

There have been several iterations of the thread ID, see this idea, but you shouldn't be using a regular regex, because that may be bad. Here's my suggestion:

public static String shortenID(String idValue) {
    String[] keys = idValue.left(15).split('');
    while(keys.size() > 5 && keys[5] == '0') {
    return String.join(keys,'');

public String getThreadId(Id caseId) {
        'ref:_' + shortenId(UserInfo.getOrganizationId()) +
        ':_'    + shortenId(caseId) +  ':ref';

Anything less complex than this will work for the near future, but, as people have found out, the format does periodically change (the '_' characters are a "new" addition). What you should do, for now, is try send this ID simply by using actual standard templates instead of trying to build it yourself, because it will break one day.

Also... vote on the idea.


Only reliable way to get the Thread Id at this time is when getting the result from Salesforce itself. You can do this by getting the result that Salesforce would generate when sending an Email:

// To be replaced with a real case Id.
Id caseId = '500c0000008kJL5'; 

List<Messaging.RenderEmailTemplateBodyResult> renderResults = Messaging.renderEmailTemplate(null, caseId, new List<String>{'{!Case.Thread_Id}'});

System.debug('this is the Case Thread Id: ' + renderResults[0].getMergedBody());
  • brilliant! i'll be adding this to my Util lib – cropredy Apr 11 '18 at 18:12
  • N.B. the renderEmailTemplate method burns a SOQL so you can't use it in a loop within a trigger – cropredy Oct 24 '18 at 20:31

Case Thread ID is the combination of Organization Id and Case ID so You can create a formula field on Case object with following value as per the Salesforce document


in apex you can use following code

public static String CASE_REF_FORMAT = 'ref:{0}.{1}:ref';

private static String shortenOrgId(String id) {
     String part = id.substring(0,15);
     Pattern p = Pattern.compile('^([A-Za-z0-9]{5})([A-Za-z0-9]*)$');
     Matcher m = p.matcher(part);

     if (m.matches()) {
          return '_' + m.group(1) + m.group(2).replace('0', '');

     return '';

private static String shortenCaseId(String id) {
     String part = id.substring(0,15);
     Pattern p = Pattern.compile('^([A-Za-z0-9]{5})([A-Za-z0-9]*)([A-Za-z0-9]{5})$');
     Matcher m = p.matcher(part);

     if (m.matches()) {
          return '_' + m.group(1) + m.group(2).replace('0', '') + m.group(3);

     return '';

public static String caseRefId(String orgId, String caseId) {
     if (orgId == null || caseId == null) {
          return '';

     String shortenedOrgId = shortenOrgId(orgId);
     String shortenedCaseId = shortenCaseId(caseId);

     return String.format(
          new List<String>{

example :

  • Both the formula and Apex Code are technically incorrect. You're close on both counts, though. For example, the hypothetical case ID 5003500307ARiL1 would be rendered as _50035:_37ARiL1 instead of _50035:_307ARiL1. – sfdcfox Dec 22 '15 at 18:22
  • Interesting, I used "ref:_"&LEFT( $Organization.Id , 4)&"0"&RIGHT( $Organization.Id , 4)&"._"&LEFT(Id , 4)&"0"&RIGHT(Id , 5)&":ref" that I sourced from success.salesforce.com/ideaView?id=087300000006trk – cropredy Dec 22 '15 at 18:30
  • yah i got that from that idea only – Himanshu Dec 22 '15 at 18:31
  • Thank you! So basically Thread_Id could be a hidden field on the case correct? – Nilam Patel Dec 22 '15 at 18:33
  • @crop1645 That version is technically incorrect, as I recently found out that the 4-5 positions on the ID are pod identifiers, but has historically been a 0 (because they hadn't counted that high yet). So, LEFT(Id, 5) is the minimum safe value, then you need to simply delete zeroes until you come to the first non-zero value. While today, we know there are five significant characters in most IDs, that won't be always be true in the future. – sfdcfox Dec 22 '15 at 18:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.