1 Overview
Some web-of-trust calculations need a large volume of events and much computing power. A phone client cannot crawl the whole network to rank every pubkey. This NIP moves that work to a service provider that the user declares as trusted.
The provider runs its algorithm over the network. It then publishes the results as signed Trusted Assertion events (TAs). An assertion is a small addressable event: "this pubkey has rank 89" or "this note received 12 zaps". Clients fetch these events and show the numbers.
The user stays in control through a kind 10040 list. It names the provider key and relay for each result type the user wants. Two providers can compute the same metric in different ways. The user picks the provider whose view matches their own.
Think of a provider as a strategy guide hotline. You do not solve the whole map yourself. You call the hotline you trust, and it tells you the score. Different hotlines give different answers - that is the point.
2 Assertion Events
A Trusted Assertion is always an addressable event as defined in NIP-01. The d tag holds the subject of the assertion. The NIP recognizes four subject types. Each subject type maps to one event kind:
| Subject | Event kind | d tag value |
|---|---|---|
| User | 30382 | <pubkey> |
| Event | 30383 | <event_id> |
| Addressable event | 30384 | <event_address> |
| NIP-73 identifier | 30385 | <i-tag> |
Calculation results live in pre-defined tags. Providers and clients agree on the syntax and semantics of each tag. This example ranks a pubkey with a web-of-trust score of 89:
{
"kind": 30382,
"pubkey": <service pubkey>,
"tags": [
["d", "e88a691e98d9987c964521dff60025f6…27850411"], // target user's pubkey
["rank", "89"]
],
"content": "",
// created_at, id, sig …
}
A provider must use a different service key for each distinct algorithm. When an algorithm is personalized to one user's point of view or settings, the provider must use one key per user. One key, one algorithm, one viewpoint.
3 Kind 30382 — Users as Subject
Kind 30382 rates a person. The d tag holds the target pubkey. These result types are declared:
| Result type | Tag name | Tag value format |
|---|---|---|
| Follower count | followers | int |
| User rank | rank | int, normalized 0-100 |
| First post time | first_created_at | unix timestamp |
| Post count | post_cnt | int |
| Reply count | reply_cnt | int |
| Reactions count | reactions_cnt | int |
| Zap amount received | zap_amt_recd | int, sats |
| Zap amount sent | zap_amt_sent | int, sats |
| Zap number received | zap_cnt_recd | int |
| Zap number sent | zap_cnt_sent | int |
| Avg zap amount/day received | zap_avg_amt_day_recd | int, sats |
| Avg zap amount/day sent | zap_avg_amt_day_sent | int, sats |
| Reports received | reports_cnt_recd | int |
| Reports sent | reports_cnt_sent | int |
| Common topics | t | string |
| Generally active start | active_hours_start | int, 0-24, UTC |
| Generally active end | active_hours_end | int, 0-24, UTC |
Each provider can compute these values its own way. One provider may exclude the user's muted pubkeys from the follower count. Another provider may keep them. The user picks the provider whose method matches their view. Zap metrics come from NIP-57 receipts. Report metrics come from NIP-56 events.
4 Kind 30383 — Events as Subject
Kind 30383 rates one regular event. The d tag holds the event id. Providers can attach these tags:
| Result type | Tag name | Tag value format |
|---|---|---|
| Event rank | rank | int, normalized 0-100 |
| Event comment count | comment_cnt | int |
| Event quote count | quote_cnt | int |
| Event repost count | repost_cnt | int |
| Event reaction count | reaction_cnt | int |
| Event zap count | zap_cnt | int |
| Event zap amount | zap_amount | int, sats |
5 Kind 30384 — Addressables as Subject
Kind 30384 rates all versions of one addressable event together. The d tag holds the event address (kind:pubkey:d-value). The tag set mirrors kind 30383:
| Result type | Tag name | Tag value format |
|---|---|---|
| Address rank | rank | int, normalized 0-100 |
| Address comment count | comment_cnt | int |
| Address quote count | quote_cnt | int |
| Address repost count | repost_cnt | int |
| Address reaction count | reaction_cnt | int |
| Address zap count | zap_cnt | int |
| Address zap amount | zap_amount | int, sats |
6 Kind 30385 — External Identifiers as Subject
Kind 30385 rates things outside Nostr: books, locations, movies, websites, and hashtags. The d tag holds a NIP-73 identifier (an i tag value). Add the matching NIP-73 k tags to the event as well.
| Result type | Tag name | Tag value format |
|---|---|---|
| Rank | rank | int, normalized 0-100 |
| Comment count | comment_cnt | int |
| Reaction count | reaction_cnt | int |
7 Declaring Trusted Providers — Kind 10040
A kind 10040 event lists the user's preferred source for each result. Each tag names a kind:tag pair, then the publisher's pubkey, then the relay where the assertion events live. Providers may use multiple keys and relays, including a key per user for personalized algorithms.
Users can share this list publicly as plain tags. Or they can keep it private: JSON-stringify the tag list, encrypt it with NIP-44, and store it in the content field.
{
"kind": 10040,
"tags": [
[<kind:tag>, <service key>, <relay hint>],
// examples
["30382:rank", "4fd5e210530e4f6b…fe5f12fe", "wss://nip85.nostr.band"],
["30382:rank", "3d842afecd5e293f…2d44a42d", "wss://nostr.wine"],
["30382:zap_amt_sent", "4fd5e210530e4f6b…fe5f12fe", "wss://nip85.nostr.band"]
],
"content": nip44Encrypt(JSON.stringify([
[<kind:tag>, <service key>, <relay hint>],
// examples
["30383:rank", "4fd5e210530e4f6b…fe5f12fe", "wss://nip85.nostr.band"],
["30384:rank", "4fd5e210530e4f6b…fe5f12fe", "wss://nip85.nostr.band"]
])),
// other fields …
}
When a provider offers several algorithms, or several points of view of one algorithm, the key in each tag should point to the key created for that specific algorithm or point of view.
The source example is loose in two ways. First, its nip44Encrypt( call is never closed before the trailing comment. Second, it shows public tags and an encrypted content list in the same event, while the prose frames public and private as a user choice. The spec does not say how a client merges the two lists if both are present.
8 Operational Rules
- Providers should update Trusted Assertions as fast as new information arrives. But they should re-publish an event only when its contents actually change. This avoids re-downloading the same information.
- Providers may limit access to results by publishing to paid relays.
- In a TA, a
p,e, oratag with the same value as thedtag may be added. It carries a relay hint to the home relay of that user or event.
9 Provider Discoverability
A provider should sign a kind 0 metadata event (NIP-01) for each service key. It explains who controls the key and what the current version of the algorithm is about:
{
"kind": 0,
"pubkey": <service pubkey>,
"tags": [],
"content": "{
\"name\": \"Vitor's Brainstormer\",
\"about\": \"A Web of Trust algorithm from Vitor's point of view that
considers Follows and Mutes, but no reports, and gives extra
score points for anyone around Boston\",
\"picture\": \"https://brainstorm.com/logo.png\",
\"website\": \"https://brainstorm.com\"
}",
// other fields …
}
The kind 0 example in the source uses = between keys and values inside content (for example \"name\" = \"…\"). That is not valid JSON. The block above shows the intended shape with :. Treat the source example as illustrative only.
A client that wants to offer a list of providers to its users should:
- Download the kind 10040 events of the user's follow list.
- Connect to each listed relay. Download the kind 0 of each service key.
- Parse the kind 0 and collect the
websiteproperty. - Load the OpenGraph tags of that website. Display them as clickable items.
10 Worked Example
Alice wants to see trust ranks in her client. She declares a provider, and her client fetches an assertion about Bob. Orange lines go to the relay. Blue lines come from the relay.
-- Alice publishes her provider list -- → ["EVENT", {"kind":10040,"pubkey":"a11ce9f2…","created_at":1749821000, "tags":[["30382:rank","4fd5e210…","wss://nip85.nostr.band"]], "content":"","id":"c3f1a0d2…","sig":"90ab41ce…"}] ← ["OK", "c3f1a0d2…", true, ""] -- Her client asks the hinted relay for Bob's assertion -- → ["REQ", "wot", {"kinds":[30382], "authors":["4fd5e210…"], "#d":["b0b7c4e1a95d20fa88431fe1dd2ae9b4…13cf02aa"]}] ← ["EVENT", "wot", {"kind":30382,"pubkey":"4fd5e210…","created_at":1749820500, "tags":[["d","b0b7c4e1a95d20fa88431fe1dd2ae9b4…13cf02aa"], ["rank","89"],["followers","1204"],["zap_cnt_recd","312"], ["p","b0b7c4e1a95d20fa88431fe1dd2ae9b4…13cf02aa","wss://bob.example"]], "content":"","id":"7e2d90bc…","sig":"d4e88a01…"}] ← ["EOSE", "wot"] -- Client shows: Bob - rank 89 - 1204 followers (per this provider) --
11 Version History
NIP-85 is young. Vitor Pamplona proposed it after a long-running pull request discussion. Notable changes, newest first:
- 20262026-06Repo-wide cleanup by fiatjaf changed the code fence language of the examples.
- 20262026-05Clarifications pass: tightened wording on subjects, keys, and tag semantics.
- 20262026-02Added Appendix 1: service provider discoverability through kind 0 metadata on each service key.
- 20262026-01Typo fixes shortly after merge.
- Origin2026-01-22Vitor Pamplona merged the initial Trusted Assertions spec (PR #1534): kinds 30382-30385, kind 10040, and the result-type tables.
Original Proposal - Credits
| Author | Vitor Pamplona |
| First commit | 2026-01-22 — “Trusted Assertions (#1534)” - PR #1534 |
| Status | draftoptional |
| Source | 85.md on GitHub - full change history |
12 See Also
- NIP-01 — addressable events, the
dtag, and kind 0 metadata that this NIP builds on. - NIP-73 — external content identifiers; the subjects of kind 30385 assertions.
- NIP-44 — the encryption used to keep a kind 10040 provider list private.
- NIP-57 — zaps; the source of all zap amount and zap count metrics.
- NIP-56 — reporting; the source of the report count metrics.
- NIP-25 — reactions; the source of the reaction count metrics.