Skip to main content
Version: Next

HOPR Apps - Hello world

The following is a 5-minute guide to help you get familiar with the HOPR protocol and start developing apps on top of the HOPR network by learning how to send and read messages between two nodes.


1. Previous guides

Before getting started, we suggest you get familiar with the following concepts:

2. HOPR Cluster & exported variables

Make sure you have a HOPR cluster1 available for you to connect. Also, make sure to have the equivalent of at least 2 node endpoints (both HTTP and WS). Here are the default values for each of these endpoints.

Default values for apiToken and nodes endpoints







We'll assume your HOPR nodes were run using the instructions from "HOPR Cluster Development Setup". If you are looking to interact with your node via a terminal, we suggest you copy/paste the following commands every time you open a new terminal.

export commands for terminal

API Token

export apiToken=^^LOCAL-testing-123^^

Node 1


Node 2


All in one line

export apiToken=^^LOCAL-testing-123^^ HOPR_NODE_1_HTTP_URL= HOPR_NODE_1_WS_URL=ws:// HOPR_NODE_2_HTTP_URL= HOPR_NODE_2_WS_URL=ws://

Connect to your nodes

1. Connect to the WebSocket server of node 2

Using websocat or any other WebSocket client, connect to node 2 until you are able to receive and send messages to it.

Connecting to node 2 via websocat

.bin/websocat "$(echo "$HOPR_NODE_2_WS_URL" | sed "s/http/ws/")/?apiToken=$apiToken"

Connecting to node 2 via Piesocket WebSocket Tester


You can verify that you are connected by typing the command address and seeing an output similar to this:

{"type":"log","msg":"admin > address\n","ts":"2022-02-02T19:17:48.431Z"}
{"type":"log","msg":"HOPR Address: 16Uiu2HAmKhrwGWcvaZ3ic5dgy7oFawmnELJGBrySSsNo4bzGBxHW\nETH Address: 0x4cD95E1deF16D5913255Fe0af208EdDe2e04d720","ts":"2022-02-02T19:17:48.435Z"}

2. Verify REST API connectivity for node 1

Using curl or any other HTTP client, verify you can reach node 1's API

Obtaining the address for node 1 using curl

echo -n $apiToken | base64 | xargs -I {} curl -s -H "Authorization: Basic {}" $HOPR_NODE_1_HTTP_URL/api/v2/account/addresses | jq

Obtaining the address for node 1 using reqbin


Custom Header (default apiToken base64-encoded)

Basic Xl5MT0NBTC10ZXN0aW5nLTEyM15e

If you sent a successful request, the response will look something like this:

"nativeAddress": "0x3a54dDE3ee5ACfd43C902cbecC8ED0CBA10Ff326",
"hoprAddress": "16Uiu2HAmE9b3TSHeF25uJS1Ecf2Js3TutnaSnipdV9otEpxbRN8Q"

Send messages

The HOPR protocol allows you to send private messages between nodes by using other nodes as relayers. Each message “hops” (hence the name “HOPR”) until it reaches its final destination, its contents are known only to the final recipient. This is done automatically by HOPR nodes, which pick a random path to send your message to your recipient.

The path consists of at least 2 nodes that have channels opened between each other. For instance, to send a message to node 2 from node 1, one path a message could take is node 1 -> node 4 -> node 3 -> node 2. Since HOPR clusters have channels open between all nodes, all possible paths are available.

To try this out, let's use the REST API from node 1 and send a message to node 2, which we'll be able to see via our WebSocket client connection.

1. Obtaining the address (PeerId) of node 2

Using node 2, type the following command in your terminal with websocat running or the WebSocket client interface:


You should see a response like the following:

{"type":"log","msg":"admin > address\n","ts":"2022-02-02T19:17:48.431Z"}
{"type":"log","msg":"HOPR Address: 16Uiu2HAmKhrwGWcvaZ3ic5dgy7oFawmnELJGBrySSsNo4bzGBxHW\nETH Address: 0x4cD95E1deF16D5913255Fe0af208EdDe2e04d720","ts":"2022-02-02T19:17:48.435Z"}

As you can see, the address or PeerId of node 2 is 16Uiu2HAmKhrwGWcvaZ3ic5dgy7oFawmnELJGBrySSsNo4bzGBxHW. You can use that information to send a message from node 1. Make sure to keep your WebSocket client connected to see any messages received by node 2

2. Sending a message to node 2 from node 1:

To send a message from node 1 to node 2, we need to use node 1's REST API, specifically the /messages endpoint. Using curl or any other HTTP client, send the following request:

curl -X 'POST' \
"$HOPR_NODE_1_HTTP_URL/api/v2/messages/" \
-H 'accept: */*' \
-H "x-auth-token: $apiToken" \
-H 'Content-Type: application/json' \
-d "{
\"body\": \"Hello world from Node 1\",
\"recipient\": \"$HOPR_NODE_2_ADDR\"

In the terminal of node 2, you will see something similar to this:

{"type":"log","msg":"#### NODE RECEIVED MESSAGE [2022-02-03T21:48:13.845Z] ####","ts":"2022-02-03T21:48:13.845Z"}
{"type":"log","msg":"Message: Hello world","ts":"2022-02-03T21:48:13.846Z"}
{"type":"log","msg":"Latency: 668ms","ts":"2022-02-03T21:48:13.846Z"}
{"type":"message","msg":"Hello world","ts":"2022-02-03T21:48:13.847Z"}

Congratulations! You have sent your first message using the HOPR protocol!

3. Extra: Channels and tickets

You cannot send unlimited messages2. Each message requires tickets and headers with signatures for claiming balance updates in a HOPR token balanced payment channel. For every relayer you use (default 2), you need to "attach" HOPR tokens (0.01 per relay) which are used to pay for the relayer's work. Tickets are settled in a single global entry HoprChannels Ethereum contract.

The previous message worked because a cluster is configured by default to open a few channels and lock enough HOPR tokens to send messages to at least 2 relayers. When a path used to relay has depleted (empty) or closed channels, your message will not be forwarded. You can always see your open channels and their balance with the following command:


You can see your balance via the following command:



We ran all these commands via our WebSocket API, but you can also see them via our web UI interface called hopr-admin. To view the interface in your browser, simply paste your HOPR_NODE_1_WS_URL. You should be able to see an image like the following one:

HOPR Admin Image


If you need help completing this tutorial, you can watch our 15-minute walkthrough, which also includes the setup of the local HOPR cluster.


  1. As defined in "Running a local HOPR Cluster", a HOPR cluster is a set of HOPR nodes that are connected (i.e reachable) between each other and have opened funded channels between each other. This is also known as a Complete Graph, and although it is not required for successfully sending a message (i.e. you only need 1 path to a recipient when sending a message), it makes testing and developing HOPR apps easier.

  2. When a HOPR node uses the /api/v2/messages REST API endpoint to send a message, it will use a random path of at least 2 nodes as relayers. These messages cost $HOPR tokens because it pays each relayer accordingly to forward the packet. However, you can also send what is known as 0-hop messages, which bear no cost but provides no privacy, as the message is sent directly to the recipient. The REST API endpoint does not expose this, but you can send a 0-hop message via the HOPR admin UI or WebSocket client by typing send ,$peerId message.