The baseline specification for this API is FIX 4.2. Below, we’ve noted the places in which the FIX API for Coinbase Prime extends (or clarifies) the FIX spec. For example, there are custom tags with a four-digit number range, as allowed by the standard, which are unique to Prime.

A standard header must be present at the start of every message in both directions. You should configure your sessions so that

  • SenderCompID = the Service Account ID associated with the API key as your SenderCompID
  • TargetCompID = the string COIN

This is typically accomplished via your FIX client’s configuration file.

A Service Account ID is a unique ID generated when you create an API Key. You can find it to the right of your API Key in Settings.

TagNameDescription
8BeginStringMust be FIX.4.2
49SenderCompIDThe Service Account ID (on messages from the client)
56TargetCompIDMust be COIN (on messages from the client)

Logon (A)

Sent by the client to initiate a session and by the server as an acknowledgement. Only one session can exist per connection — sending a Logon message within an established session results in an error.

The Logon message sent by the client must be signed for security. The prehash string has the following fields, each joined by the empty string:

{timestamp}A{seqNum}{apiKey}{targetComp}{passphrase}.

There is no trailing separator. The RawData field should be a base64 encoding of the HMAC signature.

To establish multiple FIX connections, you must generate a new API key for each one. All messages must have a SendingTime value within 5 seconds of server time in UTC or they are rejected.

Contact primeops@coinbase.com to create an API key for accessing multiple portfolios in a single fix connection.

Only one session can exist per connection (or API key) at a time.

TagNameDescription
96RawDataClient message signature (see below)
554PasswordClient API passphrase
9406DropCopyFlagIf set to Y, execution reports are generated for all user orders (defaults to Y), if set to N execution reports are only generated for orders from the FIX session
9407Access KeyClient API key

Python Example

def toAdmin(self, message, sessionID):
    if message.getHeader().getField(35) == "A":
        rawData = self.sign(message.getHeader().getField(52), message.getHeader().getField(35),
                            message.getHeader().getField(34), self.API_KEY, message.getHeader().getField(56),
                            self.PASSPHRASE)
        message.setField(fix.StringField(554, self.PASSPHRASE))
        message.setField(fix.StringField(96, rawData))
        message.setField(fix.StringField(9407, self.API_KEY))
        msg = message.toString().replace(__SOH__, "|")
        logfix.info("(Admin) S >> %s" % msg)
        return
    else:
        return

def sign(self, t, msg_type, seq_num, access_key, target_comp_id, passphrase):
    message = ''.join([t, msg_type, seq_num, access_key, target_comp_id, passphrase]).encode("utf-8")
    hmac_key = self.API_SECRET
    signature = hmac.new(hmac_key.encode('utf-8'), message, hashlib.sha256)
    sign_b64 = base64.b64encode(signature.digest()).decode()
    return sign_b64

JavaScript Example

// create a new Logon message
var logon = new Msgs.Logon();
logon.SendingTime = new Date();
logon.passphrase = "...";
var presign = [
  logon.SendingTime,
  logon.MsgType,
  session.outgoing_seq_num,
  apiKey,
  session.target_comp_id,
  passphrase,
].join("");
// 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");
}

New Order Single (D)

Sent by the client to enter an order. Not every tag is required for every order — it depends on the target strategy used. See the table below for more information.

TagNameDescriptionNotes
1AccountThe portfolio ID
11ClOrdIDA string selected by client to identify the order
38OrderQtyOrder size in base units (e.g., BTC). Either this or CashOrderQty must be supplied.
40OrdTypeOrder type. Must match TargetStrategySee OrdType Values table
44PxIndicates the price of the orderRequired for Limit and TWAP orders
54SideMust be 1 to buy or 2 to sell
55SymbolThe product to be traded (e.g., BTC-USD)
59TimeInForceA valid TimeInForce value; see the table below for a list.Must match TargetStrategy
99StopPxStop price for Stop Limit orderSpecifies the stop price at which the order activates. The order is activated if the last trade price on Coinbase Exchange crosses the stop price specified on the order.
126ExpireTimeRepresents the time and date of order expirationRequired for TWAP/VWAP orders and Limit GTD orders, unless ParticipationRate is specified (TWAP/VWAP only)
152CashOrderQtyOrder size in quote units (e.g., USD)Either this or OrderQty must be supplied.
168EffectiveTimeRepresents the start timeRequired for TWAP/VWAP orders
210MaxShowMaximum quantity within an order to be shown to other customers (Display Size)Only available for LIMIT orders
847TargetStrategyThe target strategy of the order to place; see the table below for a list.Requires ExpireTime and EffectiveTime for TWAP/VWAP orders. Must be SL and requires StopPx for Stop Limit orders.
849ParticipationRateRepresents the estimated percent of volume for TWAP/VWAP order types.Can be used instead of ExpireTime which it computes based on historical participation of volume rate.
8999IsRaiseExactY or N, is this a raise exact order. If Y, the asset amount sold is adjusted so the total received after fees equals the input size.Optional, defaults to N. Supported for SELL, Size In Quote orders only.

TargetStrategy Values

Requires ExpireTime and EffectiveTime for TWAP/VWAP orders. Must be “SL” and requires StopPx for Stop Limit orders.

ValueDescriptionOrdTypeTimeInForce
LLimit orderMust be 2 (Limit)
  • Must be 1 (GTC) or 3 (IOC) or 4 (FOK) or 6 (GTD)
  • Limit FOK orders are currently only routed to the Coinbase Exchange
  • 44 (price) must also be provided
MMarket orderMust be 1 (Market)Must be 3 (IOC)
TTWAP orderMust be 2 (Limit)Must be 6 (GTD); 44 (price) must also be provided
VVWAP orderMust be 2 (Limit)Must be 6 (GTD); 44 (price) must also be provided
SLStop Limit orderMust be 2 (Limit)Must be 1 (GTC) or 6 (GTD); 44 (price) and 99 (StopPx) must also be provided

OrdType Values

ValueDescription
1Market
2Limit
DPreviously Quoted

TimeInForce Values

Must match TargetStrategy

ValueDescription
1Good Till Cancel (GTC)
3Immediate or Cancel (IOC)
4Fill or Kill (FOK)
6Good Till Date (GTD)

RFQ

Quote Request (R)

A Quote Request (R) is the start of the RFQ process. Coinbase Prime sends a Quote Request to Liquidity Providers (LPs) on behalf of a customer looking to participate in an RFQ trade. LPs respond to a Quote Request (R) with a Quote (S).

TagNameDescription
131QuoteReqIDA string selected by client to identify the quote
1AccountThe portfolio id
54SideMust be 1 to buy and 2 to sell
55SymbolA product pair (e.g. BTC-USD)
38OrderQtyOrder size in base units (e.g. BTC)
40OrdTypeOrder type. Must be 2 (i.e. Limit)
44PriceIndicates the limit price of the quote
59TimeInForceTime in force for the order. Must be 4 (i.e. FOK)

Quote (S)

Quote (S) messages are submitted by Liquidity Providers (LP) in response to a Quote Request (R) in order to participate in the competitive RFQ auction.

TagNameDescription
117QuoteIDA Coinbase generated identifier for the quote
131QuoteReqIDA string selected by client to identify the quote
1AccountThe portfolio id
55SymbolThe product pair from Quote Request <R>
132BidPxQuoted price. Only present in case of Sells
133OfferPxQuoted price. Only present in case of Buys
134BidSizeQuoted size. Only present in case of Sells
135OfferSizeQuoted size. Only present in case of Buys
40OrdTypeOrder type. Must be 2 (i.e. Limit)
62ValidUntilTimeIndicates expiration time of the quote (always expressed in UTC)

Accept quote - New Order Single (D)

Sent by the client in order to accept a Quote (S). Must be accepted before expiration time indicated on Tag 62 of Quote (S). Refer to New Order Single (D) for standard fields of submitting an order.

TagNameDescription
[…][…]Standard fields for NewOrderSingle <D>
117QuoteIDThe quote id on tag 117 from Quote <S>
40OrdTypeShould be D (i.e. Previously Quoted)
847TargetStrategyShould be R (i.e. RFQ, coinbase’s custom value)
59TimeInForceShould be 4 (i.e. FOK)
44PriceThe price on tag 132/133 from Quote <S>

Quote Acknowledgment (b)

Sent by the server in case the Quote Requests (R) fails.

TagNameDescription
117QuoteIDA Coinbase generated identifier for the quote (optional)
131QuoteReqIDA string selected by client to identify the quote
1AccountThe portfolio id
55SymbolThe product pair from Quote Request <R>
297QuoteAckStatusWill be always 5 (i.e. Rejected)
300QuoteRejectReasonSee QuoteRejectReason table
58TextHuman-readable description of the error

QuoteRejectReason

Possible values for QuoteRejectReason (see Quote Acknowledgment (b)).

ValueDescription
1Unknown symbol
2Exchange closed
3Quote Request exceeds limit
6Duplicate Quote
8Invalid price
99Other

Order Cancel Request (F)

Sent by the client to cancel an order.

TagNameDescriptionNotes
1AccountThe portfolio ID
11ClOrdIdClOrdId identifying this cancel request
37OrderIDOrderID assigned by Coinbase (available in any of the Execution Report messages)
38OrderQtyAccepted order quantityYou must supply this tag or CashOrderQty (depending on whichever you originally submitted)
41OrigClOrdIDClOrdID from the New Order SingleYou must also supply an OrderID
54SideMust be 1 to buy or 2 to sell (depending on whichever you originally submitted)
55SymbolThe product from the original order (e.g., BTC-USD)
152CashOrderQtyOrder size in quote units (e.g., USD)You must supply this tag or OrderQty (depending on which you submitted)

Order Status Request (H)

Sent by the client to obtain information about pending and completed orders.

TagNameDescriptionNotes
11ClOrdIDClOrdID of the order to be sent back
37OrderIDOrderID of the order to be sent backRequired
54SideMust be 1 to buy or 2 to sell
55SymbolThe product to be traded (e.g., BTC-USD)

Python Example

def get_order_status(self, order_id, clord_id):
   '''Send Order Status Request Message (H)'''
   order_status_message = fix.Message()
   header = order_status_message.getHeader()
   header.setField(fix.MsgType(fix.MsgType_OrderStatusRequest))  # 35 = H
   order_status_message.setField(fix.OrderID(order_id))
   order_status_message.setField(fix.ClOrdID(clord_id))
   order_status_message.setField(fix.Side(fix.Side_BUY))
   order_status_message.setField(fix.Symbol("DOGE-USD"))
   fix.Session.sendToTarget(order_status_message, self.sessionID)

FIX Message Request: (35=H)

8=FIX.4.2|9=181|35=H|34=12|49=SENDERCOMPID|52=20220526-16:12:08.000|56=COIN|11=CLOrdID|37=OrderID|54=1|55=DOGE-USD|10=011|

FIX Message Response:

8=FIX.4.2|9=307|35=8|34=13|49=COIN|52=20220526-16:12:08.134|56=TARGETCOMPID|1=ACCOUNT|6=0|11=CLOrdID|14=0|17=ExecID|20=1|32=0.0|37=OrderID|38=100|39=4|54=1|55=DOGE-USD|150=4|151=100|10=255|

Execution Report (8)

Sent by the server when an order is accepted, rejected, filled, or canceled. Also sent when the user sends an OrderStatusRequest.

TagNameDescriptionNotes
1AccountThe portfolio ID of the associated orderEspecially pertinent if using an Org or Entity level API key
6AvgPxThe average price of the order
11ClOrdIDClOrdID of order to be sent back
14CumQtyTotal amount filled on this order
17ExecIDUnique ID for fill
30LastMktMarket of execution for last fill
31LastPxPrice of the fill if ExecType indicates a fill
32LastSharesAmount filled (if ExecType=1). Also called LastQty as of FIX 4.3
37OrderIDOrderID from the ExecutionReport
38OrderQtyOrderQty as acceptedYou must supply this tag or CashOrderQty (depending on whichever you originally submitted)
39OrdStatusOrder status as of the current message
40OrdTypeOrder Type1 = Market
2 = Limit
3 = Stop
4 = Stop Limit
44PriceLimit Price
50SenderSubIDID of the user that initiated the request (e.g. submitted the NOS)
54SideMust be 1 to buy or 2 to sell
55SymbolSymbol of the original order
58TextHuman-readable description of errorUserContext populated if not null
103OrdRejReasonOrder Reject ReasonSee OrdRejReason Values table
13CommTypeThe Commission typeAlways Absolute (3)
12CommissionThe Coinbase Commission incurred for this fill in quote currency
136NoMiscFeesNumber of repeating groups of miscellaneous fees if anyOnly included if there are fees other than the Coinbase fee
137MiscFeeAmtMiscellaneous fee value
138MiscFeeCurrCurrency of miscellaneous fee in quote currency symbol
139MiscFeeTypeIndicates type of miscellaneous feeSee MiscFeeType Values table
150ExecTypeDescribes the type of Execution Report (8)See ExecType Values table
151LeavesQtyAmount of order remaining
152CashOrderQtyOrder size in quote units (e.g., USD)You must supply this tag or OrderQty (depending on whichever you originally submitted)
168EffectiveTimeStartTime for a TWAP or VWAP
8006NetAvgPriceFilled quote size with commission divided by the filled base size

OrdRejReason Values

OrdRejReasonDescription
0Broker option
1Unknown symbol
2Exchange closed
3Order exceeds limit
4Too late to enter
5Unknown Order
6Duplicate Order
99Other

MiscFeeType Values

MiscFeeTypeDescription
1Financing fee
2Client commission
3CES commission
4Venue fee (Cost plus pricing only; Only appears for non-zero fees)

ExecType Values

ExecTypeDescription
0New Order
1Partial Fill
2Filled
3Done
4Canceled
6Pending Cancel
7Stopped
8Rejected
DRestated
APending New
IOrder Status

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.

TagNameDescription
11ClOrdIDThe same value provided by the original cancel request
37OrderIDThe same value provided by the original cancel request
39OrdStatusThe order status; see the table below for a list.
41OrigClOrdIDThe same value provided by the original cancel request
102CxlRejReasonThe reason the order was rejected
434CxlRejResponseToThe rejection response; see the table below for a list

OrdStatus Values

Valid ValuesDescription
0New
1Partially filled
2Filled
3Done for day
4Canceled
5Replaced
6Pending Cancel (e.g., result of Order Cancel Request <F>)
7Stopped
8Rejected
9Suspended
APending New
BCalculated
CExpired
DAccepted for bidding
EPending Replace (e.g., result of Order Cancel/Replace Request <G>)

CxlRejResponseTo Values

Valid ValuesDescription
1Order Cancel Request <F>
2Order Cancel/Replace Request <G>

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.

TagNameDescription
45RefSeqNumMsgSeqNum of the rejected incoming message
58TextHuman-readable description of the error (optional)
371RefTagIDTag number of the field which caused the reject (optional)
372RefMsgTypeMsgType of the rejected incoming message
373SessionRejectReasonCode to identify reason for the reject (for session-level rejections only)