89

I'm trying to send an array(list) of requests to the WheniWork API using requests.post, and I keep getting one of two errors. When I send the list as a list, I get an unpacking error, and when I send it as a string, I get an error asking me to submit an array. I think it has something to do with how requests handles lists. Here are the examples:

url='https://api.wheniwork.com/2/batch'
headers={"W-Token": "Ilovemyboss"}
data=[{'url': '/rest/shifts', 'params': {'user_id': 0,'other_stuff':'value'}, 'method':'post',{'url': '/rest/shifts', 'params': {'user_id': 1,'other_stuff':'value'}, 'method':'post'}]
r = requests.post(url, headers=headers,data=data)
print r.text

# ValueError: too many values to unpack

Simply wrapping the value for data in quotes:

url='https://api.wheniwork.com/2/batch'
headers={"W-Token": "Ilovemyboss"}
data="[]" #removed the data here to emphasize that the only change is the quotes
r = requests.post(url, headers=headers,data=data)
print r.text

#{"error":"Please include an array of requests to make.","code":5000}
General Grievance
  • 4,555
  • 31
  • 31
  • 45
Bobby Battista
  • 1,985
  • 2
  • 17
  • 27

4 Answers4

141

You want to pass in JSON encoded data. See the API documentation:

Remember — All post bodies must be JSON encoded data (no form data).

The requests library makes this trivially easy:

headers = {"W-Token": "Ilovemyboss"}
data = [
    {
        'url': '/rest/shifts',
        'params': {'user_id': 0, 'other_stuff': 'value'},
        'method': 'post',
    },
    {
        'url': '/rest/shifts',
        'params': {'user_id': 1,'other_stuff': 'value'},
        'method':'post',
    },
]
requests.post(url, json=data, headers=headers)

By using the json keyword argument the data is encoded to JSON for you, and the Content-Type header is set to application/json.

MaxNoe
  • 14,470
  • 3
  • 41
  • 46
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
39

Well, It turns out that all I needed to do was add these headers:

headers = {'Content-Type': 'application/json', 'Accept':'application/json'}

and then call requests

requests.post(url,data=json.dumps(payload), headers=headers)

and now i'm good!

elad silver
  • 9,222
  • 4
  • 43
  • 67
13

Always remember when sending an array(list) or dictionary in the HTTP POST request, do use json argument in the post function and set its value to your array(list)/dictionary.

In your case it will be like:

r = requests.post(url, headers=headers, json=data)

Note: POST requests implicitly convert parameter's content type for body to application/json.

For a quick intro read API-Integration-In-Python

Stephen Rauch
  • 47,830
  • 31
  • 106
  • 135
MHBN
  • 131
  • 1
  • 7
1

I have a similar case but totally different solution, I've copied a snippet of code which looks like that:

resp_status, resp_data = requests.post(url, headers=headers, json=payload, verify=False) 

and this resulted in error:

ValueError: too many values to unpack (expected 2)

just assigning to one variable resolve the issue:

response = requests.post(url, headers=headers, json=payload, verify=False)
Tomerikoo
  • 18,379
  • 16
  • 47
  • 61
Michal Lis
  • 491
  • 5
  • 4