Logon (A)

Sent by the client to initiate a FIX session. Must be the first message sent after a connection is established. Only one session can be established per connection; additional Logon messages will be rejected. You can have multiple connections per subaccount.

TagNameExampleDescription
35MsgTypeAMessage type
98EncryptMethod0Must be set to "0" (None)
108HeartBInt30Heartbeat inteval; Must be set to 30
96RawData8f7e...4783Signature (see below for generation details)
8013CancelOrdersOnDisconnectY"Y": all account orders will be cancelled at the end of the session. "S": all orders placed during the session will be cancelled at the end of the session. Default: no orders will be cancelled.
1Account"my_subaccount"(Optional) Subaccount name; should be omitted if authenticating for main account. If you specify a subaccount that the API key being used doesn't have access to, you will get an error.

Signature

For security, the Logon message must be signed by the client. This signature should be passed in with tag 96 (RawData). To compute the signature, concatenate the following fields, joined by the FIX field separator (byte 0x01), and compute the SHA256 HMAC using the API secret:

  • SendingTime (52)
  • MsgType (35)
  • MsgSeqNum (34)
  • SenderCompID (49)
  • TargetCompID (56)

The resulting hash should be hex-encoded.

️ SendingTime (52) Format

Please note that the SendingTime (52) must be in the same format for generating the signature and tag 52. Thus, if the SendingTime in the signature uses this format: 20220525-07:51:52, tag 52 should use the same. If you choose to use subseconds, then both the SendingTime used to generate the signature and the SendingTime sent in tag 52 should use this format: 20220525-07:51:52.123

Here's an example of generating the signature in Python:

from datetime import datetime
import hmac

api_key = 'YOUR_API_KEY'
api_secret = 'YOUR_API_SECRET'

sending_time = datetime.utcnow().strftime('%Y%m%d-%H:%M:%S')

sign_target = '\x01'.join([
    sending_time,  # SendingTime
    'A',  # MsgType
    '1',  # MsgSeqNum
    api_key,  # SenderCompID
    'FTX',  # TargetCompID
])

signature = hmac.new(api_secret.encode(), sign_target.encode(), 'sha256').hexdigest()

Example Logon (A) message:

Sent by client:
8=FIX.4.2|9=162|35=A|49=****|56=FTX|34=1|52=20221017-20:29:39|98=0|108=30|96=0d24aba380a87c5f2c94b1d4f42c3cf8bfb29b45d373e32421ebb02412139177|10=197

Received from server:
8=FIX.4.2|9=98|35=A|49=FTX|56=****|34=1|52=20221017-20:29:41.188|98=0|108=30|10=129

Invalid Signature

When getting the error invalid signature it doesn't necessarily mean the the signature itself is invalid, just means the authentication failed. Except the signature is indeed invalid, other possible reasons to get this error:

  1. Timestamps mismatch. Please note that the SendingTime (52) must be in the same format for generating the signature and tag 52.
  2. Time zone isn't UTC
  3. Access issues.
    1. FIX doesn't support read-only. Using a read-only API key will result in the error.
    2. The API key has IP restriction but the request is actually from an unwhitelisted IP.