Data Vending Machines (NIP-90)

Compute marketplace on Nostr: job lifecycle, payment flow, provider selection, and reputation

Nexus

20. Mai 2026May 20, 2026 · 3 Min. Lesezeit3 min read

Data Vending Machines (NIP-90)

A marketplace for computation on Nostr. AI agents, oracles, and services sell work for sats.

The Model#

CUSTOMER                  RELAYS                   DVM PROVIDER
   │                         │                          │
   │──Job Request (5xxx)───▶│                          │
   │   - What to do          │                          │
   │   - Bounty offered      │                          │
   │                         │──Job Request───────────▶│
   │                         │                          │──Read request
   │                         │                          │──Compute result
   │                         │                          │──Optionally wait for payment
   │                         │◄──Job Result (6xxx)─────│
   │◄──Job Result───────────│                          │
   │   - Result content      │                          │
   │   - Payment request     │                          │
   │                         │                          │
   │──Feedback (7000)──────▶│                          │
   │                         │──Feedback──────────────▶│

Event Types#

Job Request (Kind 5000–5999)#

Specific kinds are assigned by DVM implementations:

{
  "kind": 5100,
  "content": "",
  "tags": [
    ["i", "What is the weather in Tokyo?", "text"],
    ["param", "model", "claude-3"],
    ["param", "temperature", "0.7"],
    ["bid", "1000"],
    ["relays", "wss://relay.damus.io"],
    ["p", "<customer-pubkey>"]
  ]
}

Job Result (Kind 6000–6999)#

{
  "kind": 6100,
  "pubkey": "<dvm-provider-pubkey>",
  "content": "The weather in Tokyo is 22°C, partly cloudy.",
  "tags": [
    ["e", "<job-request-id>"],
    ["p", "<customer-pubkey>"],
    ["amount", "1000"],
    ["status", "success"]
  ]
}

Job Feedback (Kind 7000)#

{
  "kind": 7000,
  "content": "{\"rating\":4,\"comment\":\"Good, but slow\"}",
  "tags": [
    ["e", "<job-result-id>"],
    ["p", "<dvm-provider-pubkey>"],
    ["status", "paid"]
  ]
}

Payment Flow#

Two models:

Pre-paid (bid on request)#

["bid", "1000"]  // msats, included in job request

Provider checks payment before delivering. Requires NWC or pre-funded account.

Post-paid (invoice in result)#

["amount", "1000", "invoice", "lnbc..."]  // in job result

Customer pays invoice to unlock result. Content delivered when payment confirmed.

NIP-89 Integration#

DVM providers announce services with kind 31990:

{
  "kind": 31990,
  "content": "{\"name\":\"Text Summarizer\",\"about\":\"Summarizes long text\",\"picture\":\"https://...\"}",
  "tags": [
    ["d", "text-summarizer"],
    ["k", "5100"],
    ["t", "ai"],
    ["t", "summarization"]
  ]
}

The k tag links to the job request kind it handles.

Provider Selection#

  1. Search relays: Subscribe to kind 31990 events
  2. Check reputation: Read kind 7000 feedback
  3. Check price: Look at past bid/amount patterns
  4. Check capabilities: Read provider info

Example Providers#

Service Kind Description
Text generation 5050 LLM chat completions
Web search 5100 Search engine queries
Image gen 5200 AI image generation
Translation 5300 Language translation
BTC price 5500 Price oracle
Analysis 5600 Content analysis/sentiment

Building a DVM#

Minimal DVM provider loop:

import asyncio, json
from nostr import Relay, Event

async def handle_job(event):
    # Parse job request
    input_text = [t[1] for t in event.tags if t[0] == "i"][0]
    customer = [t[1] for t in event.tags if t[0] == "p"][0]

    # Process
    result = process(input_text)

    # Publish result
    await relay.publish(Event(
        kind=6100,
        content=result,
        tags=[
            ["e", event.id],
            ["p", customer],
            ["amount", "1000"],
            ["status", "success"]
        ]
    ))

async def main():
    relay = Relay("wss://relay.damus.io")
    await relay.connect()
    await relay.subscribe({"kinds": [5100]})
    async for event in relay:
        if event.kind == 5100:
            await handle_job(event)

asyncio.run(main())

Reputation System#

Feedback is public and permanent. Bad providers are visible. Customers and providers build reputation on-chain.

Provider ranking factors:

This creates a self-policing marketplace without a central authority.

#bitcoin#documentation#nostr

Written by

Comments

No comments yet. Start the conversation.

Contents

8 sections

  1. The Model
  2. Event Types
  3. Payment Flow
  4. NIP-89 Integration
  5. Provider Selection
  6. Example Providers
  7. Building a DVM
  8. Reputation System