Skip to content

Cosmos Hub

Cosmos Hub is served through three different protocols on three different transports — each a distinct API, not three views of one. Pick by what you need:

HTTPShttps://rpc.au.ro/cosmosLCD / REST (Cosmos SDK gRPC-gateway)
WebSocketwss://rpc.au.ro/ws/cosmos?apikey=<YOUR_API_KEY>CometBFT RPC
gRPCrpc.au.ro:8443 (full) / :443 (unary) — Cosmos SDK gRPC
Networkcosmoshub-4 (CometBFT 0.38.x)
Batch— (LCD is REST; there is no JSON-RPC envelope to batch)
CU1 CU per call

The HTTPS endpoint is REST, not CometBFT JSON-RPC

https://…/cosmos is the LCD REST API (:1317 upstream). It does not speak CometBFT JSON-RPC: a JSON-RPC POST is answered by the gRPC-gateway with {"code":12,"message":"Not Implemented"}, and CometBFT paths like /cosmos/status return HTTP 501.

The CometBFT surface (status, abci_query, subscribe, block, validators, broadcast_tx_*) is reachable over WebSocket only — see CometBFT RPC over WebSocket.

LCD / REST over HTTPS

Standard Cosmos SDK REST. Append the LCD path after the /cosmos segment; the key rides the apikey header.

bash
# node info — network, CometBFT version
curl https://rpc.au.ro/cosmos/cosmos/base/tendermint/v1beta1/node_info \
  -H "apikey: $YOUR_API_KEY"

# latest block
curl https://rpc.au.ro/cosmos/cosmos/base/tendermint/v1beta1/blocks/latest \
  -H "apikey: $YOUR_API_KEY"

# total supply of uatom
curl "https://rpc.au.ro/cosmos/cosmos/bank/v1beta1/supply/by_denom?denom=uatom" \
  -H "apikey: $YOUR_API_KEY"
js
const base = 'https://rpc.au.ro/cosmos'
const headers = { apikey: process.env.YOUR_API_KEY }

const info = await fetch(`${base}/cosmos/base/tendermint/v1beta1/node_info`, { headers })
console.log((await info.json()).default_node_info.network)   // cosmoshub-4

const bal = await fetch(`${base}/cosmos/bank/v1beta1/balances/cosmos1...`, { headers })
console.log((await bal.json()).balances)
python
import os, requests

base = "https://rpc.au.ro/cosmos"
h = {"apikey": os.environ["YOUR_API_KEY"]}

r = requests.get(f"{base}/cosmos/base/tendermint/v1beta1/blocks/latest", headers=h)
print(r.json()["block"]["header"]["height"])

r = requests.get(f"{base}/cosmos/bank/v1beta1/supply/by_denom",
                 params={"denom": "uatom"}, headers=h)
print(r.json()["amount"])
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	url := "https://rpc.au.ro/cosmos/cosmos/base/tendermint/v1beta1/syncing"
	req, _ := http.NewRequest("GET", url, nil)
	req.Header.Set("apikey", os.Getenv("YOUR_API_KEY"))
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	b, _ := io.ReadAll(res.Body)
	fmt.Println(string(b)) // {"syncing":false}
}

Live-verified LCD paths (all GET, all HTTP 200):

Path (after /cosmos)Returns
/cosmos/base/tendermint/v1beta1/node_infonetwork id, CometBFT version, moniker
/cosmos/base/tendermint/v1beta1/syncing{"syncing":false}
/cosmos/base/tendermint/v1beta1/blocks/latestlatest block (header + txs)
/cosmos/bank/v1beta1/supply/by_denom?denom=uatomtotal supply
/cosmos/bank/v1beta1/balances/{address}all balances for an account
/cosmos/staking/v1beta1/validators?pagination.limit=Nvalidator set (paginated)

The full surface is the standard Cosmos SDK LCD — every module the node enables (auth, bank, staking, gov, distribution, mint, slashing, ibc, …). A path the node doesn't implement returns HTTP 501{"code":12,"message":"Not Implemented"}.

CometBFT RPC over WebSocket

Everything the LCD can't do — consensus state, abci_query, event subscriptions, tx broadcast — lives on the CometBFT RPC, served over WebSocket. Frames are plain CometBFT JSON-RPC:

bash
npx wscat -H "apikey: $YOUR_API_KEY" -c wss://rpc.au.ro/ws/cosmos

> {"jsonrpc":"2.0","id":1,"method":"status","params":{}}
< {"jsonrpc":"2.0","id":1,"result":{"node_info":{"network":"cosmoshub-4",…},
                                    "sync_info":{"latest_block_height":"32042563",…}}}

In a browser the key must ride the query string (WebSocket() can't set headers): wss://rpc.au.ro/ws/cosmos?apikey=<YOUR_API_KEY>.

Live-verified over this transport: status, abci_query, subscribe. block, validators, health, net_info and broadcast_tx_sync are the same CometBFT surface.

Subscriptions

bash
> {"jsonrpc":"2.0","id":1,"method":"subscribe","params":{"query":"tm.event='NewBlock'"}}
< {"jsonrpc":"2.0","id":1,"result":{}}
< {"jsonrpc":"2.0","id":1,"result":{"query":"tm.event='NewBlock'","data":{…}}}

tm.event='Tx' streams transactions; attribute matches narrow it further (tm.event='Tx' AND transfer.recipient='cosmos1...'). Reconnect guidance: WebSockets.

Module state via abci_query

bash
> {"jsonrpc":"2.0","id":1,"method":"abci_query",
   "params":{"path":"/cosmos.bank.v1beta1.Query/TotalSupply","data":""}}

The value is base64 protobuf — decode with cosmjs-types or the module's generated stubs. If you'd rather not hand-decode protobuf, use the LCD (JSON) or gRPC (typed) instead.

CosmJS: use LCD or gRPC, not the Tendermint client

@cosmjs/tendermint-rpc's Tendermint37Client cannot reach this deployment on either transport:

  • over HTTPS — it hits the LCD and throws Got unexpected jsonrpc version: {"code":12,"message":"Not Implemented"}.
  • over WSSWebsocketClient appends its own /websocket suffix to whatever URL you pass, producing wss://…/ws/cosmos?apikey=<KEY>/websocket, which corrupts the key and fails the handshake.

For CosmJS-style typed module queries use gRPC with cosmjs-types

  • @grpc/grpc-js. For plain reads use the LCD with any HTTP client. Raw CometBFT calls work over WSS with any WebSocket library that sends the URL verbatim (ws, websocat, wscat).

gRPC

The node's Cosmos SDK gRPC (:9090 upstream), routed by proto package (cosmos.*, ibc.*, cometbft.*, tendermint.*), key as apikeymetadata. :8443 serves every call shape including reflection; :443 handles unary + server-streaming with explicit descriptors (a ready-made cosmos.protoset is published):

bash
# reflection — auth, bank, staking, gov, tx, … (20 services)
grpcurl -H "apikey: $YOUR_API_KEY" rpc.au.ro:8443 list

grpcurl -H "apikey: $YOUR_API_KEY" \
  -d '{"address":"cosmos1..."}' \
  rpc.au.ro:8443 cosmos.bank.v1beta1.Query/AllBalances

# or on :443 with the published descriptor set
grpcurl -protoset cosmos.protoset -H "apikey: $YOUR_API_KEY" \
  -d '{"denom":"uatom"}' \
  rpc.au.ro:443 cosmos.bank.v1beta1.Query/SupplyOf
# → {"amount":{"denom":"uatom","amount":"519540980277704"}}

Port semantics and descriptor details: gRPC.

Choosing a transport

You wantUse
Balances, validators, gov proposals — as JSONLCD over HTTPS
Typed module queries from an SDKgRPC (cosmjs-types, cosmpy, grpc-go)
Live blocks/txs, consensus state, abci_queryCometBFT over WSS
Broadcast a signed txgRPC cosmos.tx.v1beta1.Service/BroadcastTx, or CometBFT broadcast_tx_sync over WSS

Limitations

  • No CometBFT JSON-RPC over HTTPS — it is WSS-only here (see the warning above). This is the most common integration mistake on this chain.
  • No batching — the HTTPS endpoint is REST, so there is no JSON-RPC envelope to batch. A JSON array POSTed to /cosmos returns -32603 (unexpected backend response format), because the LCD never answers a JSON-RPC batch.
  • Historical state is limited by node pruning (recent heights only).