Getting Started
Cryptowatch offers a real-time WebSocket API for streaming normalized cryptocurrency market data. The API offers trades, order books, candlesticks, and more across 26 supported exchanges.
Once you have an account, you can generate an API key in the My Account > API Access section. You only need your public key for this API. Credits will then be deducted every hour on the hour based on your API usage, which can be monitored under the Transaction History section of the Credits & Billing menu.
Connect with your api key:
wss://stream.cryptowat.ch/connect?apikey=YOUR-API-KEY
Below are bare minimum examples using no outside packages except for a WebSocket library. These examples connect to the API and print a live feed of all BTC/USD trades. The resource for that is
instruments:9:trades
. You can read more about resources here.JavaScript
Go
Bash
const WebSocket = require('ws');
// Initialize a connection using your API key
// You can generate an API key here: https://cryptowat.ch/account/api-access
// Paste your API key here:
const API_KEY = 'XT11G0PE8VX02ZZ49RUR';
var conn = new WebSocket('wss://stream.cryptowat.ch/connect?apikey='+API_KEY);
conn.on('message', function (msg) {
const d = JSON.parse(msg.toString());
// The server will always send an AUTHENTICATED signal when you establish a valid connection
// At this point you can subscribe to resources
if (d.authenticationResult && d.authenticationResult.status === 'AUTHENTICATED') {
console.log("Streaming trades for 1 second...")
subscribe(conn, ['markets:*:trades']);
setTimeout(function() {
console.log("Unsubscribing...")
unsubscribe(conn, ['markets:*:trades'])
}, 1000)
}
// Market data comes in a marketUpdate
// In this case, we're expecting trades so we look for marketUpdate.tradesUpdate
if (d.marketUpdate && d.marketUpdate.tradesUpdate) {
for (let trade of d.marketUpdate.tradesUpdate.trades) {
console.log(`BTC/USD trade on market ${d.marketUpdate.market.marketId}: ${trade.timestampNano} ${trade.priceStr} ${trade.amountStr}`);
// That's it! It's that easy to tap in to the global crypto market pipeline.
}
}
});
// Helper method for subscribing to resources
function subscribe(conn, resources) {
conn.send(JSON.stringify({
subscribe: {
subscriptions: resources.map((resource) => { return { streamSubscription: { resource: resource } } })
}
}));
}
function unsubscribe(conn, resources) {
conn.send(JSON.stringify({
unsubscribe: {
subscriptions: resources.map((resource) => { return { streamSubscription: { resource: resource } } })
}
}))
}
package main
import (
"encoding/json"
"log"
"github.com/gorilla/websocket"
)
// Initialize a connection using your API key
// You can generate an API key here: https://cryptowat.ch/account/api-access
// Paste your API key here:
const (
APIKEY = "NZAP2FY3HMEC5T1BOYA3"
)
func main() {
c, _, err := websocket.DefaultDialer.Dial("wss://stream.cryptowat.ch/connect?apikey="+APIKEY, nil)
if err != nil {
panic(err)
}
defer c.Close()
// Read first message, which should be an authentication response
_, message, err := c.ReadMessage()
var authResult struct {
AuthenticationResult struct {
Status string `json:"status"`
} `json:"authenticationResult"`
}
err = json.Unmarshal(message, &authResult)
if err != nil {
panic(err)
}
// Send a JSON payload to subscribe to a list of resources
// Read more about resources here: https://docs.cryptowat.ch/websocket-api/data-subscriptions#resources
resources := []string{
"instruments:9:trades",
}
subMessage := struct {
Subscribe SubscribeRequest `json:"subscribe"`
}{}
// No map function in golang :-(
for _, resource := range resources {
subMessage.Subscribe.Subscriptions = append(subMessage.Subscribe.Subscriptions, Subscription{StreamSubscription: StreamSubscription{Resource: resource}})
}
msg, err := json.Marshal(subMessage)
err = c.WriteMessage(websocket.TextMessage, msg)
if err != nil {
panic(err)
}
// Process incoming BTC/USD trades
for {
_, message, err := c.ReadMessage()
if err != nil {
log.Fatal("Error reading from connection", err)
return
}
var update Update
err = json.Unmarshal(message, &update)
if err != nil {
panic(err)
}
for _, trade := range update.MarketUpdate.TradesUpdate.Trades {
log.Printf(
"BTC/USD trade on market %d: %s %s",
update.MarketUpdate.Market.MarketId,
trade.Price,
trade.Amount,
)
}
}
}
// Helper types for JSON serialization
type Subscription struct {
StreamSubscription `json:"streamSubscription"`
}
type StreamSubscription struct {
Resource string `json:"resource"`
}
type SubscribeRequest struct {
Subscriptions []Subscription `json:"subscriptions"`
}
type Update struct {
MarketUpdate struct {
Market struct {
MarketId int `json:"marketId,string"`
} `json:"market"`
TradesUpdate struct {
Trades []Trade `json:"trades"`
} `json:"tradesUpdate"`
} `json:"marketUpdate"`
}
type Trade struct {
Timestamp int `json:"timestamp,string"`
TimestampNano int `json:"timestampNano,string"`
Price string `json:"priceStr"`
Amount string `json:"amountStr"`
}
wscat --connect "wss://stream.cryptowat.ch/connect?apikey=XT11G0PE8VX02ZZ49RUR"
connected (press CTRL+C to quit)
< {"authenticationResult":{"status":"AUTHENTICATED"}}
> {"subscribe":{"subscriptions":[{"streamSubscription":{"resource":"pairs:9:trades"}}]}}
< {"marketUpdate":{"market":{"exchangeId":"2","currencyPairId":"9","marketId":"65"},"tradesUpdate":{"trades":[{"timestamp":"1569879489","timestampNano":"1569879489454000000","priceStr":"8200","amountStr":"0.0106711","price":8200,"amount":0.0106711}]}}}
< {"marketUpdate":{"market":{"exchangeId":"3","currencyPairId":"9","marketId":"74"},"tradesUpdate":{"trades":[{"externalId":"97996223","timestamp":"1569879480","timestampNano":"1569879480000000000","priceStr":"8206.51","amountStr":"0.00728105","price":8206.51,"amount":0.00728105}]}}}
We maintain three official SDKs which properly handle authentication and connection logic. They also provide useful abstractions for our messaging layer.
Language | Repository |
NodeJS | |
Golang | |
Python |
It's easy to get started writing your own client if you're not using a language supported by our official SDKs.
Since this is a read-only API we only require the public key and no secret-based HMAC signature. There are two ways you can provide your API key.
wss://stream.cryptowat.ch/connect?apikey=CXRJ2EJTOLGUF4RNY4CF
X-CW-API-Key: CXRJ2EJTOLGUF4RNY4CF
Our API uses Protocol Buffer messages, and supports both JSON and binary serialization. By default, messages are serialized using JSON because it's more convenient, but you can use binary instead to reduce your bandwidth usage. Our official SDKs use binary messages by default.
If you're writing your own client and want to use binary messages, supply a URL param when connecting:
wss://stream.cryptowat.ch/connect?format=binary
Binary vs. JSON
Consuming binary-serialized messages is more work, but uses about half of the bandwidth of JSON. If you find yourself hitting your bandwidth limit with JSON, you should consider switching to binary messages. It's more work to parse them, but it can be worth it!
Deprecation warning: Strings vs. Floats
All numeric values are represented as
string
values. There are also old, deprecated float
versions of these fields which should not be used.Example message with deprecated fields:
{
"externalId": "97996223",
"timestamp": "1569879480",
"timestampNano": "1569879480000000000",
"priceStr": "8206.51",
"amountStr": "0.00728105",
"price": 8206.51, // <- DEPRECATED: DO NOT USE
"amount": 0.00728105 // <- DEPRECATED: DO NOT USE
}
You must have Cryptowatch credits in your account to access the Web Socket API. The Web Socket API is paid for on-demand — you will only pay for the bandwidth you use.
Web Socket API pricing: 120 Credits per GB bandwidth
Last modified 3yr ago