NIP-GRAPEVINE-API
NIP-GRAPEVINE-API
GrapeVine: Relay-Computed Influence Scores
draft optional
Abstract
This NIP defines a standard HTTP API for relays to expose trust-weighted influence scores computed using the GrapeVine algorithm. These scores enable clients to filter, rank, and curate content based on social graph topology and trust signals (follows, mutes, reports).
Motivation
Nostr clients need efficient ways to:
- Filter spam and low-quality content
- Rank content by trustworthiness from a user’s perspective
- Discover trusted accounts in extended social networks
- Build reputation systems without centralized authorities
Computing these scores client-side is computationally expensive and requires full graph traversal. Relays can pre-compute and cache these scores, providing instant access to trust metrics.
Specification
Authentication
All GrapeVine API endpoints require NIP-98 HTTP Authentication. Clients MUST include a signed Nostr event in the Authorization header.
Authorization Header Format:
Authorization: Nostr <base64-encoded-event>
The authentication event MUST:
- Be kind
27235(HTTP Auth) - Have a
utag with the full request URL - Have a
methodtag with the HTTP method (GET or POST) - Be signed by the requesting user’s private key
- Have a
created_attimestamp within an acceptable time window (typically ±60 seconds)
Example Authentication Event:
{
"kind": 27235,
"created_at": 1680000000,
"tags": [
["u", "https://relay.example.com/api/grapevine/scores?observer=hexpubkey..."],
["method", "GET"]
],
"content": "",
"pubkey": "hexpubkey",
"id": "...",
"sig": "..."
}
Access Control
- Regular users can only query scores for their own pubkey (the authenticated pubkey)
- Owners and admins can query scores for any observer pubkey
- Unauthenticated requests return
401 Unauthorized - Requests for other users’ scores (non-owner) return
403 Forbidden
HTTP Endpoints
Relays MAY expose GrapeVine influence scores via HTTP endpoints under /api/grapevine/.
1. Get Full Score Set
GET /api/grapevine/scores?observer=<hex_pubkey>
Returns the complete score set for an observer pubkey.
Query Parameters:
observer(required): Hex-encoded public key (64 characters)
Response: JSON object with the following structure:
{
"observer": "abc123...",
"scores": [
{
"pubkey": "def456...",
"influence": 0.9763800964692622,
"average": 1.0,
"certainty": 0.9763800964692622,
"input": 2.70192655866738,
"wot_score": 31,
"depth": 2
}
],
"computed_at": "2026-04-09T16:22:15.123Z",
"compute_ms": 26431,
"total_pubkeys": 73542
}
2. Get Single Score
GET /api/grapevine/score?observer=<hex_pubkey>&target=<hex_pubkey>
Returns the score for a single target pubkey from the observer’s perspective.
Query Parameters:
observer(required): Hex-encoded observer public keytarget(required): Hex-encoded target public key
Response: JSON object with a single score entry:
{
"pubkey": "def456...",
"influence": 0.9763800964692622,
"average": 1.0,
"certainty": 0.9763800964692622,
"input": 2.70192655866738,
"wot_score": 31,
"depth": 2
}
3. Check Computation Status
GET /api/grapevine/status?observer=<hex_pubkey>
Returns the current computation status for an observer.
Query Parameters:
observer(optional): Hex-encoded observer public key (defaults to authenticated user)
Response:
{
"status": "completed",
"observer": "abc123...",
"computed_at": "2026-04-09T16:22:15.123Z",
"total_pubkeys": 73542
}
Status Values:
not_started: No scores have been computed yetcomputing: Computation is currently in progresscompleted: Computation finished successfully
Response Fields:
status(string): Current computation statusobserver(string): Observer pubkeycomputed_at(string, optional): ISO 8601 timestamp of last completion (only whencompleted)total_pubkeys(integer, optional): Total pubkeys in graph (only whencompleted)
4. Trigger Recalculation (Optional)
POST /api/grapevine/recalculate
Content-Type: application/json
{
"observer": "abc123..."
}
Triggers asynchronous score recalculation for the specified observer.
Response:
{
"status": "started",
"observer": "abc123..."
}
Status Values:
started: New computation job startedalready_computing: Computation already in progress (no-op)
5. Database Statistics (Optional)
GET /api/stats
Returns database statistics about the relay’s social graph.
Response:
{
"kind3_author_count": 12543,
"kind3_referenced_count": 73542
}
Response Fields:
kind3_author_count(integer): Number of unique pubkeys that have published kind-3 (contact list) eventskind3_referenced_count(integer): Number of unique pubkeys referenced in p-tags of all kind-3 events (total social graph size)
Note: This endpoint does not require authentication and provides insight into the size of the relay’s social graph index. The referenced count is typically larger than the author count, as it includes all pubkeys that appear in anyone’s follow list.
Response Schema
ScoreSet Object
| Field | Type | Description |
|---|---|---|
observer |
string | Hex pubkey from whose perspective scores are computed |
scores |
array | Array of score entries (see below) |
computed_at |
string | ISO 8601 timestamp of computation |
compute_ms |
integer | Computation time in milliseconds |
total_pubkeys |
integer | Total pubkeys in the social graph |
ScoreEntry Object
| Field | Type | Range | Description |
|---|---|---|---|
pubkey |
string | 64 hex | Target pubkey being scored |
influence |
number | 0.0 - 1.0 | Primary score: trust-weighted reputation |
average |
number | -1.0 - 1.0 | Average rating (1=trusted, -1=distrusted) |
certainty |
number | 0.0 - 1.0 | Confidence in the score (based on signal strength) |
input |
number | 0.0+ | Sum of rating weights (unbounded) |
wot_score |
integer | 0+ | Web of Trust intersection count |
depth |
integer | 0+ | Hop distance from observer in social graph |
Score Interpretation
Influence Score (Primary Metric)
The influence field is the primary trust metric, computed as average × certainty:
- 0.8 - 1.0: Very high trust (close connections, strong positive signals)
- 0.5 - 0.8: High trust (extended network, good reputation)
- 0.2 - 0.5: Medium trust (distant connections, weak signals)
- 0.0 - 0.2: Low trust (very distant or minimal signals)
- < 0.0: Distrust (muted or reported by trusted accounts)
WoT Score (Secondary Metric)
The wot_score field counts how many of the observer’s direct follows also follow the target pubkey. Higher values indicate stronger social proof.
Depth (Distance Metric)
The depth field indicates BFS hop distance in the follow graph:
- 0: Observer themselves
- 1: Direct follow
- 2: Friend-of-friend
- 3+: Extended network
Algorithm
The GrapeVine algorithm is based on iterative trust propagation:
- Graph Traversal: BFS outward from observer up to
max_depthhops (typically 6) - Initialization: Observer starts with influence = 1.0, all others at 0.0
- Convergence Loop: Iteratively update each pubkey’s score based on:
- Follows (kind 3): Positive trust signal (+1.0 rating)
- Mutes (kind 10000): Negative trust signal (-1.0 rating)
- Reports (kind 1984): Negative trust signal (-1.0 rating)
- Attenuation: Influence decays by distance (typically 0.8 per hop)
- Certainty: Confidence increases with more rating signals
- Convergence: Stop when changes fall below threshold or max iterations reached
Key Parameters:
max_depth: BFS hop limit (default: 6)attenuation_factor: Weight decay per hop (default: 0.8)rigor: Certainty curve steepness (default: 0.25)follow_confidence: Base weight for follow edges (default: 0.05)
Error Responses
401 Unauthorized: Missing or invalid NIP-98 authentication
{
"error": "NIP-98 authentication failed"
}
403 Forbidden: Authenticated user trying to access another user’s scores
{
"error": "Can only query your own scores"
}
404 Not Found: Scores not computed for this observer
{
"error": "Scores not found for observer"
}
400 Bad Request: Invalid pubkey format
{
"error": "Invalid pubkey format"
}
503 Service Unavailable: GrapeVine API not enabled
{
"error": "GrapeVine API not enabled"
}
Client Usage
Clients MUST implement NIP-98 HTTP authentication to access these endpoints. See the Authentication section above for details on creating the required authorization header.
Relay Implementation
Computation
Relays SHOULD:
- Pre-compute scores for configured observer pubkeys
- Refresh scores periodically (e.g., every 6 hours)
- Cache results in persistent storage
- Support on-demand recalculation via POST endpoint
Performance
Typical computation metrics:
- Graph size: 50k-100k pubkeys
- Computation time: 20-30 seconds
- Storage: ~50 bytes per score entry
- Memory: ~500MB during computation
Privacy
Relays SHOULD:
- Only compute scores for explicitly configured observers
- Rate-limit score requests to prevent enumeration
- Consider requiring NIP-42 AUTH for score access
- Not expose scores for arbitrary pubkeys without permission
Security Considerations
Sybil Resistance
The GrapeVine algorithm provides natural Sybil resistance through:
- Attenuation by distance (fake accounts are distant)
- Trust propagation (requires connections to trusted accounts)
- WoT intersection (fake accounts have low social proof)
However, sophisticated attacks may still succeed. Clients SHOULD:
- Combine influence scores with other signals
- Allow users to adjust trust thresholds
- Provide manual override mechanisms
Gaming
Malicious actors may attempt to:
- Create follow/unfollow cycles to manipulate scores
- Coordinate fake follow networks
- Report legitimate accounts
Relays MAY implement additional protections:
- Temporal analysis (detect rapid follow/unfollow patterns)
- Account age weighting
- Cross-relay score comparison
Privacy
Score computation reveals social graph topology. Relays SHOULD:
- Limit score access to authenticated users
- Not expose raw graph data
- Consider differential privacy techniques for sensitive deployments
References
- Brainstorm GrapeRank Algorithm - Reference implementation
- NIP-02 - Follow List (kind 3)
- NIP-51 - Lists (kind 10000 mute lists)
- NIP-56 - Reporting (kind 1984)
- NIP-85 - Trusted Assertions
- NIP-98 - HTTP Auth
Changelog
- 2026-04-09: Initial draft
Looking for comments…
Searching Nostr relays. This may take a moment the first time this article is opened.
Looking for comments…
Searching Nostr relays. This may take a moment the first time this article is opened.