11

I'd like to get the current API version in Apex. Is this possible without issuing a call to e.g. REST api?

I post messages to a streaming channel via:-

string uri = URL.getSalesforceBaseUrl().toExternalForm()+'/services/data/v35.0/sobjects/StreamingChannel/'+streamingChannelId+'/push';

and so I'd like to not hardcode to v35.0 portion. This is because when my clients subscribe to the channel they are directed to /services/data/<latest api version>/sobjects/... and so as versions change the version number needs to change.

Alternatively, is it possible to ignore the v35.0 portion from the url somehow when posting and get SFDC to presume the latest version?

Thanks.

2
  • Turns out that posting to older versions of the url makes no difference to the streaming channel subscribers. Subscribing to a newer version than that posted to still shows the messages. Still interesting to get a way to get api version though... Commented May 1, 2016 at 11:30
  • A cheap and flexible alternative to retrieving the API version the hard way: I created a custom label with the version in which I want to work. And wherever I need this in my code, I use the label instead of a hardcoded version. Very efficient and easy to understand. Whenever you are ready to use the latest version, just update the label. Commented Nov 10, 2021 at 13:19

6 Answers 6

6

There is a tricky way to get it.

  • You can query attachment by following SOQL, "SELECT Id, Body FROM Attachment limit 1"

  • salesforce return attachment body as an url like below, /services/data/v36.0/sobjects/Attachment/00P28000005pwcVEAQ/Body

  • you can get latest version by splitting this url.

2
  • A cunning way to get the value indeed. I'm going to leave the question open to see if any better solutions come along but this is certainly a way of getting the version. Commented May 1, 2016 at 11:31
  • For my org, at this moment (Winter '22), this does not work. The body that I get with this query is a base64 encoded PDF file. No URL in sight, alas. Commented Nov 10, 2021 at 12:42
5

I think the reason there is no easy way is that an org actually supports many versions. So we really want the newest. I wrote this code:

public class VersionResponse
{
    public String label; 
    public String url; 
    public String version; 
}

public static String getNewestAPIVersion()
{
    String url = 'https://' + ApexPages.currentPage().getHeaders().get('Host') + '/services/data';
    system.debug('Url: ' + url); 

    HttpRequest req = new HttpRequest();
    req.setMethod('GET');
    req.setEndpoint(url);
    req.setHeader('Content-Type', 'application/json');

    Http http = new Http();
    HTTPResponse resp = http.send(req);

    String json = resp.getBody(); 
    system.debug('Body: ' + json); 

    List<VersionResponse> parsedList = (List<VersionResponse>)System.JSON.deserialize(json, List<VersionResponse>.class); 
    system.debug('Parsed Body: ' + parsedList); 

    String latestVersion = '0'; 
    for (VersionResponse item : parsedList)
    {
        if (latestVersion.compareTo(item.version) < 0)
        {
            latestVersion = item.version; 
        }
    }
    system.debug('Latest Version: ' + latestVersion); 

    return latestVersion;
}

If you do this, you must open up the host in each org. Go to Setup > Security Controls > Remote Site Settings, and add an entry for the host.

If you use communities, you will need to add the community prefix to the URl based on the user. Since your community uses a different host name, a Remote Site Setting must be added for it to.

list<Network> Prefix = [SELECT Id, UrlPathPrefix FROM Network WHERE Name = :community Limit 1];

string prefix = Prefix[0].UrlPathPrefix; 

String url = 'https://' + ApexPages.currentPage().getHeaders().get('Host') + '/' + prefix + '/services/data';
3

I don't think there is a way where we can ignore api version and use the latest one. But if you want to use latest api version then you can have a code in order to get latest api version and then use that api version in subsequent api calls.

So you would need to make api call to /services/data in order to get latest api version.

enter image description here

I haven't found any way where I could get latest api version in apex itself.

3

Patrick Denker's answer was awesome! I am just incrementing it a little bit, to avoid using Account ID and to get the exact data needed using deserializeUntyped. Thank you, Patrick!!! Helped me a lot.

JSONGenerator gen = JSON.createGenerator(false);
gen.writeObject(new User(Id = UserInfo.getUserId()));
Map<String, Object> result = (Map<String, Object>) JSON.deserializeUntyped(gen.getAsString());
Map<String, Object> resultAttributes = (Map<String, Object>) result.get('attributes');
String resultAttributesURL = (String) resultAttributes.get('url');
String apiVersion = resultAttributesURL.substringAfter('/services/data/v').substringBefore('/');
system.debug('apiVersion = [' + apiVersion + ']');
2

It is possible to use the Version to get all available versions:

curl https://MyDomainName.my.salesforce.com/services/data/ -H "Authorization: Bearer token"

which returns something similar:

[
{
    "label" : "Spring '11",
    "url" : "/services/data/v21.0",
    "version" : "21.0"
},
{
    "label" : "Summer '11",
    "url" : "/services/data/v22.0",
    "version" : "22.0"
},
{
    "label" : "Winter '12",
    "url" : "/services/data/v23.0",
    "version" : "23.0"
}
]

Here is the reference: https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/dome_versions.htm

0

Here is a solution consuming no limits. Somehow I wasn't able to get any matches with my regex.

public static String getApiVersion() {
    String apiVersion = null;
    JSONGenerator gen = JSON.createGenerator(false);

    gen.writeObject(new Account(Id='0012p00001aA1AaAAA'));

    for (String part : gen.getAsString().split('/')) {
        if (part.startsWith('v') && part.contains('.') && part.length() == 5) {
            apiVersion = part;
            break;
        }
    }

    return apiVersion;
}

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .