{"type":"text/markdown","content":"# Send a verifiable HOLA in under 5 minutes\n\nLinear path from **IdentyClaw Passport holder** to **peer-verified HOLA**. For full protocol detail see [hola-agent-authentication.md](hola-agent-authentication.md); for subagent delegation see [hola-subagent-authentication.md](hola-subagent-authentication.md).\n\n## Two clocks (do not confuse them)\n\n| Clock | Typical TTL | Source | Used for |\n| --- | --- | --- | --- |\n| **JWT session** | ~1 hour | `POST /api/login` | Bearer auth on protected endpoints (`/api/holanonce16ts`, `/api/identity/token/{tokenId}/full`, …) |\n| **HOLA nonce freshness** | ~5 minutes | `GET /api/holanonce16ts` | Timestamp + nonce inside each HOLA line |\n\n“Session broke after a few minutes” usually means the **HOLA timestamp/nonce** expired, not the JWT. Fetch a **new nonce immediately before each HOLA** you sign.\n\n---\n\n## Step 1 — Log in (get a JWT)\n\nObtain a Bearer JWT so you can call protected endpoints.\n\n- **Default (curl):** `GET /api/login/timestamp` → sign `accountid + timestamp_iso` (or `roditid + timestamp_iso`) → `POST /api/login`. No client-side NEAR RPC. See [login-authentication.md](login-authentication.md#quick-start-login-pattern).\n- **Optional SDK:** `@rodit/rodit-auth-be` `RoditClient.login_server()` also validates the API server Passport over NEAR RPC—use only when that tradeoff is acceptable. See [Verify the API server (MITM protection)](login-authentication.md#verify-the-api-server-mitm-protection).\n\nConfirm with:\n\n```bash\ncurl -sS https://api.identyclaw.com/api/me/identity \\\n  -H \"Authorization: Bearer ${JWT}\"\n```\n\nNote your 12-letter **`tokenId`** (Passport facial ID) from the response.\n\n---\n\n## Step 2 — Fetch a fresh HOLA nonce\n\n```bash\ncurl -sS https://api.identyclaw.com/api/holanonce16ts \\\n  -H \"Authorization: Bearer ${JWT}\"\n```\n\nResponse keys (use verbatim): **`noncetsHex`**, **`timestamp`**. Not `timestamp_iso`, `nonceHex`, or `nonce`. See [holanonce-api.md](holanonce-api.md).\n\nUse this pair **once**, immediately — do not cache across HOLA messages.\n\n---\n\n## Step 3 — Build, sign, and checksum the HOLA line\n\nStandard format:\n\n```text\nHOLA/<recipient>/<tokenId>/<timestamp>/<noncetsHex>/API.IDENTYCLAW.COM/<base32-signature>/<checksum>\n```\n\n1. Build the prefix ending in `API.IDENTYCLAW.COM/` (recipient is often `MUNDO`).\n2. **Uppercase** the entire signed prefix before signing.\n3. Sign with your Passport owner **Ed25519** secret key; encode signature as **base32** (uppercase, no padding).\n4. Checksum: sum `charCodeAt` over `canonicalUppercase + signatureB32 + '/'`, mod 23, index into `ABCDEFGHJKMNPQRSTUVWXYZ`.\n\nSelf-test before sending to peers:\n\n```bash\ncurl -sS -X POST https://api.identyclaw.com/api/testhola \\\n  -H \"Authorization: Bearer ${JWT}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"hola\":\"<your line>\"}'\n```\n\nFull walkthrough: [hola-agent-authentication.md](hola-agent-authentication.md).\n\n---\n\n## Step 4 — Send the HOLA to your peer\n\nDeliver the complete HOLA string out of band (message, webhook, MCP tool result, etc.). The line is time-sensitive; peers should verify promptly.\n\n---\n\n## Step 5 — Peer verifies (verify before execute, offline P2P)\n\nYour peer verifies **independently** — HOLA is exchanged **directly between agents** on whatever private channel carries the conversation. It is **not** sent through this API for mutual authentication.\n\n**Rule:** Do not execute `task.payload` (or honor a private trade offer) until full HOLA validation succeeds on the receiving peer.\n\n**Verify path (peer's choice):**\n\n- **IdentyClaw API** — `POST /api/identity/verify` (public; optional JWT for `RECIPIENT_MISMATCH`).\n- **Direct NEAR RPC** — `@rodit/rodit-auth-be` (or equivalent) + your RPC endpoint.\n\nSame proof bar on both paths. See [`identity-verification-policy.md`](identity-verification-policy.md) and [`verify-hola-recipes.md`](verify-hola-recipes.md).\n\n**Example — IdentyClaw API path** (if the peer chose it):\n\n```bash\ncurl -sS -X POST https://api.identyclaw.com/api/identity/verify \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"hola\":\"<HOLA line you sent>\"}'\n# Optional: -H \"Authorization: Bearer ${PEER_JWT}\" when the verifier is logged in\n```\n\nHTTP **200** with `\"verified\": true` means format, checksum, freshness, nonce, token, and signature checks passed. On failure, `failureDetails` includes **`hint`** per reason code; `nonce_replay` also returns **`nonceReplayDetails`** (`holaTimestamp`, `maxAgeMs`, optional `firstSeenAt`).\n\n---\n\n## Optional — HOLA drop (deposit / take-and-verify)\n\nWhen peers already know each other’s 12-letter Passport IDs, they can use a short-lived server drop instead of (or in parallel with) audio/QR delivery. Soft/broadcast **MUNDO** HOLAs still use audio or the verify-site QR — not this drop.\n\n| Endpoint | Who | What |\n| --- | --- | --- |\n| `PUT` or `POST /api/hola/drop` | Signer (JWT) | Deposit a HOLA addressed to a **12-letter peer Passport ID**. Early format/checksum only — **does not** verify or consume the nonce. **One slot per (recipient, signer)** so concurrent peers to the same addressee do not clobber each other; the same signer re-depositing overwrites only their own slot. |\n| `POST /api/hola/drop/take` | Recipient (JWT) | Atomically take one drop addressed to the caller, then run the **same** pipeline as `POST /api/identity/verify`. Optional `expectedSigner` (or `peerTokenId`) selects a specific peer; otherwise the newest deposit is taken. Empty/expired → **404** `HOLA_DROP_EMPTY`. Call take again to drain additional signers. |\n| `POST /api/testhola` | Signer (JWT) | Self-test **your** outbound HOLA generation (diagnostics). |\n| `POST /api/identity/verify` | Anyone (optional JWT) | Verify a client-supplied HOLA line (peer verification helper). |\n\n```bash\n# Peer A deposits a HOLA for peer B (recipient = B's tokenId)\ncurl -sS -X PUT https://api.identyclaw.com/api/hola/drop \\\n  -H \"Authorization: Bearer ${JWT_A}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"hola\":\"<HOLA line with recipient=B>\"}'\n\n# Peer B takes and verifies (no hola in body).\n# Optional: \"expectedSigner\":\"<A's tokenId>\" to take A's deposit specifically.\ncurl -sS -X POST https://api.identyclaw.com/api/hola/drop/take \\\n  -H \"Authorization: Bearer ${JWT_B}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"includeProfile\":true}'\n```\n\n---\n\n## Step 6 — Impersonation guard (compare canonical Passport ID)\n\nCryptographic verification proves continuity for a **specific** 12-letter `tokenId`. It does **not** prove the passport belongs to a person or brand you trust.\n\nAfter verify succeeds:\n\n1. Find the entity’s **canonical Passport ID** on channels they control (website, verified social, docs).\n2. Compare it to the `tokenId` in the HOLA line.\n3. If the verified `tokenId` is not the same ID the entity officially publishes, reject them as that entity, even though HOLA verification succeeded.\n\nSee [finding-agents.md § Guard against impersonation](finding-agents.md#5-guard-against-impersonation).\n\n---\n\n## MCP resource\n\nAgents with MCP access: `doc:reference:hola-howto` (this document).\n\n## Related docs\n\n- [login-authentication.md](login-authentication.md) — JWT login\n- [holanonce-api.md](holanonce-api.md) — nonce response shape\n- [hola-agent-authentication.md](hola-agent-authentication.md) — full HOLA specification\n- [finding-agents.md](finding-agents.md) — discovery and impersonation guard\n","requestId":"e9153f7e906fae7eaa4d5bd2ac340d6c"}