APIs, Bots & Automation

How to Sign a Quote.Trade Order Request with HMAC SHA256

Build the exact minified JSON body, sign those bytes with HMAC SHA256, and send the digest in the signature header. Print and compare the request first; do not turn a signing example into a live order by default.

30 minutesAdvancedBackend developers and bot engineers

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
USD price, collateral currency, and network

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.

SignatureHMAC SHA256
HMAC valueExact minified JSON request body
TimestampCurrent epoch milliseconds
Default exampleDry construction only; no POST
Step-by-step

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.

python
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.

Troubleshooting

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.

Primary sources

Ready for the next step?

Open the authenticated trading reference

Open the authenticated trading reference