> For clean Markdown of any page, append .md to the page URL. > For a complete documentation index, see https://docs.paradigm.co/authentication/signing-requests/llms.txt. > For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.paradigm.co/_mcp/server. # Signing Requests **Paradigm requires all RESToverHTTP requests to be signed**. #### GET REST over HTTP example demonstrating signing of requests ```python # A GET RESToverHTTP sample demonstrating the generation of signatures and signing of requests. import base64 import hmac 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 = '' secret_key = '' host = 'https://api.testnet.paradigm.trade' # GET example method = b'GET' path = b'/v2/drfq/instruments/?venue=DBT&asset=BTC' body = b'' timestamp, signature = sign_request(secret_key, method, path, body) headers = { 'Authorization': 'Bearer {}'.format(access_key), 'Paradigm-API-Timestamp': timestamp, 'Paradigm-API-Signature': signature, } url = urljoin(host, path.decode()) response = requests.get(url, headers=headers) print(response.status_code) print(response.text) ``` #### POST REST over HTTP example demonstrating signing of requests ```python # 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 = '' 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) ``` > **Warning** > > Signing is not currently supported for *JSON-RPCoverWebSocket* API endpoints. Request signatures are generated by applying the HMAC-SHA256 function to your Paradigm API `` 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 ``. 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 | > **Warning** > > Signed requests are only valid for 30 seconds from when the timestamp is captured. Requests received after the 30-second window are rejected.