Exchange FIX Order Entry Messages 4.2
About this API:
- Baseline: FIX 4.2 SP2 specification. Includes tags from later FIX versions plus custom tags in the high number range as allowed by the standard.
- Environments: Production, Sandbox
- Production:
tcp+ssl://fix.exchange.coinbase.com:4198
- Sandbox:
VAR::FIX_URL_SAND_ORDER_ENTRY_42
Header
A standard header must be present at the start of every message in both directions.
Tag | Name | Description |
---|---|---|
8 | BeginString | Must be FIX.4.2 |
49 | SenderCompID | Client API key (on messages from the client) |
56 | TargetCompID | Must be Coinbase (on messages from the client) |
999 | CoinbaseProductSeq | Response header only (returned on Execution Reports). Represents market sequence. |
New orders can only be placed when the number of open orders is below 500 for that given product.
Logon (A)
Sent by the client to initiate a session and by the server as an acknowledgement. Only one session may exist per connection; sending a Logon message within an established session is an error.
Tag | Name | Description |
---|---|---|
34 | MsgSeqNum | Must be 1 |
98 | EncryptMethod | Must be 0 (None) |
108 | HeartBtInt | Must be ≤ 30 (secs). Values greater are capped at 30 . Server sends Test Request if client messages are not received in approximately (HeartBtInt x 1.5) seconds. Server terminates session if client messages are not received in approximately (HeartBtInt x 2 seconds). |
141 | ResetSeqNumFlag | If set to Y , reset sequence numbers for both sides of the FIX session. |
554 | Password | Client API passphrase |
96 | RawData | Client message signature (see below) |
8013 | CancelOrdersOnDisconnect | S : Batch cancel all open orders placed during session; Y : Batch cancel all open orders for the current profile. The latter is more performant and recommended. |
9406 | DropCopyFlag | If set to Y , execution reports are generated for all user orders (defaults to Y ). |
The Logon message sent by the client must be signed for security. The signing method is described in Signing a Message. The prehash string is the following fields joined by the FIX field separator (ASCII code 1):
SendingTime, MsgType, MsgSeqNum, SenderCompID, TargetCompID, Password
.
There is no trailing separator. The RawData
field should be a base64 encoding of the HMAC signature.
// create a new Logon message
var logon = new Msgs.Logon();
logon.SendingTime = new Date();
logon.HeartBtInt = 30;
logon.EncryptMethod = 0;
logon.passphrase = "...";
var presign = [
logon.SendingTime,
logon.MsgType,
session.outgoing_seq_num,
session.sender_comp_id,
session.target_comp_id,
passphrase,
].join("\x01");
// add the presign string to the RawData field of the Logon message
logon.RawData = sign(presign, secret);
// send the logon message to the server
session.send(logon);
function sign(what, secret) {
var key = Buffer.from(secret, "base64");
var hmac = crypto.createHmac("sha256", key);
return hmac.update(what).digest("base64");
}
To establish multiple FIX connections, generate a new API key for each one. The maximum is 75 connections per profile. Do not use a single API key for multiple connections at the same time.
The value of SendingTime
must be within 5 minutes of server time in UTC.
Logout (5)
Sent by either side to initiate session termination. The side which receives this message first should reply with the same message type to confirm session termination.
Do not close a connection without logging out of the session first or it triggers an error.
New Order Single (D)
Sent by the client to enter an order. Each profile can place a maximum of 500 open orders on a product. Once reached, the profile cannot place any new orders until the total number of open orders is below 500 .
Tag | Name | Description |
---|---|---|
11 | ClOrdID | UUID selected by client to identify the order |
55 | Symbol | Required symbol to identify the new order, e.g., BTC-USD |
54 | Side | Must be 1 to buy or 2 to sell |
44 | Price | Limit price (e.g., in USD) (Limit order only) |
38 | OrderQty | Order size in base units (e.g., BTC) |
152 | CashOrderQty | Order size in quote units (e.g., USD) (Market order only) |
40 | OrdType | Must be 1 for Market, 2 for Limit, or 4 for Stop Limit |
99 | StopPx | Stop price for order |
59 | TimeInForce | Must be a valid TimeInForce value. See the table below (Limit order only) |
111 | MaxFloor | Maximum size within an order to be displayed. Must be > 10% of OrderQty |
126 | ExpireTime | Time/Date (in UTC) of order expiration for Good Till Date (GTD) only. The order expires within one second after the specified time. |
1109 | TriggerPriceDirection | The side from which the trigger price (or last trade price) is reached. Valid values:
|
7928 | SelfTradePrevention | Optional, see the table below |
SelfTradePrevention Values
Value | Description |
---|---|
D | Decrement and cancel (the default) |
O | Cancel resting order |
N | Cancel incoming order |
B | Cancel both orders |
If an order is decremented due to self-trade prevention, an Execution Report is sent to the client with ExecType=D
indicating unsolicited OrderQty
reduction (i.e., partial cancel).
See the self-trade prevention documentation for more details about this field.
Time In Force Values
Value | Policy | Abbr |
---|---|---|
1 | Good Till Cancel | GTC |
3 | Immediate or Cancel | IOC |
4 | Fill or Kill | FOK |
6 | Good Till Date (90-day hard limit) | GTD |
P | Post-Only (GTC & make liquidity only) |
The post-only flag (P
) indicates that the order should only make liquidity. If any part of the order results in taking liquidity, the order is rejected and no part of it executes. Open Post-Only orders are treated as Good Till Cancel.
See the Time In Force documentation for more details about these values.
Errors
If a trading error occurs (for example, the user has insufficient funds), an Execution Report with ExecType=8
is sent back, signifying that the order was rejected.
Iceberg Orders
See Iceberg Orders.
Take Profit Stop Loss Orders
See TPSL Orders.
New Order Batch (U6)
Sent by the client to create multiple orders. Maximum of 15 orders per message. All orders must have the same symbol.
Each profile can place a maximum of 500 open orders on a product. Once reached, the profile cannot place any new orders until the total number of open orders is below 500 . If the total number of open orders in the batch causes the profile to exceed the 500 maximum, the entire batch is rejected.
Tag | Name | Description |
---|---|---|
8014 | BatchID | UUID selected by client to identify this New Order Batch request |
73 | NoOrders | Number of orders in this message (number of repeating groups to follow). Must be less than or equal to 15. |
11 | ClOrdID | UUID selected by client for the order. Must be the first field in the repeating group. |
55 | Symbol | Required symbol to identify the new order (e.g., BTC-USD ) |
54 | Side | Must be 1 to buy or 2 to sell |
44 | Price | Limit price (e.g., in USD) |
38 | OrderQty | Order size in base units (e.g., BTC) |
40 | OrdType | Must be 2 for Limit |
59 | TimeInForce | Must be a valid TimeInForce value |
126 | ExpireTime | Time/Date (in UTC) of order expiration for Good Till Date (GTD) only. The order expires within one second after the specified time. |
7928 | SelfTradePrevention | Optional, see the table above |
Order Cancel Request (F)
Sent by the client to cancel an order.
Tag | Name | Description |
---|---|---|
11 | ClOrdID | UUID selected by client to identify this cancel request |
37 | OrderID | OrderID from the ExecutionReport with OrdStatus=New (39=0) |
41 | OrigClOrdID | ClOrdID from the New Order Single. When supplying this value, you do not need to supply an OrderID. |
55 | Symbol | Required symbol of the order to cancel (must match Symbol of the Order). |
58 | Text | Free format text string |
Order Status Request (H)
Sent by the client to obtain information about pending and done orders.
Tag | Name | Description |
---|---|---|
37 | OrderID | OrderID of order to be sent back. |
11 | ClOrdID | ClOrdID of order to be sent back. When supplying this value, you do not need to supply an OrderID. |
55 | Symbol | Required symbol to identify the order, e.g., BTC-USD |
Response
The response to an Order Status Request is an ExecutionReport with ExecType=I
. The ExecutionReport contains the ClOrdID
if the value is supplied. If the order cannot be found, the ExecutionReport has OrderID=0
.
Order Cancel Batch Request (U4)
Sent by the client to cancel multiple orders. Maximum of 15 orders per message. All orders must have the same symbol.
Tag | Name | Description |
---|---|---|
8014 | BatchID | UUID selected by client to identify this Order Batch Cancel Request |
73 | NoOrders | Number of orders in this message (number of repeating groups to follow). Must be less than or equal to 15. |
41 | OrigClOrdID | UUID selected by client for the order. Must be the first field in the repeating group. |
55 | Symbol | Required symbol of the order to cancel (must match Symbol of the Order) |
37 | OrderID | OrderID from the ExecutionReport with OrdStatus=New (39=0). If present, this field takes precedence over OrigClOrdID to identify the order (optional). |
11 | ClOrdID | UUID selected by client to identify this cancel request |
Response
When the message is invalid or an unexpected error occurs, an Order Cancel Batch Reject (U5) message is sent. When orders are cancelled, an Execution Report (8) is sent for each order canceled. When Order Cancel Batch Request (U4) is partially rejected (i.e., some orders are filled or already canceled), Order Cancel Reject (9) is sent for each rejected cancel.
Execution Report (8)
Sent by the server when an order is accepted, rejected, filled, or canceled. Also sent when the user sends an OrderStatusRequest
.
Tag | Name | Description |
---|---|---|
6 | AvgPx | Calculated average price of all fills on this order. Only popluates Exec Report if CumQty > 0 |
11 | ClOrdID | Only present on order acknowledgements, ExecType=New (150=0) |
14 | CumQty | Currently executed quantity for chain of orders. Populates Exec Report when:
|
17 | ExecID | Unique identifier of execution message as assigned by broker |
37 | OrderID | OrderID from the ExecutionReport with ExecType=New (150=0) |
39 | OrdStatus | Order status as of the current message |
55 | Symbol | Symbol of the original order |
54 | Side | Must be 1 to buy or 2 to sell |
32 | LastShares | Amount filled (if ExecType=1). Also called LastQty as of FIX 4.3 |
44 | Price | Price of the fill if ExecType indicates a fill, otherwise the order price |
38 | OrderQty | OrderQty as accepted (may be less than requested upon self-trade prevention). Represents original order quantity when OrdStatus is Canceled or Done for day. |
111 | MaxFloor | Maximum size within an order to be displayed. Must be > 10% of OrderQty |
198 | SecondaryOrderID | Assigned by the party that accepts the order. Can be used to provide the OrderID (37) used by an exchange or executing system. |
58 | Text | Human-readable description of the reject or cancel (optional)
|
60 | TransactTime | Time the event occurred |
103 | OrdRejReason | Insufficient funds=3 , Post-only=8 , Unknown error=0 |
136 | NoMiscFees | 1 (Order Status Request responses and fill reports) |
137 | MiscFeeAmt | Fee amount (absolute value for Order Status Request responses, percentage value for fill reports) |
138 | MiscFeeCurr | Fee currency |
139 | MiscFeeType | 4 (Exchange fees) (Order Status Request responses and fill reports) |
150 | ExecType | May be 1 (Partial fill) for fills, D for self-trade prevention, etc. |
151 | LeavesQty | Quantity open for further execution. Populates Exec Report when:
|
152 | CashOrderQty | Order size in quote units (e.g., USD) (Market order only) |
891 | MiscFeeBasis | 2 (Percentage fee basis) (fill report only) |
1003 | TradeID | Product unique trade id |
1057 | AggressorIndicator | Y for taker orders, N for maker orders |
ExecType Values
ExecType | Description |
---|---|
0 | New Order |
1 | Partial Fill |
3 | Done |
4 | Canceled |
7 | Stopped |
8 | Rejected |
D | Restated (Order Changed due to STP) |
I | Order Status |
New Order Batch Reject (U7)
Sent by the server when a New Order Batch message is rejected.
Tag | Name | Description |
---|---|---|
8014 | BatchID | BatchID from the New Order Batch message |
58 | Text | Human-readable description of the error (optional) |
Modify Order Request (G)
Supports the Order Replace Request outlined in the FIX protocol. See also: WebSocket Full Channel, Change.
Each Modify Order Request, per order, must be processed in turn. A client can only send a Modify Order Request after the previous request for the same order has been fully processed.
Example FIX Request:
BeginString=FIX.4.2 BodyLength=265 MsgType=ORDER_CANCEL_REPLACE_REQUEST MsgSeqNum=17 SenderCompID=00000000100000000000000000000003 SendingTime=20220609-04:01:48.757 TargetCompID=Coinbase ClOrdID=907b6ae6-bcbe-441a-b7bb-d932afdb9edb OrderID=71de0cdf-938f-495b-9fad-108837bde704 OrderQty=2 OrdType=LIMIT OrigClOrdID=907b6ae6-bcbe-441a-b7bb-d932afdb9eda Price=100.00 Side=BUY Symbol=ETH-USD TransactTime=20220609-04:01:48.757 CheckSum=107
Example Execution Report:
BeginString=FIX.4.2 BodyLength=253 MsgType=EXECUTION_REPORT MsgSeqNum=18 SenderCompID=Coinbase SendingTime=20220609-04:01:48.766 TargetCompID=00000000100000000000000000000003 ExecID=450d0b12-e994-48de-9f74-0f43c74fd054 ExecTransType=NEW OrderID=71de0cdf-938f-495b-9fad-108837bde704 OrderQty=3 OrdStatus=DONE_FOR_DAY Price=100 Side=BUY Symbol=ETH-USD Text=107:Broker TransactTime=20220609-04:01:48.762 ExecType=DONE_FOR_DAY LeavesQty=0 CheckSum=150
Tag | Name | Description |
---|---|---|
37 | OrderID | Unique identifier of most recent order as assigned by broker |
41 | OrigClOrdID | ClOrdID <11> of previous order (NOT initial order of the day) when canceling or replacing an order |
11 | ClOrdID | Unique identifier of replacement order as assigned by institution. |
55 | Symbol | Must match original order |
54 | Side | Must match original side |
38 | OrderQty | Total Intended Order Quantity (including the amount already executed for this chain of orders) |
60 | TransactTime | Time this order request was initiated/released by the trader or trading system |
40 | OrdType | Only limit orders are supported for now (2) |
44 | Price | Price per share |
Guidance
Queue Priority
- If you increase the quantity, or modify the price (up or down) you lose your place and move to the back of the queue. If you decrease the quantity you keep your place in the queue.
OrderQty (38)
- If you send a Modify Order request whose
OrderQty (38)
is less than the filled size of the order, Coinbase cancels the order and marks it as filled.
Matching
-
If your Modify Order request results in an immediate match and you are both the initiator of the order AND subscribed to the authenticated WebSocket feed, you should receive a change message with
"reason": "modify_order"
.After the immediate match, if there is any quantity remaining on the modified order, you should receive a new change message with
"reason":"remainder_after_modification"
which reports the new / old prices as a result of the Modify Order. -
If you are using the non-authenticated WebSocket feed (as the initiator or not), you should receive a
match + done
message for the order at the newly modified price.
Clients may experience a non-standard FIX OrderCancelReject
with text (when processing the last cancel replace request). This can occur when our system is backlogged and unable to process this Modify Order Request (or OrderCancelReplaceRequest
).
Order Cancel Reject (9)
Sent by the server when an Order Cancel Request cannot be satisfied, e.g., because the order is already canceled or completely filled.
Tag | Name | Description |
---|---|---|
11 | ClOrdID | As on the cancel request |
37 | OrderID | As on the cancel request |
41 | OrigClOrdID | As on the cancel request |
39 | OrdStatus | 4 if too late to cancel |
102 | CxlRejReason | 1 if the order is unknown |
434 | CxlRejResponseTo | 1 (Order Cancel Request) |
Order Cancel Batch Reject (U5)
Sent by the server when an Order Cancel Batch Request cannot be satisfied, e.g., because a Symbol was not present. This is not sent if no orders can be found.
Tag | Name | Description |
---|---|---|
8014 | BatchID | BatchID from the New Order Batch message |
58 | Text | Human-readable description of the error (optional) |
Reject (3)
Sent by either side upon receipt of a message which cannot be processed, e.g., due to missing fields or an unsupported message type.
Tag | Name | Description |
---|---|---|
45 | RefSeqNum | MsgSeqNum of the rejected incoming message |
371 | RefTagID | Tag number of the field which caused the reject (optional) |
372 | RefMsgType | MsgType of the rejected incoming message |
58 | Text | Human-readable description of the error (optional) |
373 | SessionRejectReason | Code to identify reason for reject |
SessionRejectReason Values
The following values can be sent by the server.
Value | Description |
---|---|
1 | Required tag missing |
5 | Value is incorrect (out of range) for this tag |
6 | Incorrect data format for value |
11 | Invalid MsgType (35) |
RFQ Request (AH)
Request For Quote (RFQ) allows liquidity providers to respond and interact with real-time RFQ requests. The RFQ process begins with Quote Request (R).
Request For Quote is enabled for users who have been approved by Coinbase as an RFQ Liquidity Provider. Once approved, clients must send an RFQ Request message (35=AH) after each successful Logon (35=A) message for any session in which you are interested in receiving RFQ requests.
- If this request is acknowledged, and no symbol is specified, this session receives all Quote requests (all assets).
- If this request is acknowledged, and symbol is specified , this session only receives requests for the specific symbols. For instance, in the scenario of subscribing to "BTC-USD," if the related products are present, quote request message for both "BTC-USD" and "USD-BTC" will be subsequently returned as responses.
- If the session submitting this request is not approved by Coinbase for participating in the RFQ program, this request is rejected with a Business Message Reject (j).
Tag | Name | Type | Required | Notes |
---|---|---|---|---|
644 | RFQReqID | UUID | Y | |
146 | NoRelatedSym | Int32 | N | Repeating group for number of symbols in the subscription message |
55 | Symbol | String32 | Y |
Not receiving a response is expected and indicative of a successful request.
RFQ Order Protections
RFQ orders are subject to price protection points (PPP) at the time a quote is accepted for execution.
At Execution time:
-
If an Order Book is present, RFQs fill at prices up to the PPP from the mid-point price, between the best bid and best offer.
-
If an Order Book is not present, PPPs are calculated using the same mid-point price methodology but leveraging PPP settings from the higher of the two USD equivalent Order Books for the given pair (e.g., max PPP setting for SHIB-USD and DOGE-USD for a SHIB-DOGE RFQ).
If a PPP threshold is crossed, a QuoteStatusReport (AI) is sent indicating your Quote has been canceled.
Quote Request (R)
Quote Request (R) is the start of the RFQ process. Liquidity Providers receive a Quote Request from Coinbase on behalf of a customer looking to participate in an RFQ trade. Any quote response to this request must adhere to the following rules to avoid rejections:
- Message must be well formed and complete (i.e., all required fields present).
- Quote message must be received before the expiration time indicated on Tag=62.
Tag | Name | Type | Required | Notes |
---|---|---|---|---|
131 | QuoteReqID | UUID | R | |
146 | NoRelatedSym | Int32 | Y | Always 1 |
55 | Symbol | String32 | Y | Example: BTC-AVAX |
38 | OrderQty | Float64 | Y | |
62 | ValidUntilTime | UTCTimestamp | Y | UTC millis20220712-00:00:00.000 |
126 | ExpireTime | UTCTimestamp | Y | UTC millis20220712-00:00:00.000 |
303 | QuoteRequestType | Char | Y | 1 = Manual Accept 2 = Automatic Accept (default) |
891 | MiscFeeBasis | INT | Y | Always 2 = Percentage |
137 | MiscFeeAmt | AMT | Y | Basis point fee to market makers (MMs) |
QuoteRequestType (303) is always 2 = Automatic Accept
for the current implementation of RFQ on Coinbase Exchange.
MiscFeeBasis (891) is always 2 = Percentage
for the current implementation of RFQ on Coinbase Exchange.
See also the new WebSocket RFQ Matches Channel.
Quote (S)
Quote in response to a Quote Request that can be submitted up to the ValidUntilTime
(Tag=62) specified in the Quote Request message. The Quote can be submitted as either a one-way quote or two-way quote. Only one side is actioned on if participant wins RFQ.
Precision for price and size is limited to 16 decimal places and 40 digits total.
Tag | Name | Type | Required | Notes |
---|---|---|---|---|
131 | QuoteReqID | UUID | Y | |
117 | QuoteID | UUID | Y | |
55 | Symbol | String32 | Y | Example: BTC-AVAX |
132 | BidPx | Float64 | C | Required if submitting a bid |
133 | OfferPx | Float64 | C | Required if submitting an offer |
134 | BidSize | Float64 | C | Required if submitting a bid. Must match OrderQty in Quote Request |
135 | OfferSize | Float64 | C | Required if submitting an offer. Must match OrderQty in Quote Request |
Quote Status Report (AI)
` Message sent in response to a successful or unsuccessful Quote.
- If the Quote was accepted, QuoteStatus=16 (Active).
- If the Quote was rejected, QuoteStatus=9 (Rejected).
- If the Quote was accepted and selected for execution, QuoteStatus=19 (Pending), and you receive an Execution Report.
- If the Quote was accepted but not selected for execution, QuoteStatus=17 (Canceled).
- If there is no response to a Quote request from Liquidity Providers, QuoteStatus=7 (Expired).
Tag | Name | Type | Required | Notes |
---|---|---|---|---|
131 | QuoteReqID | UUID | Y | |
117 | QuoteID | UUID | C | |
55 | Symbol | String32 | Y | Example: BTC-AVAX |
38 | OrderQty | Float64 | Y | Echoed from Quote 35=S |
132 | BidPx | Float64 | Y | Echoed from Quote 35=S |
133 | OfferPx | Float64 | Y | Echoed from Quote 35=S |
134 | BidSize | Float64 | C | Must match OrderQty in Quote Request |
135 | OfferSize | Float64 | C | Must match OrderQty in Quote Request |
62 | ValidUntilTime | UTCTimestamp | Y | UTC millis20220712-00:00:00.000 |
126 | ExpireTime | UTCTimestamp | Y | UTC millis20220712-00:00:00.000 |
297 | QuoteStatus | Int32 | Y | 5 = Rejected: Insufficient funds (in response to 35=S)7 = Expired:▪ Either no response to 35=S from liquidity providers ▪ Or best quote not accepted by counterparty 16 = Active: Quote successful (in response to 35=S) 17 = Canceled:▪ Either quoting window expired bc quote not best ▪ Or RFQ was unable to hold funds 19 = Pending Trade: RFQ selected for execution |
58 | Text | String | C | Required if QuoteStatus=5, Quote action was rejected |
Resend Request (2)
FIX Resend Requests are sent by the receiving application to initiate the retransmission of messages.
Tag | Name | Description |
---|---|---|
7 | BeginSeqNo | Sequence number of first message in range to be resent |
16 | EndSeqNo | Sequence number of last message in range to be resent |
Guidance
-
To successfully use replay functionality, submit a unique
senderLocationID
when logging on (because you can have multiple connections per API key).SenderLocationID <142> identifies the message originator's location.
-
To replay messages from a previous session, include
ResetSeqNumFlag=N
in your logon message (because, by default, we clear users sessions when logging on). You must also include the samesenderLocationID
used in the previous session to continue the session.ResetSeqNumFlag <141> is a boolean flag that indicates whether or not both sides of the FIX session should reset sequence numbers.
Sequence Numbers
Each request must be in batches of 2000 messages or less and lookback (the duration we keep messages) is 3 hours. For example, say you received messages in sequence range 4000-10000 within the last 3 hours:
- You can retrieve all messages from 4000 to 10000 by sending 3 requests in batches of 2000.
- You cannot retrieve messages before 4000 because of the 3 hour lookback.
Sample Ranges
- Request single:
BeginSeqNo <7>
=EndSeqNo <16>
- Request range:
BeginSeqNo <7>
= first message in range;EndSeqNo <16>
= last message in range - Request range:
BeginSeqNo <7>
= first message in range;EndSeqNo <16>
= 2000th message from first message (999999
or0
)
Heartbeat (0)
Sent by both sides if no messages have been sent for (HeartBtInt x 0.75) seconds, as agreed upon during logon. May also be sent in response to a Test Request.
Tag | Name | Description |
---|---|---|
112 | TestReqID | Copied from the Test Request, if any |
Test Request (1)
May be sent at any time by either side.
Tag | Name | Description |
---|---|---|
112 | TestReqID | Free text |