Bug? - Inconsistencies between HMAC signature requirements for different endpoints (eg Wallet vs Order)

Hi, I’m maintaining GitHub - dvcrn/binance.ex: Autogenerated Elixir wrapper for the Binance public API, an Elixir SDK for the Binance spot API

Following:

According to https://github.com/binance/binance-spot-api-docs/blob/master/rest-api.md#signed-trade-and-user_data-endpoint-security, we can specify hmac signature either in the query parameters or body, it supposedly doesn’t matter and can even be mixed.

In reality this is not the case. For example, Wallet and Order APIs function different:

  • Endpoint: “/sapi/v1/asset/dust-btc”
created signature for args: timestamp=1698553833998 -- signaturexxxxx
POSTING to "/sapi/v1/asset/dust-btc", body = "timestamp=1698553833998&signature=signaturexxxxx

Response: code: -1002, msg: "You are not authorized to execute this request."

Doing the same request with query paramters:

created signature for args: timestamp=1698553833998 -- signaturexxxxx
POSTING to "/sapi/v1/asset/dust-btc?timestamp=1698553833998&signature=signaturexxxxx

Response: OK works

Specifying in both query and body params works as well. Mentioning this because the behavior is different in other endpoints.

  • Endpoint “/api/v3/order”
created signature for args: timestamp=1698553943808&type=LIMIT&symbol=DOGEBTC&price=0.00000100&quantity=100&side=BUY&timeInForce=GTC -- signaturexxx
POSTING to "/api/v3/order", body = "timestamp=1698553943808&type=LIMIT&symbol=DOGEBTC&price=0.00000100&quantity=100&side=BUY&timeInForce=GTC&signature=signaturexxx"

Response: 
{:ok,
 %Binance.Structs.OrderResponse{
   client_order_id: "xxx",
   executed_qty: "0.00000000",
   order_id: 484992911,
   orig_qty: "100.00000000",
   price: "0.00000100",
   side: "BUY",
   status: "NEW",
   symbol: "DOGEBTC",
   time_in_force: "GTC",
   transact_time: 1698553943809,
   type: "LIMIT"
 }}
  • Doing the same with only query paramters works too
  • Doing the same with BOTH query AND body paramters (same as with the example above) results in code: -1101, msg: "Duplicate values for parameter 'timestamp'."

The only way to reliably get this working is to always send as query params and never within the request body.

Am I reading something wrong or why does the behavior vary so much between different spot endpoints? Why is body only sometimes working, and sometimes not? Why Can I sometimes have both params in query and body, sometimes not?

Or are the order endpoints special?

It’s recommended to send requests by appending all parameters in URL.

Yeah I get that this is working, but it’s against the spec written in the official API docs. The API supposedly doesn’t discriminate between query and body params, when in reality it does.

If everything ‘is recommended’ to get send as query parameters, the docs should reflect that