THE HIVEThe desktop is open. Mine a private token in your browser
propolis

Docs / Protocol / Spending

Spending

Spending a token buys one agent turn at the relay. The relay checks the signature, writes the token's nonce as a nullifier, and keeps nothing else.

The header

Tokens travel in the standard HTTP authentication scheme for Privacy Pass, RFC 9577. Several tokens are several comma-separated entries.

http
POST /api/v1/ask
Authorization: PrivateToken token=<base64url token>
Content-Type: application/json

{ "engine": "fast", "system": "Be brief.", "messages": [{ "role": "user", "content": "…" }], "tools": ["fetch"] }

Without a token the relay answers 401 with a WWW-Authenticate: PrivateToken challenge that carries the shared challenge and the issuer key, so any Privacy Pass client knows what to present.

What the relay checks

  • The token parses as type 0x0002 and its key id is the active key.
  • The challenge digest equals SHA-256 of the one Propolis challenge.
  • The RSA signature verifies against the issuer public key.
  • Its nonce has never been written as a nullifier. The write itself is the check: storing spent/<nonce> refuses to overwrite, so a second spend fails with 409 double_spend.

Engines

EngineModelTokens per turn
fastClaude Haiku 5.51
deepClaude Sonnet 5.54

The relay holds the model account; your question reaches the model provider from the relay, with no account, card or address of yours attached. The relay works within a daily model budget; when it is used up it answers 503 saturated until the next day, and local models in the Hive keep working.

The fetch tool

With "tools": ["fetch"], the model may ask the relay to read up to two public pages in the turn. The relay fetches them itself, so the site sees the relay and not you. It only follows public http and https addresses (no private, loopback or link-local ranges), stops at 1 MB or 8 seconds, keeps text only and hands the model the first 12,000 characters.

Receipts

Every answer comes with a receipt you can recompute:

text
receipt = SHA-256( "propolis/receipt/v1" || model || SHA-256(request json) || SHA-256(answer) )

Keep the receipt and the request JSON and you can later show which model gave which answer to which request, without the relay ever having stored either.

What the relay keeps

The nullifier and the hour it was spent. No prompt, no answer, no IP address, no user agent. The nullifiers of an hour are published, and their Merkle root is anchored on chain, so anyone can check that the set only grows.