Skip to main content

Prime WebSocket Overview

The websocket feed provides real-time market data updates for orders and trades.

Websocket Endpoint URL

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.

tip

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.

caution

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"
]
}
tip

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 to
  • access_key: Public API key
  • api_key_id: Service account ID
  • timestamp: 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 passphrase
  • signature: SHA256 HMAC signature using the prehash string and API secret key
  • portfolio_id / order_id: The portfolio or order ID (depending on which feed you're subscribing to. portfolio_id is required for orders 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.

info

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.

caution

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.

tip

To guarantee that messages are delivered and your order book is in sync, consider using the level2 channel.

Was this helpful?