python post request
art1313 opened this issue · comments
I am trying to place an order on testnet, but get this error{"error":{"message":"Unexpected token s in JSON at position 0","name":"SyntaxError"}}
Does anyone know what is the issue here? My code is below:
import json
import requests
import aiohttp
import asyncio
import urllib
import time
import hashlib, hmac
import urllib.parse
import json
from future.builtins import bytes
from future.standard_library import hooks
with hooks(): # Python 2/3 compat
from urllib.parse import urlparse
api_key = "api_key"
api_secret = "api_secret"
base_url = 'https://testnet.bitmex.com' ###
method = 'POST'
data = json.loads('{"symbol":"XBTUSD","orderQty":1,"price":9395.5}')
path = '/api/v1/order'
url = base_url + path
print(url)
nonce = int(time.time() * 1000) + 5
print(nonce)
message = bytes(method + path + str(nonce) + str(data), 'utf-8')
print(message)
def generate_signature(secret, verb, url, nonce, data):
"""Generate a request signature compatible with BitMEX."""
# Parse the url so we can remove the base and extract just the path.
parseURL = urlparse(url)
path = parseURL.path
if parseURL.query:
path = path + '?' + parseURL.query
if isinstance(data, (bytes, bytearray)):
data = data.decode('utf8')
message = verb + path + str(nonce) + str(data)
signature = hmac.new(bytes(secret, 'utf8'), bytes(message, 'utf8'), digestmod=hashlib.sha256).hexdigest()
return signature
signature = generate_signature(api_secret, method, path, nonce, data)
print(signature)
headers = {'api-expires':str(nonce),'api-key':api_key,'api-signature':signature, 'Content-Type':'application/json', 'Accept':'application/json'}
print(headers)
r = requests.post(url, data=data, headers=headers)
print('error: ',r.status_code)
print(r.text)
https://testnet.bitmex.com/api/v1/order
1590914238614
b"POST/api/v1/order1590914238614{'symbol': 'XBTUSD', 'orderQty': 1, 'price': 9395.01}"
7632d3f663d638c8a48ba4035d0f19b9fc2d984e651f507bcd9724323faa0aab
{'api-expires': '1590914238614', 'api-key': 'api_key', 'api-signature': '7632d3f663d638c8a48ba4035d0f19b9fc2d984e651f507bcd9724323faa0aab', 'Content-Type': 'application/json', 'Accept': 'application/json'}
error: 400
{"error":{"message":"Unexpected token s in JSON at position 0","name":"SyntaxError"}}
By default, requests
is going to post form-encoded data. https://requests.readthedocs.io/en/master/user/quickstart/#more-complicated-post-requests
Try using json.dumps(data)
in your request:
r = requests.post(url, data=json.dumps(data), headers=headers)
Thanks for a quick response Samuel. The code below works fine:
import json
import requests
import aiohttp
import asyncio
import urllib
import time
import hashlib, hmac
import urllib.parse
import json
from future.builtins import bytes
from future.standard_library import hooks
with hooks(): # Python 2/3 compat
from urllib.parse import urlparse
api_key = "api_key"
api_secret = "api_secret"
base_url = 'https://testnet.bitmex.com' ###
method = 'POST'
data = '{"symbol":"XBTUSD","orderQty":1,"price":9395.5}'
path = '/api/v1/order'
url = base_url + path
print(url)
nonce = int(time.time() * 1000) + 5
print(nonce)
message = bytes(method + path + str(nonce) + data, 'utf-8')
print(message)
def generate_signature(secret, verb, url, nonce, data):
"""Generate a request signature compatible with BitMEX."""
# Parse the url so we can remove the base and extract just the path.
parseURL = urlparse(url)
path = parseURL.path
if parseURL.query:
path = path + '?' + parseURL.query
if isinstance(data, (bytes, bytearray)):
data = data.decode('utf8')
message = verb + path + str(nonce) + data
signature = hmac.new(bytes(secret, 'utf8'), bytes(message, 'utf8'), digestmod=hashlib.sha256).hexdigest()
return signature
signature = generate_signature(api_secret, method, path, nonce, data)
print(signature)
headers = {'api-expires':str(nonce),'api-key':api_key,'api-signature':signature, 'Content-Type':'application/json', 'Accept':'application/json'}
print(headers)
r = requests.post(url, data=data, headers=headers)
print('error: ',r.status_code)
print(r.text)
This seems to be the same code as the original?
Sam in the original:
data = json.loads('{"symbol":"XBTUSD","orderQty":1,"price":9395.5}')
vs in the new one
data = '{"symbol":"XBTUSD","orderQty":1,"price":9395.5}'
Ah yes. Either way will work, it's just important that the data
passed to requests.post()
is a string.