Cryptowatch offers a Websocket API that supports real-time data streaming and trading.
The API consists of two separate back ends. Although they are separate services, both share the same connection and authentication logic, and are considered to be part of the same API. You can use one API key pair for both streaming and trading.
The streaming and trading services are hosted at
This API is currently in an invite-only beta testing phase. Please inquire here if you are interested in getting access to it.
All messages sent over the Websocket API are encoded using Protocol Buffers (
protobuf was chosen over
JSON mainly for its high efficiency, although there are many other benefits.
protobuf definitions are available at github.com/cryptowatch/proto.
Strings Vs Floats
All price, ID, and subscription data are represented as
string. This is to prevent loss of significant digits from using
float, as well as to provide a consistent and simple API.
protobuf message fields that use
float are deprecated in favor of a
string replacement. It is recommended you use the latest version of our client libraries which properly handle this deprecation.
The best way to connect to the API is with one of the official client libraries. They properly handle authentication, and provide a useful abstraction from our messaging layer. We have libraries written for
Writing Your Own Library
You can write a client library in any language using the documentation on this page, our protobuf definitions, and one of our official libraries as a reference implementation. If you write a client, send us a link and we'll share it here!
Unlike our REST API, each connection to the Websocket API must be authenticated with an API key and secret key. When establishing a connection, the client must send an APIAuthenticationMessage containing their public key, a nonce, and a token which is an
HMAC-SHA-512 created with the corresponding secret key.
An example implementation of generating the token can be found in ws-client-go.
To stream data, clients should connect to
wss://stream.cryptowat.ch and provide a list of data subscriptions.
The client will receive live updates for each subscription until the connection is closed.
Data subscriptions are strings formatted as a colon-separated scope, resource ID, and subject. For example, the subscription
exchanges:4:trades is a feed of all trades in the scope
exchanges where the resource ID is
4 (Kraken) and the subject is
trades. A client that subscribes to
exchanges:4:trades will receive all trade updates for the Kraken exchange.
A client can subscribe to a feed by supplying
subscriptions with the APIAuthenticationMessage, or dynamically using ClientSubscribeMessage. Similarly, it can unsubscribe using ClientUnsubscribeMessage.
It is possible to have up to
100 subscriptions per connection.
markets: a single market; e.g.
exchanges: all markets on an exchange; e.g.
pairs: all markets for a given pair; e.g.
assets: all markets for a given asset; e.g.
Use the REST API to obtain resource IDs for the various scopes:
- the Kraken BTC/EUR market is ID
- the Gemini exchange is ID
- the ETH/BTC pair is ID
- the XVG asset is ID
For some subjects, you can also use a wildcard
* scope the subscription to all markets or pairs.
markets:*: all markets in the system
pairs:*: all pairs in the system
Below we enumerate all possible subscription types, and the scopes they support.
Proto message type: TradesUpdate
|markets:68:trades||A feed of trades for a single market|
|markets:*:trades||A feed of trades for all markets|
|exchanges:4:trades||A feed of all trades on a given exchange|
|pairs:232:trades||A feed of all trades for a given pair|
|assets:60:trades||A feed of all trades for a given asset|
See our example code for consuming a trade feed.
24 Hour Market Summary
Periodic messages summarizing a given market over the last 24 hours, including last price, total volume, total quote volume, and price change.
Proto message type: SummaryUpdate
|markets:68:summary||Market summary updates for a single market|
|markets:*:summary||Market summary updates for all markets|
|markets:*:summary-low-volume||Market summary updates for all markets throttled to one every 2 minutes|
|exchanges:4:summary||Market summary updates for a given exchange|
|pairs:232:summary||Market summary updates for a given pair|
|assets:60:summary||Market summary updates for a given asset|
Also known as "candlestick" data, an OHLC subscription publishes updates to the latest candlestick for each time period. See also REST API OHLC data for reference.
Proto message type: IntervalsUpdate
|markets:68:ohlc||OHLC (candlestick) updates for a single market|
We publish real-time updates to the spread (best bid & ask) for the order book.
Proto message type: OrderBookSpreadUpdate
|markets:68:book:spread||Order book spread updates for a given market|
|markets:*:book:spread||Order book spread updates for all markets|
|exchanges:4:book:spread||Order book spread updates for a given exchange|
|pairs:232:book:spread||Order book spread updates for a given pair|
|assets:60:book:spread||Order book spread updates for a given asset|
The structure of our orderbook data is going through some changes. We will document full order book feeds soon! Let us know if you are interested in this data.
some example code showing how to connect, authenticate, subscribe to feeds, and consume the messages received:
kraken-trades- prints a real-time feed of all trades on a single exchange
print-quotes- prints real-time quotes for a given pair across all supported exchanges
To trade over websockets, clients should connect to
wss://broker.cryptowat.ch and provide a list of market IDs to trade on. Once authenticated, the client will receive live updates for
positions, and can place or cancel orders on any of the subscribed markets.
For the trade client, subscriptions are just a list of
string market IDs you intend to trade on and receive updates for. For example, to trade on both Kraken btc/usd and Bitfinex btc/usd, you would provide
subscriptions sent with the APIAuthenticationMessage. You can find the market IDs you need using our API: https://api.cryptowat.ch/markets.
Once authenticated, the trading back end will send a SessionStatusUpdate where
true for each of the subscribed markets, after which point it can place and cancel orders on the initialized markets.
The trading back end keeps track of the following trading properties for each of the subscribed markets, and sends updates as they occur:
positions. The official client libraries handle the following updates and keep an internal cache for convenience.
Orders (proto: OrdersUpdate)
OrdersUpdate is sent for each new order and any subsequent change to that order. For example, if an order is partially filled, a new
OrdersUpdate will be sent.
OrdersUpdate always contains all active orders for the given market.
Trades (proto: TradesUpdate)
Initially, the last 1000 trades for the subscribed market are sent to the client in a
TradesUpdate. Then any subsequent trade updates are sent in the same manner. The clients will maintain a cache of 1000 trades per market, removing the oldest as new updates occur.
Balances (proto: BalancesUpdate)
Balance updates contain a list of balances for each funding type (
margin) available on the exchange.
BalancesUpdate is sent every time one of your balances changes on an exchange where you are subscribed to one of its markets.
Positions (proto: PositionsUpdate)
Position updates contain a list of positions. A position consists of a list of orders and trades, average price, amount open and closed, and the order side.
PositionsUpdate is sent whenever your positions update on an exchange where you have a subscribed market.
Once a market is initialized, the client can place orders with PlaceOrderRequest, by supplying a PrivateOrder. Internally, order requests and updates are both represented by PrivateOrder, but the client libraries properly abstract this logic and make a distinction between the two.
After an order has been placed, a RequestResolutionUpdate will be sent to the client containing the resulting PrivateOrder, as well as an error code. If the error code is
0, the order was placed successfully.
Subsequent updates to your orders will be sent with OrdersUpdate.
The client can cancel orders by sending a CancelOrderRequest with the order ID to cancel. Similar to PlaceOrderRequest, a RequestResolutionUpdate will also be received to confirm the order was cancelled. To verify a cancelled order, it is sufficient to simply check if the
error code is
Sending a SyncRequest forces an update by polling the exchange on behalf of the user. This is done automatically by the client libraries upon initialization.
Sync should not normally be called explicitly; it is only useful in two scenarios:
- an order is placed or cancelled outside of this client
- there is something preventing our trading back end from actively polling for updates. This happens rarely, and for various reasons. For example, an exchange may rate limit one of our servers.