Technical
Welcome to the OpenHerd developer documentation. This guide is for implementers of the OpenHerd protocol — from lightweight clients and relays to full libp2p participants.
Post Envelope Format
Every post in OpenHerd is cryptographically signed and self-contained.
{
"signature": "-----BEGIN PGP SIGNATURE-----...",
"publicKey": "-----BEGIN PGP PUBLIC KEY BLOCK-----...",
"id": "keyID",
"data": "{\"id\":\"keyID\",\"text\":\"...\",\"latitude\":...,\"longitude\":...,\"date\":\"...\",\"parent\":\"...\"}"
}
signature: Detached OpenPGP signature of thedatastring.publicKey: Public key used for verification and identity.id: SHA-1 fingerprint ofpublicKey, used as the post ID.-
data: Stringified JSON containing post content: -
text: Message body latitude/longitude: Randomized coordinatesdate: ISO 8601 timestampparent: ID of parent post (optional)
Creating Posts
- Every post uses a *new- PGP key.
- Signatures verify that content wasn't altered.
- Coordinates should be fuzzed before publishing for anonymity.
- Gossipsub topic:
posts
Threading
Posts are threaded via parent. Each post forms a chain back to a root.
Example:
null (root)
↳ 8558e99c...
↳ 6a63e1d0...
Catchup Requests
Topic: catchup
Used by libp2p clients to pull historical messages.
Request:
{ "max": 200 } // Optional max (default 100)
Response:
An array of envelope objects (see above), chunked if necessary, delivered on the backlog topic.
Chunking Protocol
All large messages sent over libp2p are broken into ordered chunks.
{
"index": 0,
"total": 6,
"content": "up to 500 characters"
}
They are reassembled based on index, and all topics may include chunked messages.
HTTP Sync API (/_openherd)
For bridging libp2p and HTTP worlds.
/outbox (GET)
Returns local post history.
/inbox (POST)
Receives an array of envelopes. Validates & stores them.
[ { "signature": "...", "publicKey": "...", "id": "...", "data": "..." } ]
Responds with { "ok": true } or 400 Bad Request.
/sync (POST)
Initiates sync with an HTTP or libp2p peer.
{ "address": "http://node.example.com" }
- If HTTP: Pulls from
/outbox, pushes to/inbox. - If libp2p fails: tries fallback.
Relay Nodes
Non-interactive HTTP-only devices. Great for:
- Hotspots & darknet drops
- Raspberry Pi kiosks
- Air-gapped or NAT-constrained deployments
They implement only:
/inbox(POST)/outbox(GET)
Relays *don’t- use Gossipsub or libp2p.
mDNS Service Discovery (Optional)
- Service type:
_openherd._tcp - Allows Bonjour/zeroconf detection of nearby relays
Beacon Network
Allows relays to be discovered on the internet.
/beacon/update (POST)
Registers a relay with geolocation + metadata.
{
"publicKey": "-----BEGIN PGP PUBLIC KEY BLOCK-----...",
"message": "{\"lat\":\"33.5\",\"lng\":\"-84.2\",\"nickname\":\"peachtree-drop\",\"operator\":\"School of life\",\"ssid\":\"OpenHerd\",\"macAddress\":\"aa:bb:cc:dd:ee:ff\"}",
"signature": "base64-signature",
"nonce": 2379281
}
messageis signed with the PGP private keylat/lng: Coordinates (as strings)ssid: Visible SSID (optional)macAddress: Device MAC (optional)
Post Scriptum
- All posts are per-message anonymous, as each key is one-time-use.
- Data must be signed and verified client-side.
- Clients should randomize GPS coordinates to \~100m for safety.
- Beacon registration is optional and gated by proof-of-work.