Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.kalshi.com/llms.txt

Use this file to discover all available pages before exploring further.

Overview

Margin FIX uses standard FIX error messages with additional detail in the Text field. Errors fall into two categories:
  • Session-level errors: Protocol violations, handled with Reject (35=3)
  • Business-level errors: Application logic issues, handled with BusinessMessageReject (35=j) or order-specific rejection messages

Error Message Types

Reject (35=3)

Used for session-level protocol violations.
TagNameDescriptionRequired
45RefSeqNumSequence number of rejected messageYes
58TextHuman-readable error descriptionNo
371RefTagIDTag that caused the rejectionNo
372RefMsgTypeMessage type being rejectedNo
373SessionRejectReasonRejection reason codeNo

Session Reject Reasons (373)

CodeReasonDescription
0Invalid tag numberUnknown tag in message
1Required tag missingMandatory field not present
2Tag not defined for messageTag not valid for this message type
3Undefined tagTag number not in FIX specification
4Tag without valueEmpty tag value
5Incorrect valueInvalid value for tag
6Incorrect data formatWrong data type
8Signature problemAuthentication failure
9CompID problemSenderCompID/TargetCompID issue
10SendingTime accuracySendingTime must be within 30 seconds of server time
11Invalid MsgTypeUnknown message type

BusinessMessageReject (35=j)

Used for application-level business logic errors.
TagNameDescriptionRequired
45RefSeqNumSequence number of rejected messageYes
58TextHuman-readable error descriptionNo
371RefTagIDTag that caused the rejectionNo
372RefMsgTypeMessage type being rejectedNo
379BusinessRejectRefIDBusiness ID from rejected messageNo
380BusinessRejectReasonBusiness rejection reason codeYes

Business Reject Reasons (380)

CodeReasonDescription
0OtherSee Text field
1Unknown IDReferenced ID not found
2Unknown SecurityInvalid symbol
3Unsupported Message TypeMessage type not implemented on this margin session
4Application not availableSystem temporarily unavailable
5Conditionally required field missingContext-specific field missing

Order-Specific Rejections

Order Reject Reasons (103)

In ExecutionReport (35=8) with ExecType=Rejected:
CodeReasonCommon Causes
1Unknown symbolInvalid margin market ticker
2Exchange closedTrading paused or unavailable
3Order exceeds limitRisk limit breach or insufficient margin
4Too late to enterMarket not accepting new orders
5Stale orderExpired timestamp on request
6Duplicate orderClOrdID already used
11Unsupported order characteristicInvalid order parameters
13Incorrect quantityInvalid order size
15Unknown accountSubaccount not found or permission denied
99OtherSee Text field

Cancel Reject Reasons (102)

In OrderCancelReject (35=9):
CodeReasonDescription
0Too late to cancelOrder already filled
1Unknown orderOrder not found or identifiers do not match
99OtherSee Text field

Common Error Scenarios

Example: Invalid Tag
// Sent
8=FIXT.1.1|35=D|11=123|38=10|333333=test|...

// Response: Reject
8=FIXT.1.1|35=3|45=5|58=Undefined tag received|371=333333|372=D|373=3|
Example: Order Rejected by Exchange
// Sent
8=FIXT.1.1|35=D|11=456|38=10|55=BTC-PERP|44=19.5000|...

// Response: ExecutionReport (Rejected)
8=FIXT.1.1|35=8|11=456|150=8|39=8|58=EXCHANGE_PAUSED|103=2|...
Order-entry failures returned by the exchange are sent as ExecutionReport (35=8) with ExecType=Rejected, not as BusinessMessageReject. BusinessMessageReject (35=j) is used for application-layer failures before normal exchange rejection handling, such as rate limiting or listener-session restrictions.
Example: Insufficient Balance
// Response: ExecutionReport
8=FIXT.1.1|35=8|11=789|150=8|39=8|58=INSUFFICIENT_BALANCE|103=3|...

Troubleshooting

MsgSeqNum Too High on Logon

Symptom: Logon fails or the server sends a ResendRequest for messages the client doesn’t have. Cause: The client is sending a MsgSeqNum higher than what the server last saw. This typically happens when the client’s local sequence store persists across sessions but the server has reset (e.g. after maintenance or a prior ResetSeqNumFlag=Y logon). Fix:
  • KalshiNR, KalshiDC: Set ResetSeqNumFlag<141>=Y on every Logon. These sessions require it; Logon will be rejected without it.
  • KalshiRT: If you don’t need to recover missed messages, set ResetSeqNumFlag<141>=Y to reset both sides to 1. If you do need retransmission continuity, ensure your local sequence store matches the server’s state.
If using QuickFIX, set ResetOnLogon=Y in your session config for non-retransmission sessions.

SendingTime Rejected

Symptom: Reject (35=3) with SessionRejectReason<373>=10. Cause: The client’s clock is more than 30 seconds off from the server. Sync your system clock via NTP.

Duplicate Session (“already exists”)

Symptom: Logout (35=5) immediately after Logon with Text<58>="already exists". Cause: Another FIX connection is already active with the same API key and TargetCompID. Only one connection is allowed per API key per session type. This can also occur if a previous connection was not cleanly closed and the server hasn’t yet detected the disconnect. Fix: Ensure the previous session is fully disconnected before reconnecting. If the prior connection was lost unexpectedly, wait for the server’s heartbeat timeout to expire (up to 60 seconds depending on your HeartbeatInt setting) before retrying. Use separate API keys for concurrent connections.

Logon Signature Rejected

Symptom: Logout immediately after Logon with a signature error. Cause: The SendingTime used in the pre-hash string doesn’t match the SendingTime<52> in the actual Logon message. If using a FIX library, the library may auto-populate SendingTime. Use that exact value when computing the signature, not a separately generated timestamp.