Served from this domain. The published policy is authoritative; read it before integrating.
GET /.well-known/verifier.json
Verifier public key and policy thresholds
{
"verifier": "trip-server",
"verifier_pubkey": "<64 hex>",
"protocol": "draft-ayerbe-trip-protocol-04",
"validity_secs": 3600,
"challenge_ttl_secs": 60,
"policy": { "alpha_bio_range": [0.3, 0.8], "min_confidence": 0.1, "min_trust": 20.0 }
}
POST /v1/evidence
Submit a batch of signed breadcrumbs (CBOR frame stream, binary body)
{ "stored": 116, "unique_cells": 116, "chain_head": "<64 hex>" }
// 400 — chain rule violation
{ "error": "invalid breadcrumb chain: duplicate h3 cell ... at consecutive index 1" }
GET /v1/identity/:pubkey_hex
Chain state for one attester; 404 when there is no evidence yet
{
"attester": "<64 hex>",
"breadcrumb_count": 116,
"unique_cells": 116,
"chain_head": "<64 hex>",
"last_ts": 1790397900
}
POST /v1/verify
Create a challenge bound to an RP nonce (first step of Active Verification)
// request
{ "attester": "<64 hex>", "rp_nonce": "<32 hex>", "ttl_secs": 90 }
// response
{ "challenge_id": "<32 hex>", "expires_at": 1790397960, "delivered": true }
WS /v1/challenge?attester=<pubkey_hex>
Real-time channel: the verifier pushes a LivenessChallenge (binary CBOR), the attester returns a LivenessResponse
// the client registers first
{ "type": "hello", "attester": "<64 hex>" }
// then binary frames: challenge down, response up
// example text ack from the verifier:
{ "type": "poh_issued", "ok": true, "alpha": 0.441, "beta": 3.0,
"confidence": 0.0597, "trust": 63.27, "meets_policy": false }
GET /v1/poh/:challenge_id
Fetch the issued PoH certificate (CBOR); 202 while pending
// 202 — not issued yet
{ "status": "pending", "expires_at": 1790397960 }
// 200 — the CBOR certificate (15 fields, see the protocol page)
GET /v1/explorer
Aggregate view over every attester known to this verifier (no location data at all)
{ "attesters": [ { "pubkey": "<64 hex>", "breadcrumb_count": 116, "unique_cells": 116, "last_ts": 1790397900 } ] }
Error codes
| Code | Meaning | What to do |
| 400 | Chain rule violation (same cell, interval too short, non-contiguous index, prev-hash mismatch) | Fix the trajectory or drop the violating breadcrumb and retry |
| 404 | /v1/verify cannot find the attester: no evidence uploaded yet | Upload breadcrumbs on the Collect/Import tab first |
| 404 | /v1/identity/:hex: the verifier has no record of this identity | Same as above |
| 202 | /v1/poh/:id not issued yet (the attester has not answered the challenge) | Poll until 200 or until it times out |
| 429 | Rate limited | Back off and retry |
Same-origin and the real-time channel
The verifier on this domain is same-origin with the pages (https://gyid.geoyuan.com), so the front-end needs no backend URL and there is no CORS or mixed-content concern. The WebSocket goes to wss://gyid.geoyuan.com/v1/challenge, upgraded and proxied by nginx to the local trip-server.
Privacy boundary
None of these endpoints accept or return raw coordinates. The client sends quantized H3 cells and signatures; the server returns statistics and aggregate counts. This is not a policy promise — the data structures simply have no field that could carry a coordinate.