Create a prepared request ; you can add headers to them after creating the body:
import requests import hmac import hashlib request = requests.Request( 'POST', 'https://poloniex.com/tradingApi', data=payload, headers=headers) prepped = request.prepare() signature = hmac.new(secret, prepped.body, digestmod=hashlib.sha512) prepped.headers['Sign'] = signature.hexdigest() with requests.Session() as session: response = session.send(prepped)
I changed your params argument to data ; for a POST request, it is customary to send parameters in the body, not in the URL.
For nonce, I would use the itertools.count() object sown from the current time, so restarting does not affect it. According to the Poloniex API documentation (which you quoted in your question), nonce is part of the POST body, not the headers, so it is in the payload dictionary:
from itertools import count import time
Using int(time.time()) will reuse the same number if you created more than one request per second. In the example presented by Poloniex , int(time.time()*1000) is used to create a request for every microsecond instead, but using its monotonically increasing counter (seeded from time.time() ) is much more reliable.
You can also encapsulate the digest signing process in a user authentication object ; such an object is transmitted in the prepared request as the last step in the preparation process:
import hmac import hashlib class BodyDigestSignature(object): def __init__(self, secret, header='Sign', algorithm=hashlib.sha512): self.secret = secret self.header = header self.algorithm = algorithm def __call__(self, request): body = request.body if not isinstance(body, bytes):
Use this for requests calls:
response = requests.post( 'https://poloniex.com/tradingApi', data=payload, headers=headers, auth=BodyDigestSignature(secret))
The argument passed is the secret used in the HMAC digest; You can also pass a different header name.