This tutorial shows how to start using ZebraStream as a basic relay in a few minutes. We only use curl as a command line HTTP client to showcase the application, but any HTTP client or library can work.

Signup

Sign up to get an account and log in.

Generate a Management API Key

ZebraStream provides two different APIs to operate, one for managing streams and stream permissions, and one for transferring data via stream addresses. At first, you need to create a Management API key to access the Management API.

Once logged in, go to the internal dashboard.

Next, click 'Reset API key' to generate a key. It must be kept private.

Create Stream Access Permissions

With the Management API key, we can now issue permissions for stream addresses. We select an example stream address called /mystream and start with a simple pair of access tokens, one for writing to the stream and one for reading from the stream.

Using curl, we can access the ZebraStream Management API at https://api.zebrastream.io/v0/. We provide the stream path and an expiry time in UNIX time (in seconds). You can use an online tool like www.unixtimestamp.com to generate the timestamp, easily.

Create Writing and Reading Access Tokens

Replace the token after "Bearer" with your own token and set the correct expiry date.

curl --request POST --header "Authorization: Bearer mng_Eezai2soocaiSohkeja9uoh4" -d 'path=/mystream' -d 'recursive=false' -d 'access_mode=write' -d 'expires=1743372000' https://api.zebrastream.io/v0/accesstoken.create

If done correctly, the API returns a JSON object like this

{
"path" : "/9b09a7ce-024d-4836-ab95-90b776dfd439/mystream",
"token" : "Chohph3meephith7caecoohi",
"token_id" : "key_eengeu0xeiphaiXieph7ohyue5ih"
}

You see that the returned stream address is prefixed by the account's private namespace. The full address is needed for data transfer. Save this information in a secret place.

We do the same for the reading token, just by replacing the mode "write" with "read".

curl --request POST --header "Authorization: Bearer mng_Eezai2soocaiSohkeja9uoh4" -d 'path=/mystream' -d 'recursive=false' -d 'access_mode=read' -d 'expires=1743372000' https://api.zebrastream.io/v0/accesstoken.create

We get a second token in return that refers to the same stream path.

{
"path" : "/9b09a7ce-024d-4836-ab95-90b776dfd439/mystream",
"token" : "kie0EesheiV3Aewoh4utiYah",
"token_id" : "key_Ahg5pohighoothool7eidaaphauc"
}

In a real world application, we could hand over those access tokens to the parties that exchange data via the stream address.

List Access Tokens

Double check by listing the created access tokens

curl --request GET --header "Authorization: Bearer mng_Eezai2soocaiSohkeja9uoh4" https://api.zebrastream.io/v0/accesstoken.list

which should return the following JSON list

[
{
"access_mode" : "write",
"expires" : 1743372000,
"id" : "key_eengeu0xeiphaiXieph7ohyue5ih",
"path" : "/9b09a7ce-024d-4836-ab95-90b776dfd439/mystream",
"recursive" : false
},
{
"access_mode" : "read",
"expires" : 1743372000,
"id" : "key_Ahg5pohighoothool7eidaaphauc",
"path" : "/9b09a7ce-024d-4836-ab95-90b776dfd439/mystream"",
"recursive" : false
}
]

Example Workflow

Since producing and consuming data is done via HTTP requests, we can also use curl here. Before transitioning to streams, it's typically easiest to start with a simple file transfer. We assume the sender has a local file called data.json for the receiver.

Data Producer

The sender issues a one-line data producer curl command, providing the reading token in the authorization header.

curl --request PUT --upload-file data.json --no-buffer --http1.1 --expect100-timeout 180 --header 'Authorization: Bearer Chohph3meephith7caecoohi' 'https://data.zebrastream.io/v0/9b09a7ce-024d-4836-ab95-90b776dfd439/mystream'

Basically, this command tells curl to

  • output relay status messages instantly on the command line
  • transfer the data via HTTP/1.1 protocol
  • wait for the server when it is ready to receive the payload data for 3 minutes
  •  
  • authorize with the generated writer access token

Most of these settings are optional, but it's best practice to state them explicitly.

Data Consumer

While the producer is waiting, the the receiver can connect similarly with the reading token.

curl --request GET --header 'Authorization: Bearer kie0EesheiV3Aewoh4utiYah' --output data-received.json 'https://data.zebrastream.io/v0/9b09a7ce-024d-4836-ab95-90b776dfd439/mystream'

As you can see, the consumer command is much simpler, in fact, we could just do

curl 'https://data.zebrastream.io/v0/9b09a7ce-024d-4836-ab95-90b776dfd439/mystream?accesstoken=kie0EesheiV3Aewoh4utiYah'

The latter is the form for systems that don't allow you to specify custom headers. You could also just paste that URL into a web browser and download the file there.

Wrap-up

This walkthrough shows how easy it is to implement a data exchange channel using ZebraStream and HTTP. Just exchange the stream address and access token with the other side. Think of a stream path as the analog of a filesystem path, where the stream object is the filename at the end. If you are familiar with UNIX named pipes, you will feel quite comfortable. Stream access can also be granted in recursive mode (like a folder) by setting recursive=true and making sure, that the path ends with a dash (/). You can create stream folders to isolate different applications in namespaces and tune access permissions for producers and consumers.

A Note About Timing

The mechanism here only uses the core relay functionality. This means, that it relies on correct synchronization of sender and receiver when connecting. If one side is waiting for the other to connect, and it doesn't show up, the relay will terminate the connection after 3 minutes. This is sufficient for situations, in which the transfer is triggered by an observable event, like wall clock time. For more complex scenarios, make use of our ZebraStream Connect API for push and pull workflows.

Further Reading