I am learning how to use the Kucoin and am having trouble with the authenticating myself to the API server.
I am trying to load all of the active orders however keep getting a 401 error.
The Kucoin API documentation states that I need to add this:
{
"KC-API-KEY": "59c5ecfe18497f5394ded813",
"KC-API-NONCE" : 1506219855000 //Client timestamp (exact to
milliseconds), before using the calibration time, the server does not
accept calls with a time difference of more than 3 seconds
"KC-API-SIGNATURE" :
"fd83147802c361575bbe72fef32ba90dcb364d388d05cb909c1a6e832f6ca3ac"
//signature after client encryption
}
as a parameter to headers of request. I am unsure what this means. Any help will be appreciated.
Creating the header can be a little tricky.
For the nonce value, or any millisecond timestamp value, I've found the best way to generate this is like this
import time
int(time.time() * 1000)
The signature requires you to order the parameters alphabetically in a query string format, combine that with the path and nonce and then hash the string using sha256 with your secret key.
If you'd like to implement it yourself feel free to copy the code from here, it's split over a few functions and should be quite readable https://github.com/sammchardy/python-kucoin/blob/0ece729c406056a428a57853345c9931d449be02/kucoin/client.py#L117
Or alternatively you may be best off just using that library. (Note: I'm the author and maintainer of python-kucoin)
Here are my working codes in Python 3:
import requests
import json
import hmac
import hashlib
import base64
from urllib.parse import urlencode
import time
api_key = 'xxxxx'
api_secret = 'xx-xxx-xx'
api_passphrase = 'xxx' #note that this is *not* trading password
base_uri = 'https://api.kucoin.com'
def get_headers(method, endpoint):
now = int(time.time() * 1000)
str_to_sign = str(now) + method + endpoint
signature = base64.b64encode(hmac.new(api_secret.encode(), str_to_sign.encode(), hashlib.sha256).digest()).decode()
passphrase = base64.b64encode(hmac.new(api_secret.encode(), api_passphrase.encode(), hashlib.sha256).digest()).decode()
return {'KC-API-KEY': api_key,
'KC-API-KEY-VERSION': '2',
'KC-API-PASSPHRASE': passphrase,
'KC-API-SIGN': signature,
'KC-API-TIMESTAMP': str(now)
}
#List Accounts
method = 'GET'
endpoint = '/api/v1/accounts'
response = requests.request(method, base_uri+endpoint, headers=get_headers(method,endpoint))
print(response.status_code)
print(response.json())
Output
200
{'code': '200000', 'data': [{'available': blah,blah,blah }]}
Related
I have looked through the FTX API documentation found here: https://docs.ftx.us/#overview
And I've looked at the example code found in this repo: https://github.com/ftexchange/ftx/tree/master/rest
I can't get or post anything that requires Authentication. I am using the API key on my account that has 'full trade permissions', and when I look at print(request.headers) the headers look like they are in the right format.
Let me know if you need any more information, my code returns
Error Code: 400 Invalid API Key
import time
import hmac
from requests import Request
ts = int(time.time() * 1000)
request = Request('GET', 'https://ftx/api/wallet/balances')
prepared = request.prepare()
signature_payload = f'{ts}{prepared.method}{prepared.path_url}'.encode()
signature = hmac.new('API SECRET'.encode(), signature_payload, 'sha256').hexdigest()
request.headers[f'FTXUS-KEY'] = API KEY'
request.headers[f'FTXUS-SIGN'] = signature
request.headers[f'FTXUS-TS'] = str(ts)
res = requests.get('https://ftx/api/wallet/balances', headers=prepared.headers)
r = res.json()
I also got this error and It was a silly mistake.
I think you have FTX.US API Key and you are hitting on 'https://ftx/api/wallet/balances'. U should hit on 'https://ftx.us/api/wallet/balances' to get this working
I need to build a code to extract data from Binance using API (not using Python library).
For some requests its not required to apply API key. For instance:
import requests
market = 'ETHUSDT'
tick_interval = '1m'
startTime = 1513375200000
endTime = 1656489800000
limit = 1000
url = "https://api.binance.com/api/v3/klines"
params = {
'symbol': market,
'interval': tick_interval,
"startTime" : startTime,
"endTime" : endTime,
"limit" : limit
}
data = requests.get(url, params = params).json()
But also I want to use another endpoint to get all the trades of the account with symbol provided.
GET /api/v3/myTrades (HMAC SHA256)
https://binance-docs.github.io/apidocs/spot/en/#account-information-user_data
But I dont understand how to pass API key, what would be the url with API/secret in order to get this info?
I would much appreciate any help in that.
But I dont understand how to pass API key
This is documented in the Binance docs you've linked, albeit under the General info§Endpoint security type section.
API-keys are passed into the Rest API via the X-MBX-APIKEY header.
Add headers by passing them into your call to requests.get() with the guidance from the associated documentation and this Stack Overflow thread:
headers = { 'X-MBX-APIKEY': MY_API_KEY }
requests.get(url, headers=headers)
The SIGNED (TRADE, USER_DATA, AND MARGIN) Endpoint security section also contains information pertinent to your specific use case (considering the API method you've indicated you wish to use has the HMAC SHA256 indicator attached to it:
SIGNED endpoints require an additional parameter, signature, to be sent in the query string or request body.
Endpoints use HMAC SHA256 signatures. The HMAC SHA256 signature is a keyed HMAC SHA256 operation. Use your secretKey as the key and totalParams as the value for the HMAC operation.
The signature is not case sensitive.
totalParams is defined as the query string concatenated with the request body.
Timing security
A SIGNED endpoint also requires a parameter, timestamp, to be sent which should be the millisecond timestamp of when the request was created and sent.
An additional parameter, recvWindow, may be sent to specify the number of milliseconds after timestamp the request is valid for. If recvWindow is not sent, it defaults to 5000.
Once you've got your request almost ready to go, you'll need to do as this section in the docs mentions and concatenate the query string and the request body, hash it with your private key, then tack it on to the parameters with the key signature. Doing this in Python is relatively straightforward and detailed in this Stack Overflow thread:
import hmac
import hashlib
import urllib
API_SECRET = 'some_secret_key'
params = {
'symbol': market,
'interval': tick_interval,
"startTime" : startTime,
"endTime" : endTime,
"limit" : limit
}
body = {
'whatever': 'your',
'request': 'has'
}
params['signature'] = hmac.new(bytes(API_SECRET , 'utf-8'), msg = bytes(urllib.parse.encode(params) + urllib.parse.encode(body), 'utf-8'), digestmod = hashlib.sha256).hexdigest().upper()
# make the request using params and body variables as you normally would in your request.get() invocation
Writing a bot for a personal project, and the Bittrex api refuses to validate my content hash. I've tried everything I can think of and all the suggestions from similar questions, but nothing has worked so far. Tried hashing 'None', tried a blank string, tried the currency symbol, tried the whole uri, tried the command & balance, tried a few other things that also didn't work. Reformatted the request a few times (bytes/string/dict), still nothing.
Documentation says to hash the request body (which seems synonymous with payload in similar questions about making transactions through the api), but it's a simple get/chcek balance request with no payload.
Problem is, I get a 'BITTREX ERROR: INVALID CONTENT HASH' response when I run it.
Any help would be greatly appreciated, this feels like a simple problem but it's been frustrating the hell out of me. I am very new to python, but the rest of the bot went very well, which makes it extra frustrating that I can't hook it up to my account :/
import hashlib
import hmac
import json
import os
import time
import requests
import sys
# Base Variables
Base_Url = 'https://api.bittrex.com/v3'
APIkey = os.environ.get('B_Key')
secret = os.environ.get('S_B_Key')
timestamp = str(int(time.time() * 1000))
command = 'balances'
method = 'GET'
currency = 'USD'
uri = Base_Url + '/' + command + '/' + currency
payload = ''
print(payload) # Payload Check
# Hashes Payload
content = json.dumps(payload, separators=(',', ':'))
content_hash = hashlib.sha512(bytes(json.dumps(content), "utf-8")).hexdigest()
print(content_hash)
# Presign
presign = (timestamp + uri + method + str(content_hash) + '')
print(presign)
# Create Signature
message = f'{timestamp}{uri}{method}{content_hash}'
sign = hmac.new(secret.encode('utf-8'), message.encode('utf-8'),
hashlib.sha512).hexdigest()
print(sign)
headers = {
'Api-Key': APIkey,
'Api-Timestamp': timestamp,
'Api-Signature': sign,
'Api-Content-Hash': content_hash
}
print(headers)
req = requests.get(uri, json=payload, headers=headers)
tracker_1 = "Tracker 1: Response =" + str(req)
print(tracker_1)
res = req.json()
if req.ok is False:
print('bullshit error #1')
print("Bittex response: %s" % res['code'], file=sys.stderr)
I can see two main problems:
You are serialising/encoding the payload separately for the hash (with json.dumps and then bytes) and for the request (with the json=payload parameter to request.get). You don't have any way of knowing how the requests library will format your data, and if even one byte is different you will get a different hash. It is better to convert your data to bytes first, and then use the same bytes for the hash and for the request body.
GET requests do not normally have a body (see this answer for more details), so it might be that the API is ignoring the payload you are sending. You should check the API docs to see if you really need to send a request body with GET requests.
I only manage to use the Emotion API subscription key for pictures but never for videos. It makes no difference whether I use the API Testing Console or try to call the Emotion API by Pathon 2.7. In both cases I get a response status 202 Accepted, however when opening the Operation-Location it says
{ "error": { "code": "Unauthorized", "message": "Access denied due to
invalid subscription key. Make sure you are subscribed to an API you are
trying to call and provide the right key." } }
On the Emotion API explanatory page it says that Response 202 means that
The service has accepted the request and will start the process later.
In the response, there is a "Operation-Location" header. Client side should further query the operation status from the URL specified in this header.
Then there is Response 401, which is exactly what my Operation-Location contains. I do not understand why I'm getting a response 202 which looks like response 401.
I have tried to call the API with Python using at least three code versions that I found on the Internet that
all amount to the same, I found the code here :
Microsoft Emotion API for Python - upload video from memory
python-upload-video-from-memory
import httplib
import urllib
import base64
import json
import pandas as pd
import numpy as np
import requests
_url = 'https://api.projectoxford.ai/emotion/v1.0/recognizeInVideo'
_key = '**********************'
_maxNumRetries = 10
paramsPost = urllib.urlencode({'outputStyle' : 'perFrame', \
'file':'C:/path/to/file/file.mp4'})
headersPost = dict()
headersPost['Ocp-Apim-Subscription-Key'] = _key
headersPost['content-type'] = 'application/octet-stream'
jsonGet = {}
headersGet = dict()
headersGet['Ocp-Apim-Subscription-Key'] = _key
paramsGet = urllib.urlencode({})
responsePost = requests.request('post', _url + "?" + paramsPost, \
data=open('C:/path/to/file/file.mp4','rb').read(), \
headers = headersPost)
print responsePost.status_code
videoIDLocation = responsePost.headers['Operation-Location']
print videoIDLocation
Note that changing _url = 'https://api.projectoxford.ai/emotion/v1.0/recognizeInVideo' to _url =
'https://westus.api.cognitive.microsoft.com/emotion/v1.0/recognizeInVideo' doesn't help.
However, afterwards I wait and run every half an hour:
getResponse = requests.request('get', videoIDLocation, json = jsonGet,\
data = None, headers = headersGet, params = paramsGet)
print json.loads(getResponse.text)['status']
The outcome has been 'Running' for hours and my video is only about half an hour long.
Here is what my Testing Console looks like Testing Console for Emotion API, Emotion Recognition in Video
Here I used another video that is about 5 minutes long and available on the internet. I found the video in a different usage example
https://benheubl.github.io/data%20analysis/fr/
that uses a very similar code, which again gets me a response status 202 Accepted and when opening the Operation-Location the subscription key is wrong
Here the code:
import httplib
import urllib
import base64
import json
import pandas as pd
import numpy as np
import requests
# you have to sign up for an API key, which has some allowances. Check the
API documentation for further details:
_url = 'https://api.projectoxford.ai/emotion/v1.0/recognizeinvideo'
_key = '*********************' #Here you have to paste your
primary key
_maxNumRetries = 10
# URL direction: I hosted this on my domain
urlVideo = 'http://datacandy.co.uk/blog2.mp4'
# Computer Vision parameters
paramsPost = { 'outputStyle' : 'perFrame'}
headersPost = dict()
headersPost['Ocp-Apim-Subscription-Key'] = _key
headersPost['Content-Type'] = 'application/json'
jsonPost = { 'url': urlVideo }
responsePost = requests.request( 'post', _url, json = jsonPost, data = None,
headers = headersPost, params = paramsPost )
if responsePost.status_code == 202: # everything went well!
videoIDLocation = responsePost.headers['Operation-Location']
print videoIDLocation
There are further examples on the internet and they all seem to work but replicating any of them never worked for me. Does anyone have any idea what could be wrong?
The Video Feature of Emotion API retires October 30th, so maybe you should change your procedure to screenshots anyways.
But for your question: The API returns you an URL where your results are accessible. You cannot open this URL in your browser, this will give you the notice of "invalid key", instead you need to call over python again this URL including your key.
I will post you my code how to get the score, I am using Python 3, so there might be some adjustments necessary. Only "tricky" point is getting the Operation ID, which is just the ID in the URL ( =location in my case) which leads to your request. Rest of the parameters like subscription key etc. is as before.
#extract operation ID from location-string
OID = location[67:]
bod = ""
try:
conn =
http.client.HTTPSConnection('westus.api.cognitive.microsoft.com')
conn.request("GET", "/emotion/v1.0/operations/"+OID+"?%s" %params, bod, headers)
response = conn.getresponse()
data = response.read()
print(data)
conn.close()
except Exception as e:
print("[Errno {0}] {1}".format(e.errno, e.strerror))
Did you verify your API call is working using curl? Always prototype calls using curl first. If it works in curl but not in Python, use Fiddler to observe the API request and response.
I also found an answer in the following link, all steps are explained:
https://gigaom.com/2017/04/10/discover-your-customers-deepest-feelings-using-microsoft-facial-recognition/
I'm trying to use Python to access the trading API at poloniex.com, a cryptocurrency exchange. To do this I must follow this prescription:
All calls to the trading API are sent via HTTP POST to https://poloniex.com/tradingApi and must contain the following headers:
Key - Your API key.
Sign - The query's POST data signed by your key's "secret" according to the HMAC-SHA512 method.
Additionally, all queries must include a "nonce" POST parameter. The nonce parameter is an integer which must always be greater than the previous nonce used.
Here is what I have so far. My current issue is that I do not know how to compile the POST url so that it can be signed without sending the incomplete request first. This obviously doesn't work.
import requests
import hmac
import hashlib
import time
headers = { 'nonce': '',
'Key' : 'myKey',
'Sign': '',}
payload = { 'command': 'returnCompleteBalances',
'account': 'all'}
secret = 'mySecret'
headers['nonce'] = int(time.time())
response = requests.post( 'https://poloniex.com/tradingApi', params= payload, headers= headers )
headers['Sign'] = hmac.new( secret, response.url, hashlib.sha512)
Create a prepared request; you can add headers to that after the body has been created:
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 the parameters in the body, not the URL.
For the nonce, I'd use a itertools.count() object, seeded from the current time so restarts don't affect it. According to the Poloniex API documentation (which you quoted in your question), the nonce is part of the POST body, not the headers, so put it in the payload dictionary:
from itertools import count
import time
# store as a global variable
NONCE_COUNTER = count(int(time.time() * 1000))
# then every time you create a request
payload['nonce'] = next(NONCE_COUNTER)
Using int(time.time()) would re-use the same number if you created more than one request per second. The example code provided by Poloniex uses int(time.time()*1000) to make it possible to create a request every microsecond instead, but using your own monotonically increasing counter (seeded from time.time()) is far more robust.
You can also encapsulate the digest signing process in a custom authentication object; such an object is passed in the prepared request as the last step in preparation:
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): # Python 3
body = body.encode('latin1') # standard encoding for HTTP
signature = hmac.new(self.secret, body, digestmod=self.algorithm)
request.headers[self.header] = signature.hexdigest()
return request
Use this with your requests calls:
response = requests.post(
'https://poloniex.com/tradingApi',
data=payload, headers=headers, auth=BodyDigestSignature(secret))
The argument passed in is the secret used in the HMAC digest; you can also pass in a different header name.