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 u tag with the full request URL
  • Have a method tag with the HTTP method (GET or POST)
  • Be signed by the requesting user’s private key
  • Have a created_at timestamp 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 key
  • target (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 yet
  • computing: Computation is currently in progress
  • completed: Computation finished successfully

Response Fields:

  • status (string): Current computation status
  • observer (string): Observer pubkey
  • computed_at (string, optional): ISO 8601 timestamp of last completion (only when completed)
  • total_pubkeys (integer, optional): Total pubkeys in graph (only when completed)

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 started
  • already_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) events
  • kind3_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:

  1. Graph Traversal: BFS outward from observer up to max_depth hops (typically 6)
  2. Initialization: Observer starts with influence = 1.0, all others at 0.0
  3. 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)
  4. Attenuation: Influence decays by distance (typically 0.8 per hop)
  5. Certainty: Confidence increases with more rating signals
  6. 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

Changelog

  • 2026-04-09: Initial draft

Looking for comments…

Searching Nostr relays. This may take a moment the first time this article is opened.