0

I am trying to get Autherization Token for TD Ameritrade API using C# .NET. First I get a "CODE" following some steps. Then I use that code in Postman, send the request I get Authorization Code back.

Postman Body key-value pair Postman console output

Here is my C# .NET Code to do the same :- (the "CODE" is one time value, can't be re-use. I get a NEW CODE and use that in C# app)

public async Task SignIn(string consumerKey, string code, string redirectUrl = "https://127.0.0.1:4000/TDCallBack/SetCode?code")
    {
        var path = "https://api.tdameritrade.com/v1/oauth2/token";

        using (var client = new HttpClient())
        {
            var dict = new Dictionary<string, string>
            {
                { "grant_type", "authorization_code" },
                { "access_type", "offline" },
                { "client_id", $"{consumerKey}" },
                { "redirect_uri", redirectUrl },
                { "code", code }
            };

            var req = new HttpRequestMessage(HttpMethod.Post, path) { Content = new FormUrlEncodedContent(dict) };
            var res = await client.SendAsync(req);
        }
    }

But I get "Invalid_Grant" as return, which means API call went to TD Ameritrate server but it did not return the Authorization Token. It could be header/data issue, but no explanation why it did not return an Authorization token.

I think it is a C# programming issue, because TD Ameritrade has a WEB Page (like swagger) to submit API Calls. Exact same API call work with same parameters/values (of course NEW CODE every time). Postman works, TD Ameritrade Website Works BUT my C# Code doesn't work. I will appreciate if I can get some light on this problem. Thanks.

VLAZ
  • 26,331
  • 9
  • 49
  • 67
Mehdi Anis
  • 358
  • 1
  • 9
  • 17

1 Answers1

0

Have you tried using a proxy (like Fiddler) to see what the differences are between the Postman request and request from your code?

That should go a long way towards finding obvious differences. It also looks like you’re not setting the content type to be x-www-form-urlencoded which may be necessary for the endpoint to properly handle the request.

See also: How to POST using HTTPclient content type = application/x-www-form-urlencoded

Peter Csala
  • 17,736
  • 16
  • 35
  • 75
theficus
  • 53
  • 5
  • I have checked that page and tried all suggestions - none worked. Also, the last answr with most vote (265), I am using same code and that code doesn't have the "content type = x-www-form-urlencoded" piece either. – Mehdi Anis Feb 17 '22 at 15:32
  • In this case I'd strongly recommend setting up a Fiddler proxy to inspect the HTTP message you're sending from your program to the endpoint (read up in the Fiddler docs on how to decrypt HTTPS traffic, too -- it's not hard but it's necessary when using HTTPS). Using this you can directly compare the data Postman is sending (which works) versus your application (which doesn't work) to see what the differences are. – theficus Feb 17 '22 at 18:28
  • You are right, fiddler would give the differences. However, I took a different approach. Since "curl" command also work I am running a command line curl through Process and capturing the output. It is far easy to get what I need for my current purpose. Not sure I should post detail about it and mark this item as "Answered". Because it is a sideway solution but not an actual answer to the C# .NET Post question. I will leave it OPEN. – Mehdi Anis Feb 17 '22 at 20:52
  • Let me know if you find out what the differences are between Postman message and HttpClient. That will go a long way toward being able to give a solution. :) – theficus Feb 18 '22 at 03:28