Prime WebSocket Overview
The websocket feed provides real-time market data updates for orders and trades.
wss://ws-feed.prime.coinbase.com
Rate Limits
Real-time market data updates provide the fastest insight into order flow and trades. You are responsible for reading the message stream and using the message relevant for your needs—this can include building real-time order books or tracking real-time trades.
Specs
The WebSocket feed is publicly available. Connection requests to it are rate-limited at 750 every 10 seconds per IP.
Errors
An error message displays when the client is actively disconnected for any of these reasons:
- The client has too many backed up messages (
ErrSlowConsume
). - The client is sending too many messages (
ErrSlowRead
). - The message size is too large (
Message too big
) - There are intermittent network issues.
Protocol
The websocket feed uses a bidirectional protocol that encodes all messages as JSON objects. All messages have a type
attribute that can be used to handle the message appropriately.
New message types can be added at any time. Clients are expected to ignore messages they do not support.
Error messages:
Most failure cases trigger an error
message—specifically, a message with the type
"error"
. This can be helpful when implementing a client or debugging issues.
{
"type": "error",
"message": "error message",
/* ... */
}
Subscribing
To begin receiving feed messages, you must send a signed subscribe
message to the server indicating which channels and products to receive. This message is mandatory—you are disconnected if no subscribe
has been received within 5 seconds.
Every subscribe
request must be signed. See Signing Messages below.
// Request -> Subscribe to heartbeat channel
{
"type": "subscribe",
"channel": "heartbeat",
"access_key": "ACCESS_KEY",
"api_key_id": "SVC_ACCOUNTID",
"timestamp": "TIMESTAMP",
"passphrase": "PASSPHRASE",
"signature": "signature",
"portfolio_id": "PORTFOLIO_ID",
"product_ids": [
"BTC-USD"
]
}
// Response -> heartbeat channel
{
"channel": "subscriptions",
"timestamp": "2022-01-25T20:52:59.353824785Z",
"sequence_num": 0,
"events": [
{
"subscriptions": {
"heartbeat": [
"heartbeat"
]
}
}
]
}
// Message 1:
{
"channel": "heartbeat",
"timestamp": "2022-01-25T20:53:01.66270911Z",
"sequence_num": 1,
"events": [
{
"current_time": "2022-01-25 20:53:01.662698745 +0000 UTC m=+3551940.494451923",
"heartbeat_counter": 118398
}
]
}
Once a subscribe
message is received the server responds with a subscriptions
message that lists all channels you are subscribed to. Subsequent subscribe messages add to the list of subscriptions.
Unsubscribing
To unsubscribe from channel/product pairs, send an unsubscribe
message. The structure is equivalent to subscribe
messages.
// Request -> unsubscribe from heartbeat channel
{
"type": "unsubscribe",
"channel": "heartbeat",
"access_key": "ACCESS_KEY",
"api_key_id": "SVC_ACCOUNTID",
"timestamp": "TIMESTAMP",
"passphrase": "PASSPHRASE",
"signature": "signature",
"portfolio_id": "",
"product_ids": [
"BTC-USD"
]
}
You can also unsubscribe from a channel entirely by providing no product IDs.
// Request
{
"type": "unsubscribe",
"channels": [
"heartbeat"
]
}
As a response to an unsubscribe
message you will receive a subscriptions
message:
{
"channel": "subscriptions",
"timestamp": "2022-02-19T19:59:56.701617197Z",
"sequence_num": 0,
"events": [
{
"subscriptions": {}
}
]
}
Signing Messages
You must authenticate yourself when subscribing to any of the Prime Websocket channels.
Construct a payload schema for all channels with the following list of properties and valid values:
type
: "subscribe" or "unsubscribe"channel
: Websocket channel to subscribe toaccess_key
: Public API keyapi_key_id
: Service account IDtimestamp
: ISO 8601 for requests (seconds since the epoch); or Epoch for creating signatures. Valid ISO 8601 format:%Y-%M-%DT%H:%M:%SZ
, for example,2022-02-19T20:05:22Z
.passphrase
: Your API passphrasesignature
: SHA256 HMAC signature using the prehash string and API secret keyportfolio_id
/order_id
: The portfolio or order ID (depending on which feed you're subscribing to.portfolio_id
is required fororders
channel.)product_ids
: Comma-separated list of products to subscribe to (["BTC-USD"]
)
The signature
field is generated by creating a SHA256 HMAC by signing your API Secret key with a prehash string. The final prehash payload is generated by creating a concatenated string of channelName + accessKey + svcAccountId + timestamp + portfolioId + products
(where +
represents string concatenation).
Apply a SHA256 HMAC using your secret key on this prehash payload, and then base64-encode it as your final payload within your request. Pass the output of this SHA256 HMAC to the signature
field in each request message. See the examples of generating this signature
below.
For requests that subscribe to multiple products (e.g., product_ids: ["BTC-USD", "ETH-USD"]
), the product_ids
string in the prehash must be formatted as follows: BTC-USDETH-USD
.
timestamp = Time.now.to_i
string = "#{channelName}#{accessKey}#{svcAcctId}#{timestamp}#{portfolioId}";
# create a SHA256 hmac with the secret key
hash = OpenSSL::HMAC.digest('sha256', @secret, string)
# pass this body with your requests
message = Base64.strict_encode64(hash)
def sign(channel, key, secret, account_id, product_ids):
message = channel + key + account_id + timestamp + "".join(product_ids)
signature = hmac.new(secret.encode('utf-8'), message.encode('utf-8'), digestmod=hashlib.sha256).digest()
signature_b64 = base64.b64encode(signature).decode()
return signature_b64
Sequence Numbers
Most feed messages contain a sequence number. Sequence numbers are increasing integer values for each product, with each new message being exactly one sequence number greater than the one before it.
Sequence numbers that are greater than one integer value from the previous number indicate that a message has been dropped. Sequence numbers that are less than the previous number can be ignored or represent a message that has arrived out of order.
In either situation you may need to perform logic to make sure your system is in the correct state.
Even though a websocket connection is over TCP, the websocket servers receive market data in a manner that can result in dropped messages. Your feed consumer should be designed to handle sequence gaps and out of order messages, or should use channels that guarantee delivery of messages.
To guarantee that messages are delivered and your order book is in sync, consider using the level2 channel.