---
title: "Subscribe for events via WebSocket."
method: GET
path: "/subscribe"
tags: ["Websocket"]
---

# Subscribe for events via WebSocket.

`GET /subscribe`

To tell which events you want, you need to provide a query. query is a
string, which has a form: "condition AND condition ..." (no OR at the
moment). condition has a form: "key operation operand". key is a string with
a restricted set of possible symbols ( \t\n\r\\()"'=>< are not allowed).
operation can be "=", "<", "<=", ">", ">=", "CONTAINS" AND "EXISTS". operand
can be a string (escaped with single quotes), number, date or time.

Examples:
      tm.event = 'NewBlock'               # new blocks
      tm.event = 'CompleteProposal'       # node got a complete proposal
      tm.event = 'Tx' AND tx.hash = 'XYZ' # single transaction
      tm.event = 'Tx' AND tx.height = 5   # all txs of the fifth block
      tx.height = 5                       # all txs of the fifth block

Ostracon provides a few predefined keys: tm.event, tx.hash and tx.height.
Note for transactions, you can define additional keys by providing events with
DeliverTx response.

import (
    abci "github.com/Finschia/ostracon/abci/types"
    "github.com/Finschia/ostracon/libs/pubsub/query"
)

abci.ResponseDeliverTx{
  Events: []abci.Event{
      {
          Type: "rewards.withdraw",
          Attributes: abci.EventAttribute{
              {Key: []byte("address"), Value: []byte("AddrA"), Index: true},
              {Key: []byte("source"), Value: []byte("SrcX"), Index: true},
              {Key: []byte("amount"), Value: []byte("..."), Index: true},
              {Key: []byte("balance"), Value: []byte("..."), Index: true},
          },
      },
      {
          Type: "rewards.withdraw",
          Attributes: abci.EventAttribute{
              {Key: []byte("address"), Value: []byte("AddrB"), Index: true},
              {Key: []byte("source"), Value: []byte("SrcY"), Index: true},
              {Key: []byte("amount"), Value: []byte("..."), Index: true},
              {Key: []byte("balance"), Value: []byte("..."), Index: true},
          },
      },
      {
          Type: "transfer",
          Attributes: abci.EventAttribute{
              {Key: []byte("sender"), Value: []byte("AddrC"), Index: true},
              {Key: []byte("recipient"), Value: []byte("AddrD"), Index: true},
              {Key: []byte("amount"), Value: []byte("..."), Index: true},
          },
      },
  },
}

All events are indexed by a composite key of the form {eventType}.{evenAttrKey}.
In the above examples, the following keys would be indexed:
   - rewards.withdraw.address
   - rewards.withdraw.source
   - rewards.withdraw.amount
   - rewards.withdraw.balance
   - transfer.sender
   - transfer.recipient
   - transfer.amount

Multiple event types with duplicate keys are allowed and are meant to
categorize unique and distinct events. In the above example, all events
indexed under the key `rewards.withdraw.address` will have the following
values stored and queryable:

   - AddrA
   - AddrB

To create a query for txs where address AddrA withdrew rewards:
query.MustParse("tm.event = 'Tx' AND rewards.withdraw.address = 'AddrA'")

To create a query for txs where address AddrA withdrew rewards from source Y:
query.MustParse("tm.event = 'Tx' AND rewards.withdraw.address = 'AddrA' AND rewards.withdraw.source = 'Y'")

To create a query for txs where AddrA transferred funds:
query.MustParse("tm.event = 'Tx' AND transfer.sender = 'AddrA'")

The following queries would return no results:
query.MustParse("tm.event = 'Tx' AND transfer.sender = 'AddrZ'")
query.MustParse("tm.event = 'Tx' AND rewards.withdraw.address = 'AddrZ'")
query.MustParse("tm.event = 'Tx' AND rewards.withdraw.source = 'W'")

See list of all possible events here
https://godoc.org/github.com/Finschia/ostracon/types#pkg-constants

For complete query syntax, check out
https://godoc.org/github.com/Finschia/ostracon/libs/pubsub/query.

```go
import rpchttp "github.com/Finschia/ostracon/rpc/client/http"
import "github.com/Finschia/ostracon/types"

client := rpchttp.New("tcp:0.0.0.0:26657", "/websocket")
err := client.Start()
if err != nil {
  handle error
}
defer client.Stop()
ctx, cancel := context.WithTimeout(context.Background(), 1 * time.Second)
defer cancel()
query := "tm.event = 'Tx' AND tx.height = 3"
txs, err := client.Subscribe(ctx, "test-client", query)
if err != nil {
  handle error
}

go func() {
 for e := range txs {
   fmt.Println("got ", e.Data.(types.EventDataTx))
   }
}()
```

NOTE: if you're not reading events fast enough, Ostracon might
terminate the subscription.

## Query parameters

- `query` string, required

## Response `200`

empty answer

- EmptyResponse — Empty Response
  - `id` integer
  - `jsonrpc` string
  - `result` object

## Other responses

- `500` — empty error

---

[API](https://skmtc.net/finschia/apis/ostracon-rpc.md) · [All operations](https://skmtc.net/finschia/apis/ostracon-rpc/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/finschia/ostracon-rpc/revisions/f8b90bf02ef4/schema)
