Subscriptions
Every filter in a REQ must say what it is looking for. Filters that would stream the whole lane are rejected.
Accepted and rejected filters
| Filter | Result |
|---|---|
{"kinds":[1078], "#t":["lobby"]} | Accepted — any tag except #p |
{"kinds":[31081], "#d":["deck"]} | Accepted |
{"authors":["<pubkey>"]} | Accepted (up to 1024 authors) |
{"#p":["<your pubkey>"]} | Accepted after AUTH |
{"#p":["<someone else>"]} | Rejected, with or without AUTH |
{"kinds":[20000]}, {} | Rejected — no scope |
{"#t":[]} | Rejected — an empty tag list matches nothing |
A rejected subscription is answered with ["CLOSED", <id>, "restricted: …"]. If one filter in a REQ is rejected, the whole REQ is.
Why the rules exist
A filter without scope turns the relay into a firehose: it costs the most and tells a watcher everything happening in the lane. #p is limited to yourself because it reveals who is being contacted, when, and by whom.
Limits
- At most 16 open subscriptions per connection; the 17th is closed with
rate-limited:. - At most 1024 stored events are returned per filter; a larger
limitis reduced. - Stored events are returned newest first, followed by
EOSE; new matching events then arrive live.