# FIX Market Data API

Market makers use the Integral FIX Market Data API to get real-time L1 market data.

## Implementation details

This specification is based on the FIX 4.3 standard (https://www.fixtrading.org/) and has been adapted to Integral’s requirements. Users should have a basic knowledge of the FIX protocol and FIX messaging.

The Integral FIX Market Data API only supports messages, component blocks, and fields that are described in this document. All fields not in this document are ignored by Integral, including fields that are required or conditionally required by the FIX protocol.

### Market data sessions

#### Session type

The Integral FIX Market Data API operates on a single market data session for receiving real-time market data. You initiate the market data session to subscribe to and receive streaming market data.

FIX messages on the market data session are transient and are not persisted. Integral does not resend any market data messages in response to a resend request from a client app.

#### Session availability

Weekly market-data sessions are available from 17:00:05 EST/EDT Sunday through 17:00:00 EST/EDT Friday.

Sessions are off-line daily for general maintenance from 17:00:00 EST/EDT Sunday until 17:00:05 EST/EDT Sunday. Sessions do not go off-line during the week.

The FIX sequence numbers for all sessions are reset during general maintenance.

To successfully reconnect at 17:00:05 EST/EDT, you must send a Logon message with a sequence number of “1” (one). Integral’s Logon response also has a sequence number of “1” (one).

Integral sends a Logout message at 17:00 EST/EDT. Upon receipt of this message, you should disconnect by sending a Logout message.

#### Intra-session reconnections

For intra-session disconnections, Integral recommends using the next sequence number to reconnect to maintain FIX session persistence.

If your sequence numbers need a reset, your app must send a Logon message with a sequence number of “1” (one) and the `ResetSeqNumFlag` (#141) set to “Y”. Integral replies with a Logon message with the sequence number set to “1” (one).

### Supported message set

The Integral FIX Market Data API supports only the following FIX message types. Any other message types received by Integral are rejected.

#### Supported session-level messages

Message direction is from the customer's perspective.

Supported session-level messages 

| Direction | Message name | `MsgType` (#35)  | Message purpose |
|  --- | --- | --- | --- |
| In, Out | Logon | A | Customer initiates a FIX session.
Integral responds to a successful Logon request. |
| In, Out | Logout | 5 | Customer or Integral ends a FIX session. |
| In, Out | Heartbeat | 0 | Customer or Integral signals the status of the communication link. Should be sent when no data has been sent for the number of seconds set by `HeartBtInt` (#108). |
| In, Out | Test Request | 1 | Customer or Integral queries the status of the connection when no data has been received for twice the number of seconds set by `HeartBtInt` (#108).The receiving party should always send a Heartbeat message in response to a Test Request message.
 |
| In, Out | Session-level Reject | 3 | Customer or Integral cannot process a message. |
| In, Out | Resend Request | 2 | Customer or Integral detects a gap in the number sequence `MsgSeqNum` (#34) and requests retransmission of messages. |
| In, Out | Sequence Reset | 4 | Customer or Integral resets `MsgSeqNum` (#34) after receiving a Resend Request. |


#### Supported business messages

Message direction is from the customer's perspective.

Supported business messages 

| Direction | Message name  | `MsgType` (#35)  | Message purpose |
|  --- | --- | --- | --- |
| Out | Market Data Request | V | Customer subscribes to and unsubscribes from market data. |
| In | Market Data Snapshot/Full Refresh | W | Customer receives updates for subscribed price streams as a full snapshot. |
| In | Market Data Request Reject | Y | Indicates that the market data request cannot be processed. |


#### Message validation

Integral validates all FIX messages to ensure the presence of all mandatory and conditional fields and component blocks.

For messages that fail validation, Integral follows the FIX protocol where possible and responds with the following reject messages by message type:

Corresponding reject message types 

| Customer message (rejected) | Reject response from Integral |
|  --- | --- |
| Logon (#35=A) | Logout (#35=5) |
| Market Data Request (#35=V) | Market Data Request Reject (#35=Y) |


### Session management

#### Connect

The Integral FIX Market Data API acts as the acceptor for all FIX sessions. The customer initiates the connection by sending a FIX Logon message. If the connection can be established, Integral responds with a Logon acknowledgment message.

If the Logon fails, Integral responds with a Logout message. The Logout message includes a rejection reason for the failure in the `Text` (#58) field.

#### Heartbeat

Both the customer's app and Integral send the Heartbeat message to indicate that the connection is active.

The Test Request message forces a heartbeat from the receiving system. The receiving system responds to a Test Request message with a Heartbeat message containing the `TestReqID` (#112) sent in the Test Request message.

#### Disconnect

Both the customer's app and Integral can initiate disconnection by sending a Logout message. The other party should acknowledge this message with a Logout acknowledgment message.

### Market data

The Integral FIX Market Data API supports a single currency pair per Market Data Request message.

Integral responds to a successful Market Data Request message with one or more Market Data Snapshot/Full Refresh messages. Each Market Data message contains the `MDReqID` (#262) of the originating Market Data Request message.

Market data response messages contain one or more prices as indicated by the `NoMDEntries` (#268) field. Each market data entry is either a bid or an offer and is represented as a group of fields, including a price and a size.

#### Market data snapshots

Market Data Snapshots are snapshots of the order book sorted by price. Each price level has a price and the total amount available at that price.

Customers request market data snapshots by sending a Market Data Request message with the number of price levels requested in the `MarketDepth` (#264) field. If set to one, Integral publishes only the top of book. If set to three, Integral publishes the first three price levels. To receive the maximum price levels (currently five), set the field to zero.

Each price in the market data response is tradable independent of the other prices in the message.

Each market data snapshot replaces the previously sent market data snapshot.

#### Active (tradable) vs. inactive (non-tradable) prices

The `QuoteCondition` (#276) field in the Market Data Snapshot/Full Refresh message indicates whether the price is tradable. A value of “A” indicates that the price is active (tradable). A value of “B” indicates that the price is inactive (non-tradable).

A Market Data – Snapshot/Full Refresh message containing inactive, non-tradable prices on both sides (`QuoteCondition` (#276) = B) means that there is no market data currently available for the instrument associated with the Market Data Request. Any market data received previously for that instrument should be discarded. If non-tradable prices are received for an instrument on one side, the previous market data for that instrument and side should be discarded.

#### Price conventions

Integral follows standard OTC spot market conventions for order price precision to one-tenth of a pip. You can review Integral price conventions at the following Web site:

https://www.integral.com/minimum-size-and-price-conventions/

### Common message components

This section describes the features common to each message format in the Integral FIX Market Data API.

#### Terminology

Each Integral FIX Market Data API message is comprised of message fields defined in this document. Each field has its own set of attributes including:

* Tag: field number.
* Field name: human-readable name for reference.
* Req’d: indicates if the field must be sent on the FIX message:
  * Y = required by the FIX protocol.
  * Y(API) = required by the FIX Market Data API implementation.
  * N = optional for both the FIX Market Data API and the FIX protocol.
  * C = conditional. Refer to the field’s description to determine applicability.
* Valid values: specific values accepted for this field.
* Description: brief description of the field.
* Type(length): FIX data type of the field and the maximum length of the field value.
* →: arrow indicates a field in a repeating group.


#### Standard header

Each message type sent over the Integral FIX Market Data API has a standard header component as described below. The header is abbreviated as <Standard header> in this document.

Standard header format 

| Tag | Field name | Req’d | Valid values | Description | Type(length) |
|  --- | --- | --- | --- | --- | --- |
| 8 | BeginString | Y | FIX4.3 | Identifies beginning of new message and protocol version. Must be the first field in the message. | String(7) |
| 9 | BodyLength | Y | — | Message length (in bytes) forward to the `CheckSum` (#10) field. Must be the second field in the message. | int(6) |
| 35 | MsgType | Y | — | Defines the type of the message. Must be the third field in the message. | String(2) |
| 49 | SenderCompID | Y | — | This value is used to identify the firm sending the message. Should be set with the `SenderCompID` (#49) supplied by Integral for this FIX connection. | String(20) |
| 56 | TargetCompID | Y | — | This value is used to identify the firm receiving the message. Should be set with the `TargetCompID` (#56) supplied by Integral for this FIX connection. | String(20) |
| 34 | MsgSeqNum | Y | — | Integer message sequence number. | SeqNum(9) |
| 43 | PossDupFlag | N | Y=Possible Duplicate
N=Original Transmission | Indicates possible retransmission of message with this sequence number. Must be set to “Y” for messages sent in response to a Resend Request. | Boolean(1) |
| 52 | SendingTime | Y | — | Time the message was transmitted. Always expressed in UTC. | UTCTimestamp(21) |


#### Standard trailer

Each message type sent over the Integral FIX Market Data API also has a standard trailer component as described below. The header is abbreviated as <Standard trailer> in this document.

Standard trailer format 

| Tag | Field name | Req’d | Valid values | Description | Type(length) |
|  --- | --- | --- | --- | --- | --- |
| 10 | Checksum | Y | — | Three-byte checksum. Always the last tag in the message. Functions as an end-of-message delimiter. | String(3) |


## Administrative messages

### Logon

The customer sends a Logon message to establish a FIX session with Integral. If the Logon fails, Integral responds with a Logout message. The `Text` (#58) field of the Logout message contains the reason for the rejection of the Logon message.

Valid responses 

* Logon (#35=A)
* Logout (#35=5)


Message format 

Logon format 

| Tag | Field name | Req’d | Valid values | Description | Type(length) |
|  --- | --- | --- | --- | --- | --- |
| <Standard header>  | Y | — | 35=A | — |
| 98 | EncryptMethod | Y | 0=None | Always unencrypted | int(1) |
| 108 | HeartBtInt | Y | — | Heartbeat interval in seconds. The customer’s app determines the heartbeat interval. | int(3) |
| 141 | ResetSeqNumFlag | N | Y=Yes, reset sequence numbers
N=No | Indicates that both sides of the FIX session should reset sequence numbers. | Boolean(1) |
| 553 | Username | Y(API) | — | Should be set with the username supplied by Integral for this FIX connection. | String(20) |
| 554 | Password | Y(API) | — | Should be set with the password supplied by Integral for this FIX connection. | String(20) |
| <Standard trailer>  | Y | — | — | — |


### Logout

The customer sends a Logout message to end a session. Integral sends a single Logout message in response when all Logout related actions have been completed by Integral.

Valid responses 

* Logout (#35=5)


Message format 

Logout format 

| Tag | Field name | Req’d | Valid values | Description | Type(length) |
|  --- | --- | --- | --- | --- | --- |
| <Standard header>  | Y | — | 35=5 | — |
| 58 | Text | N | — | The reason for the Logon rejection. Only included for Logout messages in response to an invalid Logon message. | String(150) |
| <Standard trailer>  | Y | — | — | — |


### Heartbeat

Integral and the customer send a Heartbeat message in response to a Test Request message to ensure connectivity. The Heartbeat message includes the `TestReqID` (#112) value from the received Test Request.

Valid responses 

* None


Message format 

Heartbeat format 

| Tag | Field name | Req’d | Valid values | Description | Type(length) |
|  --- | --- | --- | --- | --- | --- |
| <Standard header>  | Y | — | 35=0 | — |
| 112 | TestReqID | C | — | Required if heartbeat message is generated in response to a Test Request message. In this case, this tag must contain the TestReqID that was sent in the Test Request message. | String(20) |
| <Standard trailer>  | Y | — | — | — |


### Test Request

Integral and the customer send a Test Request message to force a heartbeat from the receiving app. The receiving app responds with a Heartbeat message that includes the `TestReqID` (#112) value from the received Test Request.

Valid responses 

* Heartbeat (#35=0)


Message format 

Test Request format 

| Tag | Field name | Req’d | Valid values | Description | Type(length) |
|  --- | --- | --- | --- | --- | --- |
| <Standard header>  | Y | — | 35=1 | — |
| 112 | TestReqID | C | — | This identifier should be returned in the Heartbeat response. | String(20) |
| <Standard trailer>  | Y | — | — | — |


### Session-level Reject

A Session-level Reject message is sent by Integral when a message is received but cannot be processed.

Valid responses 

* None


Message format 

Session-level Reject format 

| Tag | Field name | Req’d | Valid values | Description | Type(length) |
|  --- | --- | --- | --- | --- | --- |
| <Standard header>  | Y | — | 35=3 | — |
| 56 | TargetCompID | N | — | The `SenderSubID` (#50) supplied in the Market Data Request message, if any. | String(20) |
| 45 | RefSeqNum | Y | — | `MsgSeqNum` (#34) of the message being rejected. | SeqNum(9) |
| 371 | RefTagID | N | — | Tag ID of the field being referenced. | int(4) |
| 372 | RefMsgType | Y(API) | — | The `MsgType` (#35) of the FIX message being rejected. | String(2) |
| 373 | SessionRejectReason | Y(API) | 0=Invalid tag number.
1=Required tag missing.
2=Tag not defined for message type.
3=Undefined tag.
4=Tag specified without a value.
5=Value is incorrect (out of range) for this tag.
6=Incorrect data format for value.
7=Decryption problem.
8=Signature problem.
9=CompID problem.
10=SendingTime accuracy problem.
11=Invalid MsgType.
12=XML validation error.
13=Tag appears more than once.
14=Tag specified out of required order.
15=Repeating group fields out of order.
16=Incorrect NumInGroup count for repeating group.
17=Non “data” value includes field delimiter (SOH character).
99=Other. | Rejection code. | int(4) |
| 58 | Text | Y(API) | — | Reason the message was rejected. | String(150) |
| <Standard trailer>  | Y | — | — | — |


### Resend Request

The receiving app sends a Resend Request message to initiate the retransmission of messages, typically when it detects a gap in the message sequence number. The sender can request a single message or a range of messages.

The Resend Request message applies only to persistent sessions.

Valid responses 

* Various


Message format 

Resend Request format 

| Tag | Field name | Req’d | Valid values | Description | Type(length) |
|  --- | --- | --- | --- | --- | --- |
| <Standard header>  | Y | — | 35=2 | — |
| 7 | BeginSeqNo | Y | — | Message sequence number of the first message in range to be re-sent. | int(9) |
| 16 | EndSeqNo | Y | — | Message sequence number of the last message to be re-sent. | int(9) |
| <Standard trailer>  | Y | — | — | — |


## Application messages

### Market Data Request

Integral FIX Market Data API customers request real-time price streams with the Market Data Request message.

Valid responses 

* Market Data Snapshot/Full Refresh (#35=W)
* Market Data Request Reject (#35=Y)


Message format 

Market Data Request format 

| Tag  | Field name | Req’d | Valid values | Description | Type(length) |
|  --- | --- | --- | --- | --- | --- |
| <Standard header>  | Y | — | 35=V | — |
| 128  | DeliverToCompID | N | ALL | — | String(10) |
| 50  | SenderSubID | N | — | The `SenderSubID` (#50) supplied by Integral for this FIX connection, if any. | String(20) |
| 9502  | ClientTagID | N | — | Unique identifier of the undisclosed customer whose market data is being requested. This client tag is sent in the `MDEntryOriginator` (#282) field of market data refresh messages. | String(10) |
| 262  | MDReqID | Y | — | Client assigned unique ID for subscription if `SubscriptionRequestType` (#263)=1 (Subscribe) or the ID of a subscription to disable if `SubscriptionRequestType` (#263)=2 (Unsubscribe). | String(11) |
| 263  | SubscriptionRequestType | Y | 1=Subscribe
2=Unsubscribe | Indicates the action to be taken for streaming prices. | char(1) |
| 264  | MarketDepth | Y | 0=Full Book
1=Top of Book
N>1=Top N price levels of market data | Used to specify the number of price levels being requested. | int(1) |
| 265  | MDUpdateType | C | 0=Full Refresh | Type of Market Data update. | int(1) |
| 267  | NoMDEntryTypes | Y | 2 | Repeating group: Number of `MDEntryTypes` (#269) being requested. Must always be 2. | NumInGroup(1) |
| → | 269 | MDEntryType | Y | 0=Bid
1=Offer | The type of market data requested, confined to the side of the rates, either buy or sell. | char(1) |
| 146  | NoRelatedSym | Y | 1 | Repeating group: Number of currency pairs being requested. Must always be 1. | NumInGroup(1) |
| → | 55 | Symbol | Y(API) | — | Currency pair. | String(35) |
| → | 460 | Product | Y(API) | 4=CURRENCY | Indicates the type of product. | int(1) |
| <Standard trailer>  | Y | — | — | — |


### Market Data Snapshot/Full Refresh

Integral responds to a successful Market Data Request message with one or more Market Data Snapshot/Full Refresh messages when `MDUpdateType` (#265) on the request is set to 0 (zero). Each Market Data message contains the `MDReqID` (#262) of the originating Market Data Request message.

Market Data message contain one or more prices (market data entries) as indicated by the `NoMDEntries` (#268) field. Each market data entry is either a bid or an offer and is represented as a group of fields, including a price and a size.

The Market Data Snapshot/Full Refresh message communicates the current price of the requested instrument (`Symbol` (#55)) followed by subsequent messages with changes to the price and associated attributes like the price size and quote condition (active/inactive). Each Market Data Snapshot/Full Refresh message for an instrument replaces any previously transmitted market data message for that instrument.

A Market Data – Snapshot/Full Refresh message containing inactive, non-tradable prices on both sides (`QuoteCondition` (#276) = B) means that there is no market data currently available for the instrument associated with the Market Data Request. Any market data received previously for that instrument should be discarded. If non-tradable prices are received for an instrument on one side, the previous market data for that instrument and side should be discarded.

Valid responses 

* None


Message format 

Market Data Snapshot/Full Refresh format 

| Tag  | Field name | Req’d | Valid values | Description | Type(length) |
|  --- | --- | --- | --- | --- | --- |
| <Standard header>  | Y | — | 35=W | — |
| 57  | TargetSubID | N | — | The `SenderSubID` (#50) supplied in the Market Data Request message, if any. | String(20) |
| 262  | MDReqID | Y | — | Refers to the originating market data request. | String(11) |
| 55  | Symbol | Y | — | Currency pair. | String(35) |
| 460  | Product | Y | 4=CURRENCY | Indicates the type of product. | int(1) |
| 541  | MaturityDate | Y | — | Date of maturity. | String(4) |
| 268  | NoMDEntries | Y | — | Number of prices in the market data message. Each bid and offer is considered a separate market data entry. | NumInGroup(1) |
| → | 269 | MDEntryType | Y | 0=Bid
1=Offer | Type of Market Data entry. | char(1) |
| → | 270 | MDEntryPx | Y | — | Price associated with this market data entry. | Price(20) |
| → | 15 | Currency | Y | — | Specifies the currency of the market data entry. | String(3) |
| → | 271 | MDEntrySize | Y | — | Quantity or size represented by the market data entry. | Qty(20) |
| → | 276 | QuoteCondition | Y | A=Tradable
B=Not tradable | Indicates whether the price represented by the market data entry is active (tradable) or inactive (not tradable). | char(1) |
| → | 110 | MinQty | Y(API) | — | Minimum quantity required for the order to be executed. | Qty(20) |
| → | 299 | QuoteEntryID | Y | — | Unique ID for each market data entry. | String(15) |
| → | 282 | MDEntryOriginator | N | — | The client tag of the undisclosed customer for whom the market data was requested. This is the client tag that was sent in the `ClientTagID` (#9502) field of Market Data Request message. | String(20) |
| → | 290 | MDEntryPositionNo | Y | 0 | Always set to 0 (zero). | int(1) |
| <Standard trailer>  | Y | — | — | — |


### Market Data Request Reject

Integral sends the Market Data Request Reject message to the customer in response to a Market Data Request message that cannot be honored due to business or technical reasons. The fields `MDReqRejReason` (#281) and `Text` (#58) describe the reason for the rejection.

Valid responses 

* None


Message format 

Market Data Request Reject format 

| Tag | Field name | Req’d | Valid values | Description | Type(length) |
|  --- | --- | --- | --- | --- | --- |
| <Standard header>  | Y | — | 35=Y | — |
| 57 | TargetSubID | Y | — | The `SenderSubID` (#50) supplied in the Market Data Request message, if any. | String(20) |
| 262 | MDReqID | Y | — | The unique identifier from the originating Market Data Request. | String(11) |
| 281 | MDReqRejReason | N | 0=Unknown symbol
1=Duplicate MDReqID
3=Insufficient Permissions | The reason for the reject. | char(1) |
| 58 | Text | N | — | Description of why the market data request is being rejected. | String(100) |
| <Standard trailer>  | Y | — | — | — |