{"type":"text/markdown","content":"# API Reference\n\nComplete endpoint listing for IdentyClaw API.\n\n## Table of Contents\n\n- [Public Endpoints](#public-endpoints)\n- [Protected Endpoints](#protected-endpoints)\n- [Privileged Endpoints](#privileged-endpoints)\n- [DID Resolution](#did-resolution)\n- [MCP Resources](#mcp-resources)\n- [Policy Documents](#policy-documents)\n\n## Public Endpoints\n\nNo authentication required.\n\n### Discovery\n\n| Endpoint | Method | Description |\n|----------|--------|-------------|\n| `/` | GET | API overview with enrollment URL and endpoint listing |\n| `/health` | GET | Health check endpoint |\n| `/.well-known/enrollment` | GET | Complete enrollment guide with pricing and steps |\n| `/.well-known/mcp` | GET | MCP discovery metadata — see [mcp-connection-guide.md](mcp-connection-guide.md) |\n| `/openapi.json` | GET | Canonical OpenAPI 3.0 specification |\n| `/swagger.json` | GET | OpenAPI 3.0 specification (alias of `/openapi.json`) |\n| `/api/v1/openapi.json` | GET | Deprecated redirect to `/openapi.json` |\n| `/docs/enrollment` | GET | **Removed** — always returns `410 ENDPOINT_REMOVED` |\n| `/api-docs` | * | **Removed** — always returns `410 ENDPOINT_REMOVED` |\n\n### Authentication\n\n| Endpoint | Method | Description |\n|----------|--------|-------------|\n| `/api/login/timestamp` | GET | Get single-use timestamp challenge pair for login |\n| `/api/login` | POST | Authenticate with accountid signature and fresh challenge, get JWT |\n\nLogin request/response shapes, field constraints, and error semantics are maintained in OpenAPI:\n\n- Canonical contract: [`../api-docs/swagger.json`](../api-docs/swagger.json)\n- Runtime endpoints: `GET /openapi.json`, `GET /swagger.json`\n\nFor step-by-step API login implementation guidance (challenge retrieval, signing flow, retries, and troubleshooting), use:\n\n- [`login-authentication.md`](login-authentication.md)\n\n### Agent Discovery\n\n| Endpoint | Method | Description |\n|----------|--------|-------------|\n| `/api/agents` | GET | List all IdentyClaw Passport holders (cursor-paginated) |\n\n**Query Parameters**:\n- `limit` (default: 20, max: 100)\n- `cursor` (optional, for pagination)\n\n**Response**:\n```json\n{\n  \"agents\": [\n    {\n      \"tokenId\": \"bkbvehbdcrgm\",\n      \"creature\": \"Legal Specialist\",\n      \"face\": {\n        \"checksumValid\": true,\n        \"categories\": {\n          \"skinTone\": { \"index\": 2, \"letter\": \"c\", \"value\": \"pale-skinned\" },\n          \"ethnicity\": { \"index\": 1, \"letter\": \"b\", \"value\": \"Nordic\" },\n          \"faceShape\": { \"index\": 0, \"letter\": \"a\", \"value\": \"oval-faced\" }\n        }\n      }\n    }\n  ],\n  \"nextCursor\": \"cursor_string_or_null\",\n  \"requestId\": \"01HQXYZ...\",\n  \"disclaimer\": \"The creature field and other agent metadata are self-declared by the agent. It is your responsibility to verify the accuracy and authenticity of this information before relying on it.\"\n}\n```\n\n### Client Token Signing\n\n| Endpoint | Method | Description |\n|----------|--------|-------------|\n| `/api/signclient` | POST | Request server to sign client token metadata |\n\n**Note**: Request non-privileged signing operations through this endpoint. Use permissioned metrics/system/debug/reset endpoints for privileged flows.\n\n### Identity Verification\n\n| Endpoint | Method | Description |\n|----------|--------|-------------|\n| `/api/identity/verify` | POST | Verify peer HOLA message (public; optional JWT for `RECIPIENT_MISMATCH`; edge rate-limited) |\n\n**POST /api/identity/verify**:\n\nVerify a HOLA message from a peer agent. No authentication required. When a bearer JWT is supplied, the caller's authenticated identity is used for `RECIPIENT_MISMATCH` warnings (suppress with `expectedRecipient`).\n\n**Request**:\n```json\n{\n  \"hola\": \"HOLA/MUNDO/bkbvehbdcrgm/2026-04-19T10:47:00.000Z/4F9A3C7E.../API.IDENTYCLAW.COM/dGVzdA.../M\"\n}\n```\n\n**Response** (HTTP 200 when well-formed — trust only when `verified` is true):\n```json\n{\n  \"verified\": true,\n  \"peerTokenId\": \"bkbvehbdcrgm\",\n  \"destinatary\": \"MUNDO\",\n  \"checks\": {\n    \"tokenExists\": true,\n    \"tokenActive\": true,\n    \"timestampFresh\": true,\n    \"nonceReplaySafe\": true,\n    \"signatureValid\": true,\n    \"checksumValid\": true\n  },\n  \"failureReasons\": [],\n  \"requestId\": \"01HQXYZ...\"\n}\n```\n\nSee [hola-agent-authentication.md](hola-agent-authentication.md) for full diagnostics.\n\n---\n\n## Protected Endpoints\n\nRequire JWT authentication via `Authorization: Bearer <token>` header.\n\n### Identity\n\n| Endpoint | Method | Description |\n|----------|--------|-------------|\n| `/api/me/identity` | GET | Get your own identity information |\n| `/api/identity/token/{tokenId}/full` | GET | Get full identity metadata for any token |\n| `/api/isauthorizedsigner` | POST | Check if caller is authorized to sign |\n\n**GET /api/identity/token/{tokenId}/full**:\n\nReturns complete identity metadata including DN attributes, facial description, and peer-routable `metadata.webhook_url` when set on-chain.\n\n**Response**:\n```json\n{\n  \"tokenId\": \"bkbvehbdcrgm\",\n  \"dn\": {\n    \"raw\": \"NNSWF=Alice,Creature=Legal Specialist,Address=123 Main St\",\n    \"nameNotSharedWithFamily\": \"Alice\",\n    \"nameSharedWithFamily\": \"Smith\",\n    \"displayName\": \"Alice Smith\",\n    \"contactUri\": \"alice@example.com\",\n    \"taxResidence\": \"US\",\n    \"inceptDateTime\": \"2026-01-01T00:00:00.000Z\",\n    \"inceptPlace\": \"New York\",\n    \"taxPayerCode\": \"12-3456789\",\n    \"address\": \"123 Main St\",\n    \"creature\": \"Legal Specialist\",\n    \"avatarUrl\": \"https://example.com/avatar.jpg\",\n    \"emojiUrl\": \"https://example.com/emoji.png\",\n    \"allAttributes\": {}\n  },\n  \"face\": {\n    \"checksumValid\": true,\n    \"categories\": {\n      \"skinTone\": { \"index\": 2, \"letter\": \"c\", \"value\": \"pale-skinned\" },\n      \"ethnicity\": { \"index\": 1, \"letter\": \"b\", \"value\": \"Nordic\" },\n      \"faceShape\": { \"index\": 0, \"letter\": \"a\", \"value\": \"oval-faced\" }\n    }\n  },\n  \"metadata\": {\n    \"webhook_url\": \"https://my-openclaw.example.com\"\n  },\n  \"requestId\": \"01HQXYZ...\",\n  \"disclaimer\": \"The DN metadata including creature, name, contact URI, address, and other attributes are self-declared by the agent. It is your responsibility to verify the accuracy and authenticity of this information before relying on it.\"\n}\n```\n\n### Nonces\n\n| Endpoint | Method | Description |\n|----------|--------|-------------|\n| `/api/holanonce16ts` | GET | Get nonce for HOLA message (16-byte nonce); requires Bearer JWT |\n\n**Exact response JSON keys** (use verbatim; not login `timestamp_iso` / not `nonceHex`): `noncetsHex`, `timestamp`, `length`, `algorithm`, `requestId`. See [holanonce-api.md](holanonce-api.md).\n\n**Response**:\n```json\n{\n  \"noncetsHex\": \"4F9A3C7E2D1B9A4CDEADBEEFCAFEBABE\",\n  \"timestamp\": \"2026-04-19T10:47:00.000Z\",\n  \"length\": 16,\n  \"algorithm\": \"randomBytes(16)_hex\",\n  \"requestId\": \"01HQXYZ...\"\n}\n```\n\n### Session Management\n\n| Endpoint | Method | Description |\n|----------|--------|-------------|\n| `/api/logout` | POST | Logout and invalidate JWT token |\n\n### HOLA Self-Test\n\n| Endpoint | Method | Description |\n|----------|--------|-------------|\n| `/api/testhola` | POST | Validate **your own** outbound HOLA before sending to peers (JWT required; not permission-gated) |\n\n**POST /api/testhola**:\n\nSelf-testing endpoint — submit a complete HOLA line you generated. On success the server returns its own valid HOLA response. For verifying **another agent's** HOLA, use public `POST /api/identity/verify` instead.\n\n**Request**:\n```json\n{\n  \"hola\": \"HOLA/MUNDO/bkbvehbdcrgm/2026-04-19T10:47:00.000Z/4F9A3C7E2D1B9A4CDEADBEEFCAFEBABE/API.IDENTYCLAW.COM/MFRGG.../J\"\n}\n```\n\nOptional: `expectedRecipient` — suppresses `RECIPIENT_MISMATCH` when the HOLA recipient does not match your authenticated Passport ID.\n\n**Response** (HTTP 200 when valid):\n```json\n{\n  \"valid\": true,\n  \"peerTokenId\": \"bkbvehbdcrgm\",\n  \"destinatary\": \"MUNDO\",\n  \"peerVerified\": true,\n  \"hola\": \"HOLA/MUNDO/<serverTokenId>/.../API.IDENTYCLAW.COM/.../X\",\n  \"serverTokenId\": \"pkcnjdbdefcp\",\n  \"checks\": {\n    \"formatValid\": true,\n    \"checksumValid\": true,\n    \"timestampFresh\": true,\n    \"nonceReplaySafe\": true,\n    \"signatureValid\": true\n  },\n  \"requestId\": \"01HQXYZ...\"\n}\n```\n\nInvalid payloads return HTTP 400 with `code: HOLA_VALIDATION_FAILED` and `error.details.reasonCode`.\n\n---\n\n## Privileged Endpoints\n\nRequire JWT authentication AND specific permissions in IdentyClaw Passport's `permissioned_routes`.\n\n### Metrics\n\n| Endpoint | Method | Description | Permission Required |\n|----------|--------|-------------|---------------------|\n| `/api/metrics` | GET | Get performance metrics (admin only) | `metrics` |\n| `/api/metrics/system` | GET | Get system metrics (admin only) | `system` |\n| `/api/metrics/reset` | POST | Reset metrics | `reset` |\n| `/api/metrics/debug` | GET | Get debug information | `debug` |\n\n### Sessions\n\n| Endpoint | Method | Description | Permission Required |\n|----------|--------|-------------|---------------------|\n| `/api/sessions/list_all` | GET | List all active sessions | `list_all` |\n| `/api/sessions/cleanup` | POST | Cleanup expired sessions | `cleanup` |\n| `/api/sessions/revoke` | POST | Revoke specific session | `revoke` |\n\n---\n\n## DID Resolution\n\n**Status:** Experimental (OpenAPI). **Method specification:** [did-rodit-method.md](did-rodit-method.md).\n\nProtected endpoints for DID resolution (require JWT authentication). Primary identifier: `did:rodit:<12-letter-passport-id>`. Alias: `did:web:<host>:token:<passport-id>`. Resolution uses the server’s `NEAR_CONTRACT_ID` on NEAR mainnet.\n\n| Endpoint | Method | Description |\n|----------|--------|-------------|\n| `/.well-known/did/rodit/{tokenId}` | GET | Get DID document for IdentyClaw Passport |\n| `/.well-known/did/resolve` | GET | Resolve DID from token ID (query param: `did`) |\n| `/.well-known/did/web/token/{tokenId}` | GET | Get DID:web document |\n| `/.well-known/did/web/token/{tokenId}/did.json` | GET | Get DID:web JSON document |\n\n**Example** (`GET /.well-known/did/resolve?did=did:rodit:bkbvehbdcrgm`):\n\nSee [did-rodit-method.md §5](did-rodit-method.md#5-did-document) for the full document shape. Illustrative fields:\n\n```json\n{\n  \"id\": \"did:rodit:bkbvehbdcrgm\",\n  \"alsoKnownAs\": [\n    \"did:web:api.identyclaw.com:token:bkbvehbdcrgm\"\n  ],\n  \"controller\": \"<near-owner-account-id>\",\n  \"verificationMethod\": [\n    {\n      \"id\": \"did:rodit:bkbvehbdcrgm#controller\",\n      \"type\": \"Ed25519VerificationKey2020\",\n      \"publicKeyBase58\": \"...\"\n    }\n  ],\n  \"authentication\": [\n    \"did:rodit:bkbvehbdcrgm#controller\"\n  ],\n  \"service\": [\n    \"RoditTokenMetadata\",\n    \"MCPDiscoveryService\"\n  ]\n}\n```\n\n---\n\n## MCP Resources\n\nMachine-readable capabilities for AI agent discovery (public endpoints).\n\n| Endpoint | Method | Description |\n|----------|--------|-------------|\n| `/api/mcp/resources` | GET | List all available MCP resources |\n| `/api/mcp/resource/{uri}` | GET | Get specific MCP resource by URI |\n| `/api/mcp/schema` | GET | Get MCP schema definition |\n\n### MCP Streamable HTTP Transport\n\nDistinct from REST discovery above — requires an MCP client (not plain `curl` for docs). See [mcp-connection-guide.md](mcp-connection-guide.md).\n\n| Endpoint | Method | Description |\n|----------|--------|-------------|\n| `/mcp` | GET | SSE stream for an established MCP session (`Accept: text/event-stream`) |\n| `/mcp` | POST | JSON-RPC MCP requests (`Accept: application/json, text/event-stream`) |\n| `/mcp` | DELETE | Terminate an MCP transport session |\n\n---\n\n**GET /api/mcp/resources**:\n\nLists all available MCP resources for AI agent integration.\n\n**Response**:\n```json\n{\n  \"resources\": [\n    {\n      \"uri\": \"jsonld:context\",\n      \"name\": \"JSON-LD Context\",\n      \"description\": \"JSON-LD context for semantic mappings\",\n      \"mimeType\": \"application/ld+json\"\n    },\n    {\n      \"uri\": \"jsonld:contract-metadata\",\n      \"name\": \"Contract Metadata\",\n      \"description\": \"Contract metadata as JSON-LD\",\n      \"mimeType\": \"application/ld+json\"\n    },\n    {\n      \"uri\": \"howto:enrollment\",\n      \"name\": \"Enrollment Guide\",\n      \"description\": \"Complete enrollment guide with pricing\",\n      \"mimeType\": \"text/markdown\"\n    },\n    {\n      \"uri\": \"howto:authentication\",\n      \"name\": \"Authentication Flows\",\n      \"description\": \"API login and HOLA protocol flows\",\n      \"mimeType\": \"text/markdown\"\n    },\n    {\n      \"uri\": \"howto:hola-protocol\",\n      \"name\": \"HOLA Protocol\",\n      \"description\": \"HOLA protocol specification\",\n      \"mimeType\": \"text/markdown\"\n    }\n  ],\n  \"requestId\": \"01HQXYZ...\"\n}\n```\n\n**GET /api/mcp/resource/{uri}**:\n\nRetrieve a specific MCP resource by URI.\n\n**Example**: `GET /api/mcp/resource/jsonld:context`\n\n**Response**: Returns the resource content (format varies by resource type)\n\n---\n\n## Policy Documents\n\nPublic policy documents (no authentication required).\n\n| Endpoint | Method | Description |\n|----------|--------|-------------|\n| `/.well-known/terms-of-service` | GET | Terms of Service |\n| `/.well-known/privacy-policy` | GET | Privacy Policy |\n| `/.well-known/data-retention` | GET | Data Retention Policy |\n| `/.well-known/why-identyclaw` | GET | Use cases and benefits of IdentyClaw |\n\n---\n\n## Rate Limiting\n\nTwo layers apply:\n\n| Layer | Scope | Mechanism |\n|-------|-------|-----------|\n| **Edge (public routes)** | Selected public URIs (e.g. `/api/login/timestamp`, `/api/identity/verify`, `/api/agents`) | nginx `limit_req` per `$remote_addr` — see OpenAPI `info.x-publicRateLimit` (1101 req/min sustained, burst 6101) |\n| **Authenticated routes** | Protected/privileged routes after JWT login | Per-Passport `max_requests` / `maxrq_window` from on-chain metadata via SDK rate limiter |\n\nThe API does **not** emit `X-RateLimit-*` headers. Rate-limit failures use the standard error envelope:\n\n**Response** (HTTP 429, public edge example):\n```json\n{\n  \"error\": {\n    \"code\": \"RATE_LIMIT_EXCEEDED\",\n    \"message\": \"Exceeded anonymous auth-params rate limit\"\n  },\n  \"requestId\": \"01HX9WZ7F7B5DDXPKRZC4J8M0X\",\n  \"timestamp\": \"2026-04-15T08:20:00.000Z\"\n}\n```\n\n---\n\n## Error Codes\n\nCommon error codes across all endpoints:\n\n| Code | Status | Description |\n|------|--------|-------------|\n| `UNAUTHORIZED` | 401 | Missing or invalid JWT token |\n| `FORBIDDEN` | 403 | Insufficient permissions |\n| `NOT_FOUND` | 404 | Resource not found |\n| `RATE_LIMIT_EXCEEDED` | 429 | Too many requests |\n| `INTERNAL_SERVER_ERROR` | 500 | Server error |\n\n### Authentication Errors\n\n| Code | Status | Description |\n|------|--------|-------------|\n| `SIGNATURE_VERIFICATION_FAILED_035` | 401 | Signature verification failed |\n| `TOKEN_EXPIRED` | 401 | IdentyClaw Passport expired |\n| `TOKEN_NOT_FOUND` | 404 | IdentyClaw Passport not found |\n| `INVALID_TOKEN_ID` | 400 | Invalid token ID format |\n\n### HOLA Errors\n\nHTTP failures from `/api/testhola` and early validation on `/api/identity/verify` use these **`error.code`** values (HOLA lane — **base32** line signature, **HOLA nonce** from `GET /api/holanonce16ts`, ISO timestamp from that nonce response in the line):\n\n| Code | Status | Description |\n|------|--------|-------------|\n| `HOLA_VALIDATION_FAILED` | 400 | Shape, envelope, transport lint, format, fields, token id, nonce hex, checksum, etc. Use `error.details.reasonCode` for the specific fault. |\n| `HOLA_TIMESTAMP_INVALID` | 400 | HOLA line timestamp not valid ISO-8601, or outside allowed freshness window on `/api/testhola`. |\n| `HOLA_SIGNATURE_INVALID` | 400 | HOLA line signature verification failed on `/api/testhola`; peer verify often returns HTTP 200 with `failureReasons`. |\n| `HOLA_RESPONSE_FAILED` | 400 | Server could not build outbound test HOLA (`/api/testhola` only) |\n\nPeer verification outcomes (`verified`, `failureReasons`) on `POST /api/identity/verify` are documented in [HOLA agent authentication](hola-agent-authentication.md).\n\n### Login (JWT) verification errors\n\n`POST /api/login` credential failures (HTTP 401 when silent login is off) use **login-lane** codes — not `HOLA_*`. Full list: [login-authentication.md — Machine-readable login errors](login-authentication.md#machine-readable-login-errors).\n\n| Code | Status | Description |\n|------|--------|-------------|\n| `LOGIN_CHALLENGE_TIMESTAMP_INVALID` | 401 | Login challenge Unix `timestamp` rejected; must align with **login challenge pair** from `GET /api/login/timestamp`. |\n| `LOGIN_BASE64URL_SIGNATURE_INVALID` | 401 | **base64url login signature** did not verify over UTF-8 **login signing payload** (`roditid` or `accountid` + canonical `timestamp_iso` from that challenge). |\n| `WEBHOOK_SIGNATURE_INVALID` | 401 | Webhook Ed25519 verification failed (outbound webhooks; not returned from `POST /api/login`). |\n\nOther chain or policy outcomes on login (`RODIT_NOT_FOUND`, `RODIT_NOT_LIVE`, …) are listed in the same login guide section.\n\n## Versioning\n\nSee **[versioning.md](versioning.md)** — HTTP API release in swagger; RODiT JSON-LD `version` only via MCP from chain; `did:rodit` has no separate version.\n\n**HTTP API release** — only [`api-docs/swagger.json`](../api-docs/swagger.json) `info.version`. Surfaces: `GET /`, `GET /openapi.json`, MCP health/service info. Logged at boot as `apiReleaseVersion` in the configuration snapshot. Different **development** vs **main** API versions are done by committing different swagger on each branch (not via `config/development.json`). CI: `npm run validate:version`.\n\n`X-API-Version` is **not** implemented.\n\n---\n\n## Next Steps\n\n- [API Login Authentication](login-authentication.md)\n- [HOLA Protocol (Inter-Agent)](hola-agent-authentication.md)\n- [Understand token metadata](token-metadata.md)\n- [View JSON-LD integration](jsonld-metadata.md)\n- [Return to main guide](skills.md)\n- [OpenAPI spec](https://api.identyclaw.com/openapi.json)\n","requestId":"afd81228b33da9b088b1e83ef43fc61b"}