We are trying to interface with our SalesForce instance via HTTP. The idea would be to call some of our custom classes from outside salesforce but without any user interaction. Typical scenario is when our ERP System calls out to SalesForce to inform it about a new customer or order.

The plan is for our ERP to call something like GET https://<our.salesforce.com>/our/res/class?param1=A&param2=B (or POST with DATA).

I am reasonably well versed in making the actual REST classes but stumped when it comes to OAuth authentication. I take it Basic Authentication by encoding the username:password as Authorization: Basic blahblah== is out? So how to authenticate or get a Session ID?

Note, this is machine-to-machine communication with no user interaction. Yet the Remote Application setup in SalesForce requires me to enter a "Callback URL" which is described as "typically the URL that a user’s browser is redirected to after successful authentication". So what is atypical? What must I enter here?


Here the CURL command I am using:

curl --form client_id=*****
     --form client_secret=*****
     --form grant_type=password
     --form username=blah%40blah.com.sandbox
     --form password=passwordTOKEN
     -H "content-type: application/x-www-form-urlencoded"


POST https://test.salesforce.com/services/oauth2/token HTTP/1.1
User-Agent: curl/7.26.0
Host: test.salesforce.com
Accept: */*
Content-Length: 723
Expect: 100-continue
content-type: application/x-www-form-urlencoded; boundary=----------------------------e3e12e44c894

Content-Disposition: form-data; name="client_id"

Content-Disposition: form-data; name="client_secret"

Content-Disposition: form-data; name="grant_type"

Content-Disposition: form-data; name="username"

Content-Disposition: form-data; name="password"



HTTP/1.1 400 Bad Request
Date: Tue, 28 Jan 2014 13:20:53 GMT
Pragma: no-cache
Cache-Control: no-cache, no-store
Content-Type: application/json;charset=UTF-8
Content-Length: 81

{"error_description":"grant type not supported","error":"unsupported_grant_type"}

Tried using test.salesforce.com and instance.salesforce.com (which the docs use). Also tried with and without API token appended to password.

My client_id is 85 characters long.

  • Can your ERP append HTTP headers to the outgoing requests? Jan 28, 2014 at 11:37
  • Sure, of course.
    – Marc
    Jan 28, 2014 at 12:11
  • 1
    Needless to say unsupported_grant_type is not one of the documented error codes! help.salesforce.com/apex/…
    – Marc
    Jan 28, 2014 at 13:42
  • you have to use login.salesforce if are using production or test.salesforce if are using a sandbox. That error is typical when you are missing a header or have a wrong encoded value. stackoverflow.com/questions/10890467/… Jan 28, 2014 at 13:45
  • I'm using test.salesforce.com as I'm in a sandbox. I've also 100% verified my credentials (username, password and token) into the same instance by using the SOAP API (test.salesforce.com/services/Soap/c/24.0)
    – Marc
    Jan 28, 2014 at 13:46

3 Answers 3


You must use OAth login flow first to have REST access. There is a lot of good information out there about Salesforce OAuth login flow.

In order to make it programatically (Server to Server ), I think that the most efficient way is:


  1. Set the current access_token to the request header you need to do.
  2. Make the request trying to catch any exception.
  3. If you have an exception of type 401 Unauthorized you have to launch the login flow and save the access_token for future requests.

Using this you don't have to go through the login flow on each request.


This is a sample of how to get the access_token:


Realize an HTTP POST to https://[login].salesforce.com/services/oauth2/token **you must select between test or login according the environment we want to use (sandbox or production).



** replace default values with values from your org/user

content-tpe: application/x-www-form-urlencoded

Answer = Ok. Ex:


Answer = Error Ex:

"error_description":"authentication failure - Invalid Password"

WS Usage

Once obtained the access_token and instance_url, you can send the requests to the web services

More information

You will found a deeper information here about external applications on REST

  • 2
    I've tried your proposal (see my 'Answer' update) but get only 400 errors. The question remains: in order to setup OAuth I must enter a "Callback URL". What is that?
    – Marc
    Jan 28, 2014 at 12:50
  • You must add the TOKEN and also check the header content-type. Set the callback using localhost, that is used in other flows. Jan 28, 2014 at 12:54
  • 2
    I've tried the password with and without the token. Also with and without the content-type header. Also using a vairety of callback URLs. Always get grant type not supported. btw. Typo: content-tpe
    – Marc
    Jan 28, 2014 at 13:14
  • 1
    Your answer is correct in theory just doesn't work for me in practice. If I do exactly the same HTTP call from APEX code it works perfectly. I've tried whitelisting my IP (CURL client) to no avail.
    – Marc
    Jan 28, 2014 at 14:00
  • Your question has changed. You first ask about what authentication you should implement, now you are asking about an error you are getting. Probably, the better way the community can help you is if you create a new question about the error. Jan 28, 2014 at 14:16

Finally got this working (i.e. solved the enigmatic unsupported_grant_type error) though the reason remains unclear. It seems (my version of) CURL creates a different kind of request to "normal" HTTP clients which the REST endpoint is not understanding.

When I compared the POST with what apex HttpRequest() was doing I noticed CURL adds this header:

content-type: application/x-www-form-urlencoded; boundary=----...etc.

and then have a complex body using that boundary whilst other clients do without it:

content-type: application/x-www-form-urlencoded

and have a simple body:


Thanks a lot CURL, think I'll stick to Fiddler from now on.

So HTTP Request:

POST /services/oauth2/token HTTP/1.1
User-Agent: Fiddler
Host: test.salesforce.com
Accept: */*
Content-Length: 241
content-type: application/x-www-form-urlencoded


Get's you:

HTTP/1.1 200 OK


  • your problem was that you were using --form option to your parameters, they specify ` --form CONTENT Specify HTTP multipart POST data (H), so curl actually created added body parts which probably doesn't make sense, as content type is not multipart, and so it added boundary` to header. In order to make it work in curl, you need to use -d instead of --form
    – dhblah
    Aug 12, 2015 at 15:48

You can use Username-Password OAuth Authentication Flow. The username-password authentication flow can be used to authenticate when the consumer already has the user’s credentials. In this flow, the user’s credentials are used by the application to request an access token as shown in the following steps.

enter image description here

An example request body might look something like the following:

  • So I need to use OAuth? Which means I need to enter a callback URL (or I can't enable OAuth)? See also my update (400 Error).
    – Marc
    Jan 28, 2014 at 12:15
  • You can use any callback url when using this flow with OAuth Jan 28, 2014 at 12:31
  • There's some info on salesforce.stackexchange.com/questions/22704/… answer that might help Jan 28, 2014 at 12:36
  • Phil, that seems to deal with remote sites as in sites that my SF instance wants to call out to.
    – Marc
    Jan 28, 2014 at 13:26

You must log in to answer this question.

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