Nip 89


Recommended Application Handlers

draft optional author:pablof7z

This NIP describes kind:31989 and kind:31990: a way to discover applications that can handle unknown event-kinds.


Nostr's discoverability and transparent event interaction is one of its most interesting/novel mechanics. This NIP provides a simple way for clients to discover applications that handle events of a specific kind to ensure smooth cross-client and cross-kind interactions.

Parties involved

There are three actors to this workflow:

  • application that handles a specific event kind (note that an application doesn't necessarily need to be a distinct entity and it could just be the same pubkey as user A)
    • Publishes kind:31990, detailing how apps should redirect to it
  • user A, who recommends an app that handles a specific event kind
    • Publishes kind:31989
  • user B, who seeks a recommendation for an app that handles a specific event kind
    • Queries for kind:31989 and, based on results, queries for kind:31990


Recommendation event

    "kind": 31989,
    "pubkey": <recommender-user-pubkey>,
    "tags": [
        [ "d", <supported-event-kind> ],
        [ "a", "31990:app1-pubkey:<d-identifier>", "wss://relay1", "ios" ],
        [ "a", "31990:app2-pubkey:<d-identifier>", "wss://relay2", "web" ]

The d tag in kind:31989 is the supported event kind this event is recommending.

Multiple a tags can appear on the same kind:31989.

The second value of the tag SHOULD be a relay hint. The third value of the tag SHOULD be the platform where this recommendation might apply.

Handler information

    "kind": 31990,
    "pubkey": <pubkey>,
    "content": "<optional-kind:0-style-metadata>",
    "tags": [
        [ "d", <random-id> ],
        [ "k", <supported-event-kind> ],
        [ "web", "https://..../a/<bech32>", "nevent" ],
        [ "web", "https://..../p/<bech32>", "nprofile" ],
        [ "web", "https://..../e/<bech32>" ],
        [ "ios", ".../<bech32>" ]
  • content is an optional metadata-like stringified JSON object, as described in NIP-01. This content is useful when the pubkey creating the kind:31990 is not an application. If content is empty, the kind:0 of the pubkey should be used to display application information (e.g. name, picture, web, LUD16, etc.)

  • k tags' value is the event kind that is supported by this kind:31990. Using a k tag(s) (instead of having the kind onf the NIP-33 d tag) provides:

    • Multiple k tags can exist in the same event if the application supports more than one event kind and their handler URLs are the same.
    • The same pubkey can have multiple events with different apps that handle the same event kind.
  • bech32 in a URL MUST be replaced by clients with the NIP-19-encoded entity that should be loaded by the application.

Multiple tags might be registered by the app, following NIP-19 nomenclature as the second value of the array.

A tag without a second value in the array SHOULD be considered a generic handler for any NIP-19 entity that is not handled by a different tag.

User flow

A user A who uses a non-kind:1-centric nostr app could choose to announce/recommend a certain kind-handler application.

When user B sees an unknown event kind, e.g. in a social-media centric nostr client, the client would allow user B to interact with the unknown-kind event (e.g. tapping on it).

The client MIGHT query for the user's and the user's follows handler.


User A recommends a kind:31337-handler

User A might be a user of Zapstr, a kind:31337-centric client (tracks). Using Zapstr, user A publishes an event recommending Zapstr as a kind:31337-handler.

    "kind": 31989,
    "tags": [
        [ "d", "31337" ],
        [ "a", "31990:1743058db7078661b94aaf4286429d97ee5257d14a86d6bfa54cb0482b876fb0:abcd", <relay-url>, "web" ]

User B interacts with a kind:31337-handler

User B might see in their timeline an event referring to a kind:31337 event (e.g. a kind:1 tagging a kind:31337).

User B's client, not knowing how to handle a kind:31337 might display the event using its alt tag (as described in NIP-31). When the user clicks on the event, the application queries for a handler for this kind:

["REQ", <id>, '[{ "kinds": [31989], "#d": ["31337"], 'authors': [<user>, <users-contact-list>] }]']

User B, who follows User A, sees that kind:31989 event and fetches the a-tagged event for the app and handler information.

User B's client sees the application's kind:31990 which includes the information to redirect the user to the relevant URL with the desired entity replaced in the URL.

Alternative query bypassing kind:31989

Alternatively, users might choose to query directly for kind:31990 for an event kind. Clients SHOULD be careful doing this and use spam-prevention mechanisms to avoid directing users to malicious handlers.

["REQ", <id>, '[{ "kinds": [31990], "#k": [<desired-event-kind>], 'authors': [...] }]']