Nostr Data App

In the old days there were only static web pages. Then someone invented web apps - a way to use the same HTTP protocol to serve dynamic content, to make API calls, to generate content on demand.

Nostr today is mostly static signed events. Users create events and send them to relays, for others to consume. Maybe it's time to make the same leap, and use Nostr protocol to serve dynamic content, to make API calls, to generate content on demand. Let's call it Nostr Data Apps (ndapps).

To learn more about ndapps and the rationale behind our approach, read the announcement on and a proposed NIP. Basically, the main idea of an ndapp is that requests are made using the same REQ verb that you use to request data from a relay, and replies are served as nostr events, signed by the API provider. This page is dedicated to Nostr.Band's ndapp, which is available at wss://

Nostr.Band is an aggregator, and many people wanted us to build an API. There is also a general need for what some call an aggregation layer for Nostr, a way to count, search or discover stuff, without forcing relays to become too smart. Our ndapp is an attempt to build an aggregation layer API on top of Nostr protocol, without bloating the base layer.

Right now our API can do two things: count events, and serve our trust rank metric. Here is how it works:

  • Connect to wss://, like you would to any relay.
  • Send REQ message with a set of filters. The basic template is this:
    ["REQ", "", {
  • So you're asking for an event by our pubkey 9b7a10bd934a2ad7a3eede6945452d707273e918de41f4a621532c70f53f747e (it's npub1ndapp0vnfg4d0glwme5523fdwpe886gcmeqlff3p2vk8paflw3lqem9665), of a special kind 33333 (it's a parameterized replaceable event, NIP-33), with a d-tag used to transfer an API call parameters as a query string. Notice that you could pass several d-tags and thus request several API calls with a single filter.
  • Here is an example to count the followers of jack:
    ["REQ", "", {
  • And this is how our ndapp could reply:
  • The content field contains the response, and the nostr event that serves as an envelope for this response brings two benefits to the table: a) the response can be forwarded to and stored on any relay just like any other parameterized replaceable event, and b) the response is signed and timestamped, so you can be sure which API provider produced it, and when.
  • These benefits could potentially reduce the chances that an API provider becomes a single point of failure: the events our API produces can be stored on the relay network, and the same filters can be used to request them from our ndapp or from any relay.

To count events, pass these params as a d-tag: m=count - method name, k - kind, p - pubkey, e - event id, tX - tag X, like tp for p-tag. At least one of p, e or tX must be specified. The result is a json w/ count field set to the number of events matching your parameters.

To get a trust rank of a pubkey, pass these params as a d-tag: m=trust - method name, p - pubkey. The result is a json w/ tr field set to a floating-point number in the range [0,1]. The bigger the number, the higher the trust rank of that pubkey. Trust rank only defines order, no other meaning is assigned to it, i.e. tr of 0.6 is _not_ 'two times more popular' than 0.3.

Please refer to the proposed NIP for recommendations on how to construct a proper d-tag query string for better interoperability with Nostr base layer.

Eventually, if ndapp idea finds support in the Nostr community, and if other aggregation providers decide to build their own ndapps, we could standardize a set of aggregation layer methods (like the count method above), and then clients would be able to switch between aggregators.

The API is free for now, until the nostr ecosystem figures out how to integrate LN payments at the protocol level to compensate relays.

To discuss this, contact on Nostr.