# system.net.httpClient().post throwing 'unsupported\_grant\_type' error

**URL:** <https://forum.inductiveautomation.com/t/system-net-httpclient-post-throwing-unsupported-grant-type-error/58122>\
**Category:** Ignition\
**Tags:** ignition81, scripting, vision\
**Created:** [April 6, 2022, 4:11pm UTC](https://forum.inductiveautomation.com/t/system-net-httpclient-post-throwing-unsupported-grant-type-error/58122 "2022-04-06T16:11:19Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![mdia](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/mdia/32/87599_2.png) [@mdia](https://forum.inductiveautomation.com/u/mdia)\
**Post date:** [April 6, 2022, 4:11pm UTC](https://forum.inductiveautomation.com/t/system-net-httpclient-post-throwing-unsupported-grant-type-error/58122/1 "2022-04-06T16:11:19Z")

</div>

I am using system.net.httpClient().post to issue a refresh token but for some reason I am getting an ‘unsupported\_grant\_type’ error. Here’s my code:

```auto
from base64 import b64encode
logger = system.util.getLogger("myLogger")

client_id = system.tag.read("[WFM_API]client_id").value
client_secret = system.tag.read("[WFM_API]client_secret").value
AccessToken = system.tag.read("[WFM_API]Tokens/AccessToken").value
scope = system.tag.read("[WFM_API]scopes").value
redirect_url = 'https://xero.com/'
RefreshToken = system.tag.read("[WFM_API]Tokens/RefreshToken").value

b64_id_secret = b64encode(client_id + ':' + client_secret)

def XeroRefreshToken(refresh_token):
   token_refresh_url = 'https://identity.xero.com/connect/token'
   client = system.net.httpClient()
   response = client.post(token_refresh_url,
                           headers = {
                               'Authorization' : 'Basic ' + b64_id_secret,
                               'Content-Type': 'application/x-www-form-urlencoded'
                           },
                           data = {
                               'grant_type' : 'refresh_token',
                               'refresh_token' : refresh_token
                           })
   json_response = response.json
   print json_response
   logger.info(str(json_response))
   
XeroRefreshToken(RefreshToken)

```

I’ve also tried using the **system.net.httpPost** function and that returned the same error too.  
I used the urlencode function on the “body” parameter by referring to this post [here](https://forum.inductiveautomation.com/t/system-net-httppost-throwing-error-while-postman-is-not/44815), but that also threw the same error. Any help is much appreciated.

Ignition Version 8.1.16

---

<div class="post-metadata">

**Author:** ![Kevin.Herron](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kevin.herron/32/7259_2.png) [@Kevin.Herron](https://forum.inductiveautomation.com/u/Kevin.Herron)\
**Post date:** [April 6, 2022, 4:15pm UTC](https://forum.inductiveautomation.com/t/system-net-httpclient-post-throwing-unsupported-grant-type-error/58122/2 "2022-04-06T16:15:34Z")

</div>

Do you have any documentation on what this API actually expects?

---

<div class="post-metadata">

**Author:** ![mdia](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/mdia/32/87599_2.png) [@mdia](https://forum.inductiveautomation.com/u/mdia)\
**Post date:** [April 6, 2022, 4:23pm UTC](https://forum.inductiveautomation.com/t/system-net-httpclient-post-throwing-unsupported-grant-type-error/58122/3 "2022-04-06T16:23:41Z")

</div>

Yes, and I think I am doing it right. This is what they’re expecting [Refreshing access & refresh tokens](https://developer.xero.com/documentation/guides/oauth2/auth-flow#refreshing-access-and-refresh-tokens). I also forgot to mention that I am having no issues refreshing the token using postman.  
Here are the headers:

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/e/c/ececc01d76e8a7138b0e5341748f794b3c73c563.png)

Body:

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/1/e/1eec2db409c400f5d52e64199e8b7cda3a235e8f.png)

Settings:

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/5/8/58dc925ec4a2c6ebfbedbc0e7613e0597e2f868c.png)

---

<div class="post-metadata">

**Author:** ![Kevin.Herron](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kevin.herron/32/7259_2.png) [@Kevin.Herron](https://forum.inductiveautomation.com/u/Kevin.Herron)\
**Post date:** [April 6, 2022, 4:30pm UTC](https://forum.inductiveautomation.com/t/system-net-httpclient-post-throwing-unsupported-grant-type-error/58122/4 "2022-04-06T16:30:45Z")

</div>

I don’t think either of the [system.net](http://system.net) methods can automatically encode your payload as “form-data” or “application/x-www-form-urlencoded” data.

You’re passing in a dictionary and it’s almost certainly just being encoded as a JSON object and sent off as the body.

You may need to manually concatenate the payload into a String with the correct format instead.

---

<div class="post-metadata">

**Author:** ![mdia](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/mdia/32/87599_2.png) [@mdia](https://forum.inductiveautomation.com/u/mdia)\
**Post date:** [April 6, 2022, 4:52pm UTC](https://forum.inductiveautomation.com/t/system-net-httpclient-post-throwing-unsupported-grant-type-error/58122/5 "2022-04-06T16:52:01Z")

</div>

I tried urlencoding my ‘data’ argument and also tried using it as a string and both times I got a  
{‘error’: u’invalid\_grant’}

**URL Encoding:**

```auto
def XeroRefreshToken(refresh_token):
from urllib import urlencode
token_refresh_url = 'https://identity.xero.com/connect/token'
	client = system.net.httpClient()
	response = client.post(token_refresh_url,
                            headers = {
                                'Authorization' : 'Basic ' + b64_id_secret,
                                'Content-Type': 'application/x-www-form-urlencoded'
                            },
                            data = urlencode({
                                'grant_type' : 'refresh_token',
                                'refresh_token' : refresh_token
                            }))
	json_response = response.json
	print json_response

```

**Concatenating in a string:**

````auto
def XeroRefreshToken(refresh_token):
	token_refresh_url = 'https://identity.xero.com/connect/token'
	client = system.net.httpClient()
	response = client.post(token_refresh_url,
                            headers = {
                                'Authorization' : 'Basic ' + b64_id_secret,
                                'Content-Type': 'application/x-www-form-urlencoded'
                            },
                            data = 'grant_type=refresh_token&refresh_token=%s'%refresh_token
                            )
	json_response = response.json
	print json_response
	
XeroRefreshToken(RefreshToken)```
````

---

<div class="post-metadata">

**Author:** ![Kevin.Herron](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kevin.herron/32/7259_2.png) [@Kevin.Herron](https://forum.inductiveautomation.com/u/Kevin.Herron)\
**Post date:** [April 6, 2022, 4:53pm UTC](https://forum.inductiveautomation.com/t/system-net-httpclient-post-throwing-unsupported-grant-type-error/58122/6 "2022-04-06T16:53:40Z")

</div>

Try URL-encoding this String you build:

```auto
'grant_type=refresh_token&refresh_token=%s'%refresh_token

```

Your two examples are either URL-encoding the string representation of a dictionary or not URL encoding the data at all.

---

<div class="post-metadata">

**Author:** ![mdia](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/mdia/32/87599_2.png) [@mdia](https://forum.inductiveautomation.com/u/mdia)\
**Post date:** [April 6, 2022, 5:05pm UTC](https://forum.inductiveautomation.com/t/system-net-httpclient-post-throwing-unsupported-grant-type-error/58122/7 "2022-04-06T17:05:27Z")

</div>

My bad, thought I only had to encode the dictionary. Looks like **urlencode** only works with dictionaries because it was returning `TypeError: not a valid non-string sequence or mapping object` when I was using it with a string. Did some research and it looks like I have to use **urllib.quote** or **urllib.quote\_plus** with a string and non of them worked. Both returned `{'error': u'unsupported_grant_type'} `

---

<div class="post-metadata">

**Author:** ![Kevin.Herron](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kevin.herron/32/7259_2.png) [@Kevin.Herron](https://forum.inductiveautomation.com/u/Kevin.Herron)\
**Post date:** [April 6, 2022, 5:10pm UTC](https://forum.inductiveautomation.com/t/system-net-httpclient-post-throwing-unsupported-grant-type-error/58122/8 "2022-04-06T17:10:20Z")

</div>

Hmm, well I just looked at the docs for `urlencode`, and you _can_ pass it a dictionary, which I didn’t know.

I’m assuming you can’t access the URL via plain HTTP, so you might need to get some kind of local HTTP mitm/dev proxy set up that will let you see what the difference between what you’re sending via Postman and Ignition is.

---

<div class="post-metadata">

**Author:** ![mdia](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/mdia/32/87599_2.png) [@mdia](https://forum.inductiveautomation.com/u/mdia)\
**Post date:** [April 6, 2022, 5:21pm UTC](https://forum.inductiveautomation.com/t/system-net-httpclient-post-throwing-unsupported-grant-type-error/58122/9 "2022-04-06T17:21:53Z")

</div>

Just figured it out! I clicked on the code snippet icon **\</\>** in PostMan and selected the ‘Python - http.client’ option from the dropdown. I saw that the code was importing the **encode** module from a library called **codecs**. So I tried it out and system.net.httpClient().post is returning the expected response now. My script became like this:

```auto

client_id = system.tag.read("[WFM_API]client_id").value
client_secret = system.tag.read("[WFM_API]client_secret").value
AccessToken = system.tag.read("[WFM_API]Tokens/AccessToken").value
scope = system.tag.read("[WFM_API]scopes").value
redirect_url = 'https://xero.com/'
RefreshToken = system.tag.read("[WFM_API]Tokens/RefreshToken").value

b64_id_secret = b64encode(client_id + ':' + client_secret)

def XeroRefreshToken(refresh_token):
	from codecs import encode
	token_refresh_url = 'https://identity.xero.com/connect/token '
	client = system.net.httpClient()
	response = client.post(token_refresh_url,
                            headers = {
                                'Authorization' : 'Basic ' + b64_id_secret,
                                'Content-Type': 'application/x-www-form-urlencoded'
                            },
                            data = encode('grant_type=refresh_token&refresh_token=%s'%refresh_token)
                            )
	json_response = response.json
	print json_response	

XeroRefreshToken(RefreshToken)

```

Thanks Kevin for your help.
