2

Using Bit.ly V4 API via this code:

HttpRequest req2 = new HttpRequest();           
req2.setEndpoint('https://api-ssl.bitly.com/v4/shorten');           
req2.setMethod('POST');
req2.setHeader('Authorization', 'Bearer ...');
String jsonBody = '{"long_url":"https://test.com"}';
req2.setBody(jsonBody);
req2.setHeader('Content-Type', 'application/json');

Http http2 = new Http();
HttpResponse res2 = http2.send(req2);           
system.debug(res2);

yields the following response:

CALLOUT_RESPONSE [24] | System.HttpResponse [Status = Not Acceptable, StatusCode = 406]

The same request works in Postman. Why doesn't it work in Apex?

10
  • Instead of setting the auth header in the code, have you tried using named credentials?
    – arut
    Commented Sep 8, 2020 at 12:24
  • can you try with application as a small in your content type. Not sure, but if they're handling case-sensitive it could be an issue.
    – Ysr Shk
    Commented Sep 8, 2020 at 13:37
  • @YsrShk yes, tried change. not case-sensitive
    – Yevhen B
    Commented Sep 8, 2020 at 14:07
  • @arut it's just a little piece of code to test. We have class with named credentials and 2 methods
    – Yevhen B
    Commented Sep 8, 2020 at 14:10
  • 1
    @YevhenB It's kind of difficult to track down this issue (since the final headers sent by HttpRequest & Http classes are not known exactly) and also, no clue of how Bitly is processing the request sent. From a quick test that I did, I got the same response even after commenting out the line of code for authorization header. This basically tells me that Bitly might not have even tried to authorize the request due to some missing header information. So, it would be easier to let named credential handle the auth even for testing (unless you are really want to troubleshoot this).
    – arut
    Commented Sep 8, 2020 at 14:17

1 Answer 1

5

Your code snippet

Http http2 = new Http();
HttpResponse res2 = http2.send(req2);           
system.debug(res2);

sends the reference (res2) to debug log. When this happens, SF calls toString() method on the reference and you see System.HttpResponse [Status = Not Acceptable, StatusCode = 406] as the result. toString gives you the class name and status string + associated code. That is not enough information to see what's going on.

If you send the body of the response to debug log in addition to status like so

system.debug(res2.getStatusCode() + ': ' + res2.getBody());

you'd see

<timestamp> USER_DEBUG [12]|DEBUG|406: {"message":"INVALID_ACCEPT_HEADER"}

This pretty much tells you what's wrong - you need to include the Accept header to indicate that your client can accept JSON as the response. This works:

...
req2.setHeader('Accept', 'application/json');

Http http2 = new Http();
HttpResponse res2 = http2.send(req2);           
system.debug(res2.getStatusCode() + ': ' + res2.getBody());

Depending on configuration, Postman may automatically add headers to the request. While it seemed like your request in Postman was the same as it was in Apex, it really wasn't. When testing REST APIs, it's better to use a command-line client such as curl.

1
  • Thank you! You are the best! :)
    – Yevhen B
    Commented Sep 8, 2020 at 17:54

You must log in to answer this question.

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