1

Here is the error I'm getting when I try to call a Tooling API Rest Api:

00:53:19.0 (7411847)|CALLOUT_REQUEST|[28]|System.HttpRequest[Endpoint=https://vcorg-dev-ed.my.salesforce.com/services/data/v36.0/tooling/executeAnonymous/?anonymousBody=util.sendEmail%28%27%7B+recordId%3A+%221234TEST1234%22%2C+success%3A+%22TRUE%22%2C+result%3A+%22Executed+callback%22+%7D%27%29%3B, Method=GET]
00:53:19.0 (139800574)|CALLOUT_RESPONSE|[28]|System.HttpResponse[Status=Unauthorized, StatusCode=401]

I'm trying to call Tooling API to executeanonymous from within APEX. I've already added the Endpoint and even added other combination of endpoints such as without My Domain and Visualforce version of URL but the Error do not go away:

My End Points setup in Remote Setup are:

https://ap1.salesforce.com
https://vcorg-dev-ed.my.salesforce.com
https://vcorg-dev-ed--pknmsp.ap1.visual.force.com

My Rest API code is being called in Queueable interface and my code is:

public with sharing class ApexServiceAsync implements Queueable, Database.AllowsCallouts {

    public void execute(QueueableContext context) {
    string functionCall    = 'util.sendEmail(\'test subject\');';

        HttpRequest req        = new HttpRequest();
        req.setHeader('Authorization', 'Bearer ' + UserInfo.getSessionID());
        req.setHeader('Content-Type', 'application/json');
        //string instance        = [select instanceName from Organization limit 1].instanceName.toLowerCase();
        //String baseUrl         = 'https://'+instance+'.salesforce.com/services/data/v36.0/tooling';
        String baseUrl         = URL.getSalesforceBaseUrl().toExternalForm() + '/services/data/v36.0/tooling';
        String toolingendpoint = baseUrl + '/executeAnonymous/?anonymousBody='+encodingUtil.urlEncode(functionCall,'utf-8');
        req.setEndpoint(toolingendpoint);
        req.setMethod('GET');

        system.debug('@@ callbackFn [req]: '+req);

        Http h                 = new Http();
        h.send(req);
   }

}

and VF page button executes this function like this:

public void executeCB() {
        try {
         system.enqueueJob(new ApexServiceAsync());
        }
        catch (Exception ex) {
            util.LogError(ex, true, true);
        }
    }

This is really frustrating, as I can execute the full HTTP Request code in Execute Anonymous window of Developer Console just fine and it works there, though it does not work when I call it from the page. What Unauthorized endpoint could there be in my case here?

5
  • Try to run the code with upgrading/downgrading version of your class.
    – Raul
    Sep 27 '16 at 8:59
  • I tried, that. I tried running it down from 30.0 to 37.0 and same error coming up.
    – VarunC
    Sep 27 '16 at 9:26
  • i think when you run in class it takes some different URL. Check in debug
    – Raul
    Sep 27 '16 at 9:34
  • 1
    Your error message is not 'Unauthorized endpoint' but 'Unauthorized'. So the endpoint is probably fine, but the authentication is not. Sep 27 '16 at 9:48
  • That was it guys .. Thanks a bunch. Silliest mistake on my part, I mis-understood the Unauthorized error to be related to endpoint only. It was the session not getting passed.
    – VarunC
    Sep 27 '16 at 10:20
0

The unauthorized endpoint is returned from the API callout you are doing and not because of Remote site settings.

For Apex code that is executed asynchronously, such as @future methods, Batch Apex jobs, or scheduled Apex jobs, getSessionId returns null.

Since you are calling using batch the session Id is null and hence its failing.

2
  • That is it. My mistake I wasn't looking into Session as my mind was fully into Endpoint security and just assumed it is coming from there. Thanks a lot for pointing that out.
    – VarunC
    Sep 27 '16 at 10:22
  • note that as of winter 19, getSessionId() returns non-null in async contexts
    – cropredy
    May 20 '19 at 22:19

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.