Comment on page
Signing Requests
Paradigm requires all RESToverHTTP requests to be signed.
1
# A GET RESToverHTTP sample demonstrating the generation of signatures and signing of requests.
2
3
import base64
4
import hmac
5
import time
6
from urllib.parse import urljoin
7
8
import requests
9
10
11
def sign_request(secret_key, method, path, body):
12
signing_key = base64.b64decode(secret_key)
13
14
timestamp = str(int(time.time() * 1000)).encode('utf-8')
15
message = b'\n'.join([timestamp, method.upper(), path, body])
16
digest = hmac.digest(signing_key, message, 'sha256')
17
signature = base64.b64encode(digest)
18
19
return timestamp, signature
20
21
22
access_key = '<access-key>'
23
secret_key = '<secret-key>'
24
host = 'https://api.testnet.paradigm.trade'
25
26
# GET example
27
method = b'GET'
28
path = b'/v1/drfq/instruments/?venue=DBT&asset=BTC'
29
body = b''
30
31
timestamp, signature = sign_request(secret_key, method, path, body)
32
headers = {
33
'Authorization': 'Bearer {}'.format(access_key),
34
'Paradigm-API-Timestamp': timestamp,
35
'Paradigm-API-Signature': signature,
36
}
37
url = urljoin(host, path.decode())
38
response = requests.get(url, headers=headers)
39
print(response.status_code)
40
print(response.text)
# A POST RESToverHTTP sample demonstrating the generation of signatures and signing of requests.
import base64
import hmac
import json
import time
from urllib.parse import urljoin
import requests
def sign_request(secret_key, method, path, body):
signing_key = base64.b64decode(secret_key)
timestamp = str(int(time.time() * 1000)).encode('utf-8')
message = b'\n'.join([timestamp, method.upper(), path, body])
digest = hmac.digest(signing_key, message, 'sha256')
signature = base64.b64encode(digest)
return timestamp, signature
access_key = '<access-key>'
secret_key = '<secret-key>'
host = 'https://api.testnet.paradigm.trade'
# POST example
method = b'POST'
path = b'/v1/echo/'
data = {'message': 'hello'}
body = json.dumps(data).encode('utf-8')
timestamp, signature = sign_request(secret_key, method, path, body)
headers = {
'Authorization': 'Bearer {}'.format(access_key),
'Paradigm-API-Signature': signature,
'Paradigm-API-Timestamp': timestamp,
'Accept': 'application/json',
}
url = urljoin(host, path.decode())
response = requests.post(url, headers=headers, json=data)
print(response.status_code)
print(response.text)
Signing is not currently supported for JSON-RPCoverWebSocket API endpoints.
Request signatures are generated by applying the HMAC-SHA256 function to your Paradigm API
<secret-key>
and a concatenated message consisting of the request timestamp, request method, request path, query parameters, and body. The key provided to the HMAC function must be the base64-decoded version of the <secret-key>
. The signature must then be base64-encoded and passed via a special header value.Some important considerations are:
- The timestamp must be a UNIX timestamp (milliseconds since epoch in UTC).
- The request method must be capitalized (e.g.
GET
). - The request path must include the entire base path of the request (e.g.
/rfq/
). - The request parameters must include
?
(e.g.?cursor=a2Ed&venue=DBT
) unless none are used. - The request body should be substituted with an empty string for
GET
requests.
Once the signature is generated, the timestamp and signature should be provided as HTTP headers:
Header Name | Header Value |
---|---|
Paradigm-API-Signature | The generated signature |
Paradigm-API-Timestamp | The timestamp used when generating the signature |
Signed requests are only valid for 30 seconds from when the timestamp is captured. Requests received after the 30-second window are rejected.
Last modified 4mo ago