Implement VRP in 5 minutes

Become node #2.

One node is a file format. A second independent node — signing its own offers on its own domain — is a standard.

VRP has no registry, no API key, no gatekeeper, and nothing to sign up for. You publish two static files and one signed JSON response from your own domain, and any agent can verify you directly. This page hands you a working Ed25519 signer right in your browser and the reference code (Apache-2.0) to run it in production.

Sign your first offer now ↓

Host domain discovery, signing keys, signed offer, and agent verification flow.

The whole protocol, in five steps

A VRP node is just three documents served from your own domain. There is no central server to register with — the host-owned domain is the source of truth.

  1. Generate an Ed25519 key pair. Keep the private key on your server; the public key goes in your JWKS. Use the in-browser generator below, or openssl genpkey -algorithm ed25519 / generateKeyPairSync("ed25519").
  2. Publish your JWKS. Serve the public key as a JWKS at https://<your-domain>/.well-known/jwks.json.
  3. Publish a discovery document. Serve https://<your-domain>/.well-known/vacation-rental.json pointing at your JWKS and your offer endpoint.
  4. Sign verified stay offers. For each stay request, build a verified_stay_offer with live availability, the exact total price, a valid_until window, and a direct booking URL on your own domain — then sign it as a compact JWS.
  5. Return the signed envelope. Expose your offer endpoint (e.g. /api/verified-stay-offer) returning the signed_verified_stay_offer. Done — agents can now verify you with no help from anyone.

Fail closed: when you cannot satisfy a request, return an explicit signed available: false — never an unsigned or partial answer. See the core spec (v0.1) and the implementation guide.

Copy-paste signer — sign a real offer in your browser

This runs entirely in your browser with native Web Crypto Ed25519. No library is loaded, nothing is sent anywhere, and HemmaBo's servers play no part. Fill in your details, sign, and you get the exact three files a VRP node serves — plus a live signature check so you can see it verify.

A fresh Ed25519 key pair is generated the first time you sign. In production you generate the key once and reuse it — paste the private key into your server (see below), keep the public key in your JWKS.

Reference code (Apache-2.0)

The browser signer mirrors the canonical construction exactly: base64url(header) + "." + base64url(payload) signed with Ed25519, where the header is { "alg": "EdDSA", "typ": "JWT", "kid": "<your-kid>" }. Here is the same logic as a zero-dependency Node.js module you can drop into production:

import { generateKeyPairSync, createPublicKey, sign } from "node:crypto";

// Generate ONCE, then persist privateKey securely and reuse it.
const { privateKey, publicKey } = generateKeyPairSync("ed25519");
const kid = "my-stay.example-vrp-2026";

const b64url = (b) => Buffer.from(b).toString("base64url");

export function jwks() {
  const { x } = publicKey.export({ format: "jwk" }); // { kty, crv, x }
  return { keys: [{ kty: "OKP", crv: "Ed25519", kid, use: "sig", alg: "EdDSA", key_ops: ["verify"], x }] };
}

// offer = a verified_stay_offer payload object (see schema)
export function signOffer(offer) {
  const header = { alg: "EdDSA", typ: "JWT", kid };
  const signingInput = `${b64url(JSON.stringify(header))}.${b64url(JSON.stringify(offer))}`;
  const signature = sign(null, Buffer.from(signingInput), privateKey);
  return `${signingInput}.${b64url(signature)}`; // compact JWS
}

License boundary: the specification text and schemas are CC0-1.0 (public domain — implement freely); the reference code and conformance vectors are Apache-2.0, which includes a royalty-free patent grant (§3).

Conformance vectors — prove your verifier interops

The repo ships real, reproducible Ed25519 / compact-JWS vectors so an independent implementation can load the JWKS, verify the signed offer, and reproduce the exact result — including the failure modes (tampered payload, wrong key, unknown kid, expired window). Run them with npm test (or npm run verify-vectors).

Implemented a node? VRP has no registry to add yourself to — that is the point. Just publish, and (optionally) tell us at info@hemmabo.se so we can link independent implementations.