What you will accomplish
- Create the exact JSON body that will be signed
- Generate HMAC SHA256 in Python and JavaScript
- Send matching body and headers
- Test signing without exposing a real secret
Before you begin
- A Quote.Trade API key and secret stored server-side
- Current order schema from the trading reference
- A test account and strict order limits
Prices and order values are shown in USD. The collateral currency, such as USDC or USDT, and its blockchain network are separate settings. Check the live account and market settings for allowed currencies, minimum size, and leverage.
Create the exact request body
Use the current trading reference fields. Keep leverage disabled unless explicitly approved. Use strings for decimal values and a paymentCurrency that is actually enabled for the account.
Generate timestamp at runtime
Do not copy a fixed timestamp from documentation. Use current epoch milliseconds immediately before signing.
Serialize the exact JSON and compute the HMAC
Create the final minified JSON body once, sign those exact bytes with HMAC SHA256, and send that same body without reformatting it. The example below prints the request but does not submit an order.
import hashlib, hmac, json, os, time
secret = os.environ['QUOTE_TRADE_API_SECRET'].encode()
body = {
'liquidityOrder': 1,
'account': int(os.environ['QUOTE_TRADE_ACCOUNT_ID']),
'symbol': 'BTC',
'side': 'BUY',
'type': 'LIMIT',
'price': '60000.00',
'quantity': '0.001',
'disableLeverage': 1,
'paymentCurrency': os.environ['QUOTE_TRADE_PAYMENT_CURRENCY'],
'timestamp': int(time.time() * 1000),
}
request_body = json.dumps(body, separators=(',', ':'), ensure_ascii=False)
signature = hmac.new(secret, request_body.encode(), hashlib.sha256).hexdigest()
print(json.dumps({'url':'https://app.quote.trade/api/order','body':body,'signature':signature}, indent=2))Compare exact bytes before any POST
Verify body bytes, field order generated by your code, Content-Type, X-MBX-APIKEY, signature header, timestamp tolerance, account, and current payment currency. Do not log the secret.
Place a live order only through an explicit separate action
Require human approval, minimum practical notional, leverage disabled, and a one-shot POST. Do not auto-retry a timeout or 5xx; check orders and account state first.
Common problems and fixes
The signature is rejected
Log the body hash—not the secret—and compare the exact transmitted bytes with the signed bytes.
The digest includes “(stdin)=”
Extract only the hexadecimal digest when using openssl; do not send command-line labels in the header.
Signing works locally but fails through a framework
Disable body rewriting or sign the final byte sequence produced by the HTTP layer.
A real example secret appears in logs
Revoke and rotate it immediately; examples must use obvious placeholders.