GuidesAPI Reference
DocumentationLog In

Websocket Overview

An overview of the Prime Websocket API

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

📘

Websocket Endpoint URL

wss://ws-feed.prime.coinbase.com

Real-time market data updates provide the fastest insight into order flow and trades. This means that 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.

The websocket feed is publicly available, but connections to it are rate-limited at 1 every 4 seconds per IP. Messages sent by the client on each connection are rate-limited to 100 every second per IP.

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 to
  • access_key: Public API key
  • api_key_id: Service account ID
  • timestamp: UNIX timestamp for your request (seconds since the epoch). Valid format: 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.

📘

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)
async def sign(channel, key, secret, account_id, portfolio_id, product_ids):
    message = channel + key + account_id + time.strftime("%Y-%m-%dT%H:%M:%SZ",s) + portfolio_id + product_ids
    print(message)
    signature = hmac.new(secret.encode('utf-8'), message.encode('utf-8'), digestmod=hashlib.sha256).digest()
    signature_b64 = base64.b64encode(signature).decode()
    print(signature_b64)
    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.